Usando named_scope con un recuento de los niños modelos
-
04-10-2019 - |
Pregunta
Tengo un objeto padre sencilla tener muchos hijos. Estoy tratando de encontrar la manera de utilizar un ámbito con nombre para traer de vuelta sólo los padres con los números concretos de los niños.
¿Es esto posible?
class Foo < ActiveRecord::Base
has_many :bars
named_scope :with_no_bars, ... # count of bars == 0
named_scope :with_one_bar, ... # count of bars == 1
named_scope :with_more_than_one_bar, ... # count of bars > 1
end
class Bar < ActiveRecord::Base
belongs_to :foo
end
Estoy esperando para hacer algo como Foo.with_one_bar
Yo podría escribir métodos de la clase padre para algo como esto, pero prefiero tener el poder del alcance de nombre
Solución
class Foo < ActiveRecord::Base
has_many :bars
# I don't like having the number be part of the name, but you asked for it.
named_scope :with_one_bar, :joins => :bars, :group => "bars.foo_id", :having => "count(bars.foo_id) = 1"
# More generically...
named_scope :with_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) = ?", n]}}
named_scope :with_gt_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) > ?", n]}}
end
Llamado de esta manera:
Foo.with_n_bars(2)
Otros consejos
Yo usaría el href="http://railscasts.com/episodes/23-counter-cache-column" rel="nofollow noreferrer"> contador caché
de lo que necesita demasiado cambio en el que Ahora el recuento de Sus named_scopes luego tener también tener este aspecto: De esta manera se puede ahorrar Tengo esta idea de ver el Railscast acerca caché contador: http: // Railscasts. com / episodios / 23-contra-cache-columna * ¿Qué hay de nuevo en Active Record [4 Rieles Cuenta atrás para 2013] class AddBarCount < ActiveRecord::Migration
def self.up
add_column :foos, :bars_count, :integer, :default => 0
Foo.reset_column_information
Foo.all.each do |p|
p.update_attribute :bars_count, p.bars.length
end
end
def self.down
remove_column :foos, :bars_count
end
end
Bar
modelo como este: class Bar < ActiveRecord::Base
belongs_to :foo, :counter_cache => true
end
bars
se almacena en caché en el modelo foo
, que acelerará sus consultas para el recuento de bars
. #rails 2
named_scope :with_no_bars, :conditions => { :bars_count => 0 }
named_scope :with_one_bar, :conditions => { :bars_count => 1 }
named_scope :with_more_than_one_bar, :conditions => ["bars_count > 1"]
#rails 3 & ruby 1.9+
scope :with_no_bars, where(bars_count: 0)
scope :with_one_bar, where(bars_count: 1)
scope :with_more_than_on_bar, where("bars_count > 1")
#rails 4* & ruby 1.9+
scope :with_no_bars, -> { where(bars_count: 0) }
scope :with_one_bar, -> { where(bars_count: 1) }
scope :with_more_than_one_bar, -> { where("bars_count > 1") }
bars
conteo de tiempo para cada foo
cada vez que realice una solicitud de este tipo.