Domanda

Voglio trovare record su una combinazione di create_on >= una data E un nome IN un elenco di nomi.

Per ">=" dovrei usare la condizione sql.Per "IN" dovrei utilizzare un hash di condizioni in cui la chiave è :name e il valore è l'array di nomi.

C'è un modo per combinare i due?

È stato utile?

Soluzione

È possibile utilizzare ambiti denominati nei rail 2.1 e versioni successive

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

allora puoi farlo

Test.created_after_2005.named_fred

Oppure puoi dare a name_scope un lambda che ti permetta di passare argomenti

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

allora puoi farlo

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

Altri suggerimenti

Se stai utilizzando una versione precedente di Rails, la query di Honza è simile, ma devi aggiungere parentesi per le stringhe che vengono inserite nella condizione IN:

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

L'uso di IN può essere un miscuglio:è più veloce per i numeri interi e più lento per un elenco di stringhe.Se ti ritrovi a utilizzare un solo nome, utilizza sicuramente un operatore uguale:

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

La cosa bella dei name_scope è che funzionano anche sulle raccolte:

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

@post = Post.published

@posts = current_user.posts.published

Per ulteriori informazioni sugli scope_nomi vedere L'annuncio di Ryan e il Railscast su 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

Se hai intenzione di passare variabili ai tuoi ambiti devi usare un lambda.

Puoi concatenare il where clausola:

Person.where(name: ['foo', 'bar', 'baz']).where('id >= ?', 42).first

Gli ambiti nominati già proposti vanno piuttosto bene.Il modo classico per farlo sarebbe:

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

Penso che utilizzerò semplici cercatori AR o Cercagasmo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top