belongs_to a través de asociaciones

Dadas las siguientes asociaciones, necesito hacer referencia a la Question que se adjunta una Choice desde el modelo de Choice . He estado intentando usar belongs_to :question, through: :answer para realizar esta acción.

 class User has_many :questions has_many :choices end class Question belongs_to :user has_many :answers has_one :choice, :through => :answer end class Answer belongs_to :question end class Choice belongs_to :user belongs_to :answer belongs_to :question, :through => :answer validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ] end 

estoy obteniendo

NameError constante no inicializada User::Choice

cuando bash hacer current_user.choices

Funciona bien, si no incluyo

 belongs_to :question, :through => :answer 

Pero quiero usar eso porque quiero poder hacer validates_uniqueness_of

Probablemente estoy pasando por alto algo simple. Cualquier ayuda sería apreciada.

Una asociación belongs_to no puede tener una opción :through . Es mejor que guarde en caché el question_id en Choice y agregue un índice único a la tabla (especialmente porque validates_uniqueness_of es propenso a las condiciones de carrera).

Si es paranoico, agregue una validación personalizada a Choice que confirme que la respuesta question_id coincide, pero parece que el usuario final nunca debería tener la oportunidad de enviar datos que crearían este tipo de desajuste.

También puedes delegar:

 class Company < ActiveRecord::Base has_many :employees has_many :dogs, :through => :employees end class Employee < ActiveRescord::Base belongs_to :company has_many :dogs end class Dog < ActiveRecord::Base belongs_to :employee delegate :company, :to => :employee, :allow_nil => true end 

Simplemente use has_one lugar de belongs_to en su :though , así:

 class Choice belongs_to :user belongs_to :answer has_one :question, :through => :answer end 

No relacionado, pero me resistiría a usar validates_uniqueness_of en lugar de utilizar una restricción única adecuada en su base de datos. Cuando haces esto en ruby ​​tienes condiciones de carrera.

Simplemente podría usar has_one en lugar de belongs_to :

 has_one :question, :through => :answer 

Mi enfoque era hacer un atributo virtual en lugar de agregar columnas de base de datos.

 class Choice belongs_to :user belongs_to :answer # ------- Helpers ------- def question answer.question end # extra sugar def question_id answer.question_id end end 

Este enfoque es bastante simple, pero viene con compensaciones. Requiere que Rails cargue la answer de la base de datos, y luego question . Esto puede optimizarse más tarde cargando c = Choice.first(include: {answer: :question}) las asociaciones que necesita (es decir, c = Choice.first(include: {answer: :question}) ); sin embargo, si esta optimización es necesaria, entonces la respuesta de stephencelis probablemente sea una mejor decisión de rendimiento.

Hay un momento y lugar para ciertas elecciones, y creo que esta opción es mejor cuando se crean prototipos. No lo usaría para el código de producción a menos que supiera que era para un caso de uso infrecuente.

Parece que lo que quieres es un usuario que tenga muchas preguntas.
La pregunta tiene muchas respuestas, una de las cuales es la elección del usuario.

¿Es esto lo que buscas?

Yo modelaría algo así en esta línea:

 class User has_many :questions end class Question belongs_to :user has_many :answers has_one :choice, :class_name => "Answer" validates_inclusion_of :choice, :in => lambda { answers } end class Answer belongs_to :question end 

Entonces no puedes tener el comportamiento que quieres, pero puedes hacer algo que te apetezca. Desea poder hacer Choice.first.question

lo que hice en el pasado es algo como esto

 class Choice belongs_to :user belongs_to :answer validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ] ... def question answer.question end end 

De esta manera, ahora puede llamar a la pregunta sobre la Elección

El has_many :choices crea una asociación llamada choices , no choice . Intenta usar current_user.choices lugar.

Consulte la documentación de ActiveRecord :: Associations para obtener más información acerca de la magia de has_many .