has_many order by model and another table - ruby-on-rails

I have a Question model.
every question can have many answers. And answers have status id which is a number.
So: I have:
class Question < ActiveRecord::Base
has_many :answers, :order =>'status_cat_id'
Now, answers are related to users, and I want the order of answers to be first by status_is and then by user name.
So, when I'll call: #question.answers I will get the answers ordered first by status and then by the user name.
Is it possible to achieve that through the model?

The answer is:
has_many :answers, :include => :user, :order =>'status_cat_id, users.name'

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

Rails sort from model association

I have the following associations:
class Question < ApplicationRecord
belongs_to :shopper
has_many :question_messages, dependent: :destroy
end
class QuestionMessage < ApplicationRecord
belongs_to :question
belongs_to :shopper, optional: true
belongs_to :store, optional: true
end
As you can see from the associations above I have two different user types(store, shopper) that can create question messages. I have an index page for the shopper user where I want to sort his questions according to the last question message he created. I'm trying this with the following code:
#questions = Question.where(shopper_id: current_shopper)
.group(:id).joins(:question_messages)
.order('max(question_messages.created_at) asc')
The issue with this code is that it sorts the questions according to last questions messages created and not specifically the last question message created by the shopper. Any ideas on how to implement this so I can sort the questions according to the last question message that was created by the shopper?
Well if you want them to be sorted only by shopper's question messages then you need to apply the max only on question messages from that shopper:
Question.where(shopper_id: current_shopper)
.group(:id)
.joins(:question_messages)
.where(question_messages: {shopper_id: current_shopper })
.order('max(question_messages.created_at) asc')
The solution above will not return questions if the shopper doesn't have a QuestionMessage for it.
IF you need all questions regardless if the shopper has a question message pointing to the question, than you can use this:
Question.where(shopper_id: current_shopper)
.group(:id)
.joins("LEFT JOIN question_messages
ON question_messages.question_id = questions.id
AND question_messages.shopper_id = #{current_shopper.to_i}")
.order('max(question_messages.created_at) asc')

Use find to select attributes from joined tables

I have three tables,
QuestionSets
has_many :questions
Question
has_many :answers
Answers
Now the Answers table has a column called "actual_answer"
Now I wanted to do a find where I can get all the Answers with actual_answers equal to a specific value and belongs to a specific question_set.
I have this right now:
#questionSet= QuestionSet.find(params[:id])
#answers = Answer.find(:all, :conditions => ["actual_answer=?", SOMEACTUALANSWER])
answers_i_need = []
#answers.each do |answer|
if answer.question.question_set_id == #questionSet.id
answers_i_need << answer
end
end
Is there a BETTER way of doing this, as I'm expecting thousand array results and making a loop might not be a perfect way of doing it.
Thanks!
Why not use a has_many ... :through relation? Link to: guides
This way you can have:
QuestionSet
has_many :questions
has_many :answers, through: :questions
Question
has_many :answers
belongs_to :question_set
Answer
belongs_to :question
Then in your controller you have:
#questionSet= QuestionSet.find(params[:id])
answers_i_need = #questionSet.answers.where('actual_answer = ?', your_actual_value)
Oh, and if you have more than a thousand results to query, you might consider having a look at this.

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

Trying to get counts through multiple associations

I have created a question an answer app for a client much like StackOverflow. I am not trying to implement some sort of point system (like SO reputation). I am trying to get certain record counts through associations (which I believe are set up correctly). Primarily I am trying to get counts for votes on users answers. Here is an example.
In /views/questions/show page I list all the answers to that question by calling a partial _answer.html.erb. With each answer I pull in the answer.user information (username, email, etc.) by simply doing answer.user.username. I am wanting to display in a badge like format some total point calculations. So if User A answered Question A, next to User A's answer I want to display a total of all User A's answer votes.
I can successfully get a count for a users answers in /views/answers/_answer.html.erb by doing the following:
<%= answer.user.answers.count %>
but when I try to extend that syntax/association to get a count of votes on all User A's answers I get undefined method errors.
<%= answer.user.answers.votes.count %>
Is my set up fundamentally wrong here or am I missing something.
That is a bit confusing so let me know if you need more detail.
UPDATE:
Here are the associations:
Answers
class Answer < ActivRecord::Base
belongs_to :question
belongs_to :user
has_many :votes, :dependent => :destroy
end
Votes
class Vote < ActiveRecord::Base
belongs_to :answer
belongs_to :user
belongs_to :question
end
Users
class User < ActiveRecord::Base
has_many :questions, :dependent => :destroy
has_many :answers, :dependent => :destroy
has_many :votes, :through => :answers , :dependent => :destroy
end
<%= answer.user.answers.votes.count %>
but
answer.user.answers
is an array of answers so I suppose you wanted something like
<%= answer.user.answers[id].votes.count %>
UPDATE
<% answer.user.answers.each do |answer| %>
<%= answer.votes.count%>
<% end% >
UPDATE
<%= (answer.user.answers.map{|x| x.votes.count}).sum%>
I LOVE rails for such things
but when I try to extend that syntax/association to get a count of votes on all User A's answers I get undefined method errors.
You can find complete listing of what you can do with user.answers collection in here (besides standard Array/Enumerable methods). And it's only collection instance, not Answer object, so you can't invoke methods from Answer model on it.
You can try setupping has_many :votes, :through => :answers relationship. (See here for details) Although, I'm not sure if :through would work in such case.
Alternatively, you can create a method in User model to return all Vote objects (simply by iterating through all answers)
But frankly, creating a horde of Vote objects simply to count them sounds like a terrible waste of resources to me.

Resources