Aquí están mis modelos ActiveRecord, con Rails 3.2:Relación sobre el alcance de ActiveRecord
class User < ActiveRecord::Base
has_one :criterion
has_many :user_offer_choices
end
class Offer < ActiveRecord::Base
has_many :user_offer_choices
def seen
user_offer_choices.where(seen: true)
end
def accepted
user_offer_choices.where(accepted: true)
end
end
class Criterion < ActiveRecord::Base
belongs_to :user
end
class UserOfferChoice < ActiveRecord::Base
belongs_to :user
belongs_to :offer
end
quiero conseguir todos los criterios de los usuarios que han visto una oferta. Algo así como:
Offer.find(11).seen.users.criterions
pero no sé cómo a ella con ActiveRecord
Sé que puedo hacer algo como:
Criterion.joins(user: { user_offer_choices: :offer }).where(user: { user_offer_choices: {accepted: true, offer_id: 11} })
Pero yo quiero ser capaz de usar mis alcances en las ofertas (visto & aceptado). Entonces, ¿cómo puedo hacerlo?
Editar: he encontrado lo que estaba buscando, el método de combinación de Arel: http://benhoskin.gs/2012/07/04/arel-merge-a-hidden-gem
No quiero usar el mapa (u otro método Enum), porque es simple que Ruby y ActiveRecord no generarán SQL. –
¿Por qué es importante usar SQL en lugar de mapa? Eso me parece un requisito artificial arbitrario. Si lo notas, te demostré cómo pasar de anidar dos llamadas a mapa (lo cual es engorroso y difícil de leer) a una solución que se deshace de un mapa y usa SQL y tus ámbitos. Puede intentar extender esa técnica, pero creo que esa solución será engorrosa. (Más sobre el mapa vs SQL en el siguiente comentario).) –
Usar el mapa tiene un inconveniente: pasa por la colección, pero luego hace una llamada a la base de datos en el bucle para eliminar la referencia de la asociación. Cuando cambié el mapa de elección por el has-many-through formulé una llamada SQL para el objeto Oferta ofrecido y creamos la unión para nosotros. Sin embargo, no me preocuparía el rendimiento hasta que determinamos que toda la respuesta web tomó demasiado tiempo. –