through rails many has_one has_many has_and_belongs_to_many has example belongs and active ruby-on-rails-3 activerecord has-many

ruby on rails 3 - has_one - Utilice un ámbito de forma predeterminada en una relación Rails has_many



rails has_many through example (2)

Acabo de sumergirme en ActiveRecord y no parece que esto pueda lograrse con la implementación actual de has_many . Puedes pasar un bloque a :conditions pero esto se limita a devolver un hash de condiciones, no cualquier tipo de cosas de tipo arel.

una forma muy simple y transparente de lograr lo que desea (lo que creo que está tratando de hacer) es aplicar el alcance en tiempo de ejecución:

# foo.rb def bars super.baz end

esto está lejos de lo que estás pidiendo, pero podría funcionar;)

Digamos que tengo las siguientes clases

class SolarSystem < ActiveRecord::Base has_many :planets end class Planet < ActiveRecord::Base scope :life_supporting, where(''distance_from_sun > ?'', 5).order(''diameter ASC'') end

Planet tiene un alcance life_supporting y SolarSystem life_supporting SolarSystem has_many :planets . Me gustaría definir mi relación has_many para que cuando pregunto a un sistema solar_system por todos los planets asociados, el alcance de life_supporting se aplique automáticamente. Esencialmente, me gustaría solar_system.planets == solar_system.planets.life_supporting .

Requisitos

  • No quiero cambiar el scope :life_supporting en Planet para

    default_scope where(''distance_from_sun > ?'', 5).order(''diameter ASC'')

  • También me gustaría evitar la duplicación al no tener que agregar a SolarSystem

    has_many :planets, :conditions => [''distance_from_sun > ?'', 5], :order => ''diameter ASC''

Gol

Me gustaría tener algo como

has_many :planets, :with_scope => :life_supporting

Editar: la vuelta al trabajo

Como dijo @phoet, puede que no sea posible alcanzar un alcance predeterminado usando ActiveRecord. Sin embargo, he encontrado dos posibles soluciones alternativas. Ambos evitan la duplicación. El primero, mientras que es largo, mantiene legibilidad y transparencia obvias, y el segundo es un método de tipo colaborador cuya salida es explícita.

class SolarSystem < ActiveRecord::Base has_many :planets, :conditions => Planet.life_supporting.where_values, :order => Planet.life_supporting.order_values end class Planet < ActiveRecord::Base scope :life_supporting, where(''distance_from_sun > ?'', 5).order(''diameter ASC'') end

Otra solución que es mucho más limpia es simplemente agregar el siguiente método a SolarSystem

def life_supporting_planets planets.life_supporting end

y para usar solar_system.life_supporting_planets donde quiera que use solar_system.planets .

Ninguno de los dos responde la pregunta, así que los puse aquí como una solución alternativa si alguien más se encuentra con esta situación.


En Rails 4, las Associations tienen un parámetro de scope opcional que acepta una lambda que se aplica a la Relation (consulte el documento para ActiveRecord::Associations::ClassMethods )

class SolarSystem < ActiveRecord::Base has_many :planets, -> { life_supporting } end class Planet < ActiveRecord::Base scope :life_supporting, -> { where(''distance_from_sun > ?'', 5).order(''diameter ASC'') } end

En Rails 3, la solución alternativa where_values veces se puede mejorar utilizando where_values_hash que maneja mejores ámbitos donde las condiciones se definen por multiple where o por un hash (no es el caso aquí).

has_many :planets, conditions: Planet.life_supporting.where_values_hash