Принадлежит через ассоциации
Учитывая следующие ассоциации, мне нужно ссылаться на Question
, что a Choice
подключается через модель Choice
. Я пытаюсь использовать belongs_to :question, through: :answer
для выполнения этого действия.
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
Я получаю
NameError неинициализированная константа User::Choice
когда я пытаюсь сделать current_user.choices
Он отлично работает, если я не включаю
belongs_to :question, :through => :answer
Но я хочу использовать это, потому что хочу иметь возможность validates_uniqueness_of
Я, вероятно, не замечаю ничего простого. Любая помощь будет оценена.
Ответы
Ответ 1
A belongs_to
ассоциация не может иметь опцию :through
. Вам лучше кэшировать question_id
на Choice
и добавить уникальный индекс в таблицу (особенно потому, что validates_uniqueness_of
подвержен условиям гонки).
Если вы параноик, добавьте специальную проверку на Choice
, которая подтверждает соответствие ответа question_id
, но похоже, что конечный пользователь никогда не должен иметь возможность отправлять данные, которые могли бы создать такой вид несоответствия.
Ответ 2
Вы также можете делегировать:
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
Ответ 3
Просто используйте has_one
вместо belongs_to
в :though
, например:
class Choice
belongs_to :user
belongs_to :answer
has_one :question, :through => :answer
end
Несвязанный, но я бы не решался использовать validates_uniqueness_of вместо использования правильного уникального ограничения в вашей базе данных. Когда вы делаете это в рубине, у вас есть условия гонки.
Ответ 4
Вы можете просто использовать has_one
вместо belongs_to
:
has_one :question, :through => :answer
Ответ 5
Мой подход заключался в создании виртуального атрибута вместо добавления столбцов базы данных.
class Choice
belongs_to :user
belongs_to :answer
# ------- Helpers -------
def question
answer.question
end
# extra sugar
def question_id
answer.question_id
end
end
Этот подход довольно прост, но поставляется с компромиссами. Для этого требуется Rails для загрузки answer
из db, а затем question
. Это может быть оптимизировано позже, если вы захотите загрузить нужные вам ассоциации (т.е. c = Choice.first(include: {answer: :question})
), однако, если эта оптимизация необходима, то ответ stephencelis, вероятно, является лучшим решением производительности.
Там время и место для определенных выборов, и я думаю, что этот выбор лучше при прототипировании. Я бы не использовал его для производственного кода, если бы не знал, что это было для редкого варианта использования.
Ответ 6
Похоже на то, что вы хотите, это пользователь, у которого много вопросов.
У Вопроса много ответов, одним из которых является Пользовательский выбор.
Это то, что вам нужно?
Я бы смоделировал что-то вроде этого в следующих строках:
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
Ответ 7
Таким образом, у вас не может быть поведения, которое вы хотите, но вы можете сделать что-то, что ему нравится. Вы хотите иметь возможность Choice.first.question
то, что я делал в прошлом, это что-то вроде этого
class Choice
belongs_to :user
belongs_to :answer
validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
...
def question
answer.question
end
end
таким образом вы можете теперь вызывать вопрос на Выбор
Ответ 8
has_many :choices
создает ассоциацию с именем choices
, а не choice
. Вместо этого используйте current_user.choices
.
Информацию о магии has_many
см. в документации ActiveRecord:: Associations.