Carriles: Con los modelos A has_many B belongs_to C retorno A, donde B pertenece a C y B es la más reciente creación de una determinada?

StackOverflow https://stackoverflow.com/questions/2247257

Pregunta

tengo tres modelos A, B, y C, donde A has_many B; B belongs to C y B has a created_on timestamp. C has_many A a B.

Quiero volver todos A, donde A tiene un B que pertenece a C y B, donde B es la más reciente creación para que A.

I puede hacer esto con un bucle método. ¿Es posible hacerlo únicamente con named_scopes ?, o es alguna otra manera elegante / eficiente?

Según la petición para ejemplos del mundo real (TM) A, B y C puede ser imaginado como, por ejemplo, animales domésticos (A), PetsName (B), y los nombres de (C). PetsNames se les da a los animales domésticos en un momento determinado, y cualquier Nombre dado se puede dar a muchos animales domésticos. Cualquier animal doméstico puede tener muchos nombres (a: a través de la relación). Para un nombre dado quiero todos de los Animales en la que ese nombre es el Petname de más reciente creación para que el PET. La llamada puede ser algo como @name.pets.most_recently_named_as

¿Fue útil?

Solución

La forma de hacer esto Carriles es un ámbito con nombre en las mascotas.

Algo como esto:

class Pets
  has_many :pet_names
  has_many :names, :through => :pet_names

  named_scope :with_current_name, lambda {|name| 
    { :joins => "JOIN (pet_names pna, names) " +
        "ON (pna.pet_id = pets.id AND pna.name_id = names.id) " +
        "LEFT JOIN pet_names pnb " +
        "ON (pnb.pet_id = pets.id AND pna.created_at < pnb.created_at)", 
      :conditions => ["pnb.id IS NULL AND names.id = ? ", name]
    }
  }
end

Pets.with_current_name(@name)
@name.pets.with_current_name(@name)

Para mantener el nombre Centric cosas que siempre se podía definir un método en C / nombre que invoca el ámbito con nombre.

Siempre se puede hacer

class Name < ActiveRecord::Base
  has_many :pet_names
  has_many :pets, :through => :pet_names

  def currently_named_pets
    Pets.with_current_name(self)
  end
end

y

@name.currently_named_pets

Es una muy complicada unión. Lo cual es un indicador de que probablemente debería debería replantearse la forma en que almacena esta información. ¿Por qué es tan importante que los nombres de estar en una mesa separada?

Usted puede ser mejor hacer algo como esto:

Después de añadir columnas name y old_name para mascotas:

class Pet < ActiveRecord::Base
  serialize :old_name, Array
  def after_initialization 
    @old_name ||= []
  end

  def name= new_name
    self.old_name << new_name
    self.name = new_name
  end

  named_scope :with_name, lambda {|name|
     { :conditions => {:name => name}}
  }
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top