Question

Je souhaite rechercher des enregistrements dans une combinaison de created_on > = quelque date ET nom dans une liste de noms.

Pour " > = " Je devrais utiliser condition SQL. Pour " IN " Je devrais utiliser un hachage de conditions où la clé est: nom et la valeur est le tableau de noms.

Existe-t-il un moyen de combiner les deux?

Était-ce utile?

La solution

Vous pouvez utiliser des étendues nommées dans les rails 2.1 et supérieurs

Class Test < ActiveRecord::Base
  named_scope :created_after_2005, :conditions => "created_on > 2005-01-01"
  named_scope :named_fred, :conditions => { :name => "fred"}
end

alors vous pouvez faire

Test.created_after_2005.named_fred

Ou vous pouvez donner à named_scope un lambda vous permettant de passer des arguments

Class Test < ActiveRecord::Base
  named_scope :created_after, lambda { |date| {:conditions => ["created_on > ?", date]} }
  named_scope :named, lambda { |name| {:conditions => {:name => name}} }
end

alors vous pouvez faire

Test.created_after(Time.now-1.year).named("fred")

Autres conseils

Si vous utilisez une ancienne version de Rails, la requête de Honza est proche, mais vous devez ajouter des parenthèses pour les chaînes placées dans la condition IN:

Person.find(:all, :conditions => ["created_at > ? AND name IN (?)", date, names])

Utiliser IN peut être un sac mélangé: c'est le plus rapide pour les entiers et le plus lent pour une liste de chaînes. Si vous utilisez un seul nom, utilisez un opérateur égal à:

Person.find(:all, :conditions => ["created_at > ? AND name = ?", date, name])

Ce qui est intéressant avec named_scopes, c'est qu'ils travaillent aussi sur les collections:

class Post < ActiveRecord::Base
  named_scope :published, :conditions => {:status => 'published'}
end

@post = Post.published

@posts = current_user.posts.published

Pour plus d'informations sur named_scopes, voir Annonce de Ryan et le Railscast sur named_scopes

class Person < ActiveRecord::Base
  named_scope :registered, lambda { |time_ago| { :conditions => ['created_at > ?', time_ago] } }
  named_scope :with_names, lambda { |names| { :conditions => { :names => names } } }
end

Si vous voulez transmettre des variables à vos portées, vous devez utiliser un lambda.

Vous pouvez chaîner la clause :

Personne ailleurs (nom: ['foo', 'bar', 'baz']). where ('id > =?', 42) .first

Les champs nommés déjà proposés sont plutôt bien. La façon classique de le faire serait:

names = ["dave", "jerry", "mike"]
date = DateTime.now
Person.find(:all, :conidtions => ["created_at > ? AND name IN ?", date, names])

Je pense que je vais utiliser des détecteurs AR simples ou Searchgasm .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top