How to model a Question and Answer data structure in ActiveRecord?

Viewed 418

This feels like it should be super simple, but for the life of me I haven't been able to get it right.

In my application, I want to have Questions and Answers.

A Question can only have 1 Answer, but an Answer can be used for many Questions.

For example.

Question Table Data

  1. "Two plus Two equals?"
  2. "Number of sides to a square?"

Answer Table Data

  1. Four

Both Questions only have 1 Answer, but the Answer record can be used for both Questions.

I thought maybe this would work ::

rails g resource question verbiage:string answer:references

but then I have to put a belongs_to :answer on the Question model and that doesn't seem right.

It feels like it should be possible to do something like ::

Question.first.answer # returns the single answer

Answer.first.questions # returns all of the Questions where this record is the Answer

Can anyone educate me on the proper way to model this in ActiveRecord?

3 Answers

If you don't want to use demir's answer of

  • question belongs_to answer
  • answer has_many question

You'll have to

  • Make a QuestionAnswer join table
  • QuestionAnswer belongs_to question
  • QuestionAnswer belongs_to answer
  • question has_one question_answers
  • answer has_many question_answers

Then

  • question has_one :answer through :question_answer source :answer
  • answer has_many :question through :question_answer source :question

Ex. https://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one

For example, it makes more sense to say that a supplier owns an account than that an account owns a supplier. This suggests that the correct relationships are like this

You need has_many assosiaction. I'm gonna use scaffold for this.

  1. Create Answer:

    rails g scaffold Answer value:string
    
  2. Create Question:

    rails g scaffold Question verbiage:string answer:references
    
  3. Run rails db:migrate

  4. Create assosiactions.

    class Answer < ApplicationRecord
      has_many :questions
    end
    
    class Question < ApplicationRecord
      belongs_to :answer
    end
    

This really depends on what the requirements are. In most cases you actually need a join table:

class Question
  has_many :options
  has_many :answers, through: :options
end

class Option
  belongs_to :question
  belongs_to :answer
end

class Answer
  has_many :options
  has_many :questions, through: :options
end
answers = [Answer.create(verbiage: 'Dailey'), Answer.create(verbiage: 'Once a week'), Answer.create(verbiage: 'Never')]
question = Question.create(verbiage: 'How often do you drink milk?', answers: answers)
question_2 = Question.create(verbiage: 'How often do you excercise?', answers: answers)

If the question is has a correct answer you can use a separate association which is a direct link to the the answers table:

class Question
  has_many :options
  has_many :answers, through: :options
  belongs_to :correct_answer, class_name: 'Answer'
end

Or you can add a boolean column to the options table if their can be multiple correct answers.

class Question
  has_many :options
  has_many :answers, through: :options
  has_many :correct_answers, through: :options, 
                             class_name: 'Answer',
                             -> { where(options: { correct: true }) }
end
Related