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

¿Fue útil?

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é

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

de lo que necesita demasiado cambio en el que Bar modelo como este:

class Bar < ActiveRecord::Base
  belongs_to :foo, :counter_cache => true
end

Ahora el recuento de bars se almacena en caché en el modelo foo, que acelerará sus consultas para el recuento de bars.

Sus named_scopes luego tener también tener este aspecto:

#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") }

De esta manera se puede ahorrar bars conteo de tiempo para cada foo cada vez que realice una solicitud de este tipo.

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]

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top