How to create model with multiple fields for answers? - ruby-on-rails

I created a model Question with question:string and answer:string.
I want to create questions with multiple answers(1-30), but in the db there are only two tables(one for question, one for answer).
For example, I have a field for questions and a lot of fields for answers which I can add dynamically. After that I want to display question and all answers that belongs to it. How do I do this?

You are going to want to separate those concerns.
What I mean is:
Make a separate Answer model and migration so you can create an 'answers' table in your database. That way you can put this in your Question model:
has_many :answers
and in your Answer model:
belongs_to :question
I'd say this is the proper way to achieve what you are looking for.

Define Question and Answer model as
class Question < ActiveRecord::Base
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :question
end
RUn migration
rails g migration addQuestionIdToAnswers question_id:integer
So now you can say question.answers and this will give you all the answers which belong to that question. as you have question_id field on every `answer'
You can make calls like
answer.question # return the question the answer `belongs_to`
question.answers # return all the answers the question `has_many`

Related

Creating and querying questions/answers in Ruby-on-rails

We're creating a Ruby-on-rails application where the user is presented with a series of questions where they can give multiple different answers to one question. For now it's it's toggles but in the future we might be interested in doing freeform text as well. Each group of answers is connected to a pin on a map.
For now, each pin simply has a coplumn of questions and answers, which is a hash, but we'd really like to make it nicer and more scaleable. Some of the queries we'd like to do are e.g. count the amount of people that have answered 'It's quiet here' to the question 'Why do you come here?'
For now, I thought of the following models:
# pin.rb
class Pin < ApplicationRecord
has_many :questions
end
# question.rb
class Question < ApplicationRecord
belongs_to :pin
has_many :answers
end
# answer.rb
class Answer < ApplicationRecord
belongs_to :questions
end
Is this the right way of approaching this? I'd then fill seed.rbwith the questions and possible corresponding answers.
What's the best way of then creating new objects or rows, when a user answers a given question?
This looks good to me. If your Answer defines possible choices for a question, then for storing user answers/selections, you'll have to create another model/table
class UserAnswer < ApplicationRecord
belongs_to :question
belongs_to :answer
# attribute :value
end

Scaling large data in Rails4

I'm making a Q&A site. I have three models for now:
Question
Answer
User
Both Question and Answer can be voted for, so I need a way to store who voted on the model, to prevent multiple votes on one model by same user.
Would be a good idea to create a vote model? Where either the question_id or the answer_id will be empty in each. I'm afraid that this will create a lot of junk and slow the application down.
My other idea is to store the user_id in a hash in the Answer and in the Question.
If the user is already present in the hash it prevents voting. Or store the answer and question ids in the user.
What would be the Rails4 way to be fast but store most user interactions in models. What can be KISS, DRY and fast?
You should use a polymorphic model if you have multiple models the Vote can refer to.
class Vote < ActiveRecord::Base
belongs_to :voteable, polymorphic: true
end
class Question < ActiveRecord::Base
has_many :votes, as: :voteable
end
class Answer < ActiveRecord::Base
has_many :votes, as: :voteable
end
I don't think you have to worry about the speed for quite a while if you use indexes on the associations. Just put this snippet in a migration and you should be good to go!
add_index :votes, [:voteable_name, :voteable_id]

How to create voting to a multiple choice application using ruby on rails

I am working on a multiple choice question and answer application using Ruby on Rails and I have the following model.
class User < ActiveRecord::Base
has_many :questions
end
class Question < ActiveRecord::Base
belongs_to :user
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :question
has_many :votes
end
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :answer
end
My problem is a user can choose all the answers.
How can I fix it so that it updates to the new answer?
For example, a has 5 votes and b 3 votes.
User clicks on a and a increments to 6 votes, same user comes back and clicks on b, a decrements back to 5 votes and b increments to 4 votes.
My first guess is that I need to add another model for example, user_choice with user_id and vote_id to track the previous answer.
You have your answer within the models. Just add a point system to the question model.
Under the question model,
def points
self.answers.count
end
Or, if answers have different values attached to them, make points an attribute of the answer instances.
def points
self.answers.pluck(:points).inject(:+)
end
This will sum up all the points from an answer belonging to a question, which allows you to order the questions by point count.
However, I am assuming you will need a Choice model for a question, unless that is in fact what the votes are for.
question has_many choices
choices belong_to question, etc.
I'm not sure what you mean when you say:
How can I fix it so that it updates to the new answer?
EDIT
Er, okay so you just need exactly what I mentioned earlier. A vote is really just the number of times an answer has been chosen.
If your problem is that users can choose more than 1 answer, it is likely that you should implement view based validations via javascript, or better yet, just disable their ability to select multiple choices, which if you were using a select tag, is actually the default. You must've added
multiple: true
in the select tag options for the user to select multiple entries.
On the backend, you can do this:
class Choice < ActiveRecord::Base
validates_uniqueness_of :user_id, scope: [:question_id, :answer_id]
end

How to connect models in a form without nesting?

I did a lot of searches for this problem and watched quite a few tutorials (e.g railscast: nested model form) but I'm afraid it's not the right solution to my problem.
I want to collect data for a theory. This theory has many questions to be answered on distinctive cards. I always want to display all questions (on all cards), but the answers may vary, depending on each card. Therefor I need to catch the question_id and card_id, but deep nesting and catching the id by params would be quite a pain. Does anyone know a better solution for my problem?
Here are my models:
theory.rb
class Theory < ActiveRecord::Base
has_many :cards
has_many :questions
card.rb
class Card < ActiveRecord::Base
belongs_to :theory
has_many :answers
has_many :questions (Do I need this here - I always want to display all questions?)
question.rb
class Question < ActiveRecord::Base
belongs_to :theory
has_many :answers
answer.rb
class Answer < ActiveRecord::Base
belongs_to :card
belongs_to :question
Thank you a lot for your help!
The relationships between your models should not be determined by how they will be displayed on the screen. They should be determined by how they are actually related to each other.
I don't fully understand what theory/card are supposed to represent so I can't tell you what relationships need to exist, but I can have a stab at at it :
It seems to me as though a card represents the answers for a single person that relate a to a specific Theory? If so, then you don't need the "has_many :questions" because the card only has answers. Also, each answer links to a question so you can "get" to the questions through the answers. You could add a "has_many :questions, :through=>:answers" to the Card model if you really wanted the list of questions for a card.
If each card can have a different set of questions added to it before any answering is done, then you will need the "has_many :questions", but if all the questions are on each card then you won't need it.
Update in response to your comments below :
One way is to add the answers to the card by building them up in the controller:
#card = Card.find 2
#theory = Theory.find 1
#theory.questions.each do |question|
#card.answers.build :question=>question
end
Then in your view do something like this (this is HAML) :
= form_for #card do |f|
-#card.answers.each do |answer|
=f.fields_for answer do |answer_form|
=answer_form.hidden_field :question_id
%p=answer.question.full_question
%p=answer_form.text_field :input
This is using nested form attributes, so to get it to work with your Card model you'll have to add this to it :
class Card < ActiveRecord::Base
..
accepts_nested_attributes_for :answers
..
end

HABTM, or multiple belongs_to?

I'm teaching myself Rails, and as a test project I'm mocking up a simple question/answer app similar to stackoverflow.
In my simplified version I have:
questions
answers
users (the authors of questions and answers)
I get that answers belong to questions.
What's the proper relationship between users and questions?
What's the proper relationship between users and answers?
It would seem to me that questions and answers don't really "belong_to" users, and instead questions and answers "has_one user" (the author). But that doesn't seem right either, because then the user would "belong_to question" and "belong_to answer".
Is HABTM the answer between the three classes?
Lots of people get stuck on this relationship thing, don't they? :)
Is HABTM the answer between the three classes?
No. You don't need HABTM in any of these relationships.
What's the proper relationship between users and questions?
What's the proper relationship between users and answers?
In both of these cases, it is a one-to-many relationship: A user has many questions and a user has many answers.
From a logical point of view, consider this: One question can never be authored by multiple users and one answer cannot be authored by multiple users. As such, it's not a many-to-many relationship.
In this case, your classes should be set up like this:
class User < ActiveRecord::Base
has_many :questions
has_many :answers
end
class Question < ActiveRecord::Base
belongs_to :user
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :user
belongs_to :question
end
If you, on the other hand, have a tagging system similar to StackOverflow, you'll need a HABTM relationship. One question can have many tags, while one tag can have many questions. As a prime example, your post has three tags (ruby-on-rails, habtm, foreign-key-relationship), while the ruby-on-rails tag presently have 8,546 questions.
Belongs_to is a strange name. Figure out your has_many relationships and just put belongs_to on the other side and don't worry about the semantics of it.

Resources