Rails update database field according to two other fields - ruby-on-rails

So I have 2 fields in my Articles table.
- :vote_up
- :vote_down
I have methods in my app of updating the :vote_up and :vote_down fields that work fine. What I want to do is order my articles by total votes (:vote_up minus :vote_down).
What is the best way to do this. Can I do this directly in the controller with a certain method? Or must I create a :vote_total field that updates automatically according to the values of the other two fields (if so how do you do this).
Many thanks!

Don't do this in your controller. This is meant to be done in your model. Controllers should just use the model.
You can do this in 2 ways:
Solution 1
Try this in your console (rails c)
Article
.unscoped
.select(%q(articles.*, (articles.vote_up - articles.vote_down) AS vote_total))
.order(%q(vote_total DESC))
and the implement it as a scope in your Article class
scope :order_by_total_votes, -> {
select(%q(articles.*, (articles.vote_up - articles.vote_down) AS vote_total))
.order(%q(vote_total DESC))
}
Solution 2
Create a field vote_total for your Article and update it every time one of the vote fields gets updated (use a before_save callback). Then you can do the same as in solution 1, but without the select part.
Suggestion
I would go with solution 2, because amongst others it is faster in queries
Hope this helps.

Thanks #Hiasinho for your direction. I ended up just creating a :vote_total to my Article database and updated it on both my upvote and downvote methods like so
#article.update_attributes(vote_total: #article.vote_total + 1)
Obviously it was a -1 for downvotes.

Related

Rails join query

I am pretty new in rails and honestly, I am struggling with queries even after multiple researchs.
Here is my simple schema:
So basically, a question has many options, an option belongs to a question and has many answer, and an answer belongs to an option and has many users.
I don't think it s necessary to post the models code since it is just like i mentioned above.
What i would like to do is given a question option, see if a particular user already checked it (so look in the answer table if there is a row matching a given id_option, user_id and user_type). So in my haml loop, when displaying the different question option, i'm calling a method of my question_option model just like this :
- question.question_option.all.each do |option|
#{option.title}
.check
- if option.selected_by(current_actor)
= check_box_tag(option.id, "checked",true, class: 'styled-checkbox')
- else
= check_box_tag(option.id, "checked",false, class: 'styled-checkbox')
and the method called :
def selected_by(answerer)
answer_match =
::Vacancies::QuestionOption
.joins(:answers)
.where(answerer_id: answerer.id, answerer_type:answerer.type )
response = answer_match.find(self.id)
return response
end
This method is located in my QuestionOption model and leads to no errors but it s not working ever.
Can you help me transform this query to make it work with ActiveRecord ? Thanks
Try the below code. It checks if there are any answers by the user passed in the params on the question. I think this is what you intended to do as well-
def selected_by(answerer)
answers =
Answer.where(answerer_id: answerer.id, answerer_type:answerer.type, id_option: self.id)
answers.exists?
end

Rails - Posts with most comments in last 6 hours ordered by comments count

I can get easily find posts that have been commented on in the last 6 hours. However, I don't know how to order those posts by the number of comments made in the last 6 hours.
This is all I have:
Post.includes(:comments).where(comments: {created_at: 6.hours.ago...Time.now})
How do I order it? If the best way is to use a SQL query, I'm using PostgreSQL if it makes any difference.
I believe you want something like this:
Post.joins(:comments).where('comments.created_at BETWEEN ? AND ?', 6.hours.ago, Time.now).group('posts.id').order('COUNT(comments.id)')
If your requirement is different then feel free to comment and I will try to modify the answer.
I think it would be easiest for you to create a helper method for your Post model which returns the comments count:
def comments_count
comments.count
end
You can now do:
Post.includes(:comments).where(created_at: 6.hours.ago...Time.now).order(:comments_count)
It might be possible to do it without the helper method, I'm not sure but if you wanted to try:
Post.includes(:comments).where(created_at: 6.hours.ago...Time.now).order(:comments.count)

How can I get all the records in a table where any value of an associated table is in a given array?

I think if I had a better idea how to word this question, I would have been able to find an answer already... Anyways, I have a table called Vendors that has a many-to-many relationship with a table called Basins. I would like to be able to retrieve all the vendors that have at least one basin in an array of basins that is passed in as input.
So if I had three vendors like:
vendor1.basins = [Basin.first, Basin.second]
vendor2.basins = [Basin.second, Basin.third]
vendor3.basins = [Basin.third, Basin.fourth]
And I wanted to get all the vendors containing anything from [Basin.first, Basin.fourth], I would get both vendor1 and vendor3. If the array was [Basin.first, Basin.second], I would get both vendor1 and vendor2. I thought select might be the way to go here, but everything I've tried has been flagrantly wrong.
Thanks in advance.
I am assuming you are using Rails >= v4.0.0.
You can get vendors like:
Vendor.joins(:basins).where(basins: { id: [Basin.first.id, Basin.fourth.id] })
I hope this will help you.
You can add scope to Vendor model:
scope :foo, ->(basins_arr){ joins(:basins).
where(basins: { id: basins_arr.collect(&:id)})

Query/scope not including unsaved records in association

Scenario: I have a quiz type setup where Questions have many Answers and also have a Response provided by the user (omitted). A response has a selected attribute to indicate the user's choice and a correct? method that compares selected with the correct_answer.
Code: is here in this GitHub repo, along with seed data. Quick links to:
Question.rb
Answer.rb
Response.rb
Problem: I want to return all responses for a question that are correct however, unsaved records are not included.
I've tried a couple of different ways, as you'll see in the code including scope, question.correct_responses and also inverse_of (which I've read is supposed to be automatic now) - but to no avail.
Basically, I'm expecting following code to return 1, not 0.
q=Question.first
r=q.responses.build
r.selected = q.correct_answer
q.responses.correct.size # => 0??! wtf man!?
Your assistance is greatly appreciated.
When you use a scope you're going to the database.
Since you aren't saving the response, you don't want to go to the database. Instead, you should use something like the line below, which will select all of the question's "correct" responses and then count them.
q.responses.select { |r| r.correct? }.size
EDIT: or the short syntax for select:
q.responses.select(&:correct?).size

Want to count number of visits on my blogs

I want to count the number of visits on my blog? Can someone please suggest the overall method to implement this feature?
It is just an idea. You can add a count_view column in the database into blogs table with default value 0.
And in the show action of BlogsController add the following code
def show
#blog = Blog.where('id = ?', params[:id]).first
#blog.update_column('count_view', #blog.count_view + 1) if #blog.present?
end
You can modify this logic as per your requirement.
You can check the hit counter gem or the impressionist gem.
You could also use an existing (free) analytics solutions if you want to get much more data than the number of times the action was called (please note that if the same user refreshes the browser 5 times, you get 5 hits):
http://www.google.com/analytics/
Using these you can get data like unique visitors, referral URL, locations data, browser, OS, and a lot of different stuff to make informed decisions. There are several other options (paid, free, real time) available as well:
https://mixpanel.com
https://www.kissmetrics.com/

Resources