2010-08-15 7 views
2

J'ai une méthode qui fait appel paginé find comme ..utilisant lambda trouver dans des rails

coll = paginate(:all, lambda {{:conditions => ['status = ? AND expires < ?', 'a', DateTime.now]}}, :select => Constants::POST_FIELDS, 
        :order => 'posts.ratings DESC', :include => [{:poster => :poster_friends}, :category], :per_page => Constants::LISTINGS_PER_PAGE, 
        :page => page) 

Lorsque cet appel exécute ignore simplement les conditions dans la requête générée.

Si j'essaie dans un named_scope je reçois une erreur comme ..

named_scope :featured_all, lambda {{:conditions => ['status = ? AND expires < ?', 'a', DateTime.now], order => 'posts.ratings DESC', :include => [{:poster => :poster_friends}, :category], 
      :select => Constants::POST_FIELDS}} 

L'erreur-champ nommé:

/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/hash/keys.rb:47:in `assert_valid_keys' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2101:in `with_scope' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:113:in `__send__' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:113:in `with_scope' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:174:in `method_missing' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:188:in `load_found' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:166:in `proxy_found' 
    /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:109:in `is_a?' 
    /usr/lib/ruby/gems/1.8/gems/hirb-0.3.1/lib/hirb/formatter.rb:78:in `determine_output_class' 
    /usr/lib/ruby/gems/1.8/gems/hirb-0.3.1/lib/hirb/formatter.rb:48:in `format_output' 
    /usr/lib/ruby/gems/1.8/gems/hirb-0.3.1/lib/hirb/view.rb:213:in `render_output' 
    /usr/lib/ruby/gems/1.8/gems/hirb-0.3.1/lib/hirb/view.rb:126:in `view_output' 

Pour # 1. Qu'est-ce que je fais de mal, pourquoi ignore-t-il les conditions?

Pour # 2 Pourquoi cette erreur? Et aussi, comment puis-je passer le paramètre: page et per_page pour limiter la requête dans le named_scope.

Merci

+1

Pourquoi vous envelopper les conditions dans un lambda? – jtbandes

+0

Afin que j'obtienne le DateTime.now correct. Si ce n'est pas le cas, cet appel ne renverra-t-il pas le DateTime.now, puisque le serveur a été démarré? – badnaam

+0

@badnaam: La seule différence en l'enveloppant dans un lambda et en l'appelant immédiatement serait que le temps retourné serait plus lent de quelques microsecondes pour tenir compte du temps pris par l'appel lambda lui-même. – Chuck

Répondre

1

Votre cas d'utilisation ne garantit pas un named_scope. Vous pouvez écrire un chercheur régulier comme suit:

coll = paginate(:select  => Constants::POST_FIELDS, 
       :conditions => ['status = ? AND expires < ?', 'a', DateTime.now], 
       :include => [{:poster => :poster_friends}, :category], 
       :order  => 'posts.ratings DESC', 
       :per_page => Constants::LISTINGS_PER_PAGE, 
       :page => page) 

La méthode paginate équivaut à all, de sorte que vous ne devez pas fournir le qualificatif de portée du jeu de résultats :all la méthode paginate.

La valeur de temps est calculée lors de l'exécution de la requête. Ceci est différent d'un named_scope, où vous devez utiliser un lambda pour le même effet.

Si vous devez utiliser le named_scope puis procédez comme suit:

named_scope :featured_all, lambda {{ 
       :select  => Constants::POST_FIELDS, 
       :conditions => ['status = ? AND expires < ?', 'a', DateTime.now], 
       :include => [{:poster => :poster_friends}, :category], 
       :order  => 'posts.ratings DESC' 
       }} 

Maintenant, vous pouvez utiliser le named_scope comme suit

Post.feature_all.paginate(:per_page => Constants::LISTINGS_PER_PAGE, 
          :page => page) 
+0

Merci, bon à savoir la valeur de temps est calculée lors de l'exécution de la requête! Le chercheur fonctionne très bien. La portée nommée s'est plantée avec un message d'erreur sql se plaignant de l'attribut invlid categories.id, je suppose qu'il y a une sorte de confusion dans la portée nommée si la clause: select contient un assocation.id ou toute autre colonne avec le même nom? J'ai: select => 'posts.id, categories.id' – badnaam

+0

Quel est le SQL imprimé avec le message d'erreur? –

+0

Vous devez utiliser un alias (par exemple: 'categories.id AS categories_id') en faisant référence aux tables jointes dans la clause' SELECT'. –

0

Votre champ nommé manque un : avant votre clé de commande. Cela pourrait exploser la portée nommée. Sinon, ça a l'air bien.

Cela dit, vous n'avez pas besoin d'utiliser un lambda pour obtenir des enregistrements pertinents à l'heure actuelle. Votre base de données fournit des méthodes similaires. Par exemple, si vous utilisez MySQL, vous pouvez utiliser:

named_scope(:featured_all, { 
    :conditions => "status = 'a' AND expires < UTC_TIMESTAMP()", 
    :order => 'posts.ratings DESC', 
    :include => [{:poster => :poster_friends}, :category], 
    :select => Constants::POST_FIELDS 
}) 

UTC_TIMESTAMP() est une fonction spécifique à MySQL qui retourne la date et l'heure UTC (qui Rails doit être le stockage de vos DateTimes comme déjà).

+0

Je préférerais ne pas utiliser de code spécifique db ici. Toute autre option ou suis-je bien sans le lambda? Vous avez raison à propos de: l'ordre. Merci! – badnaam

+0

Si vous souhaitez éviter le code spécifique à la base de données, vous devrez utiliser le lambda. Cela fonctionnera sans le lambda en développement, mais il restera bloqué en production, où les classes de modèles ne sont pas rechargées par requête. –

Questions connexes