Showing database items - ruby-on-rails

I would like to have a link that only displays the last 10 database submissions with a select number of tables per submission. Hope that makes sense. So in short a can click 'recent submissions' and it will display the last 10 via customer name, submission date, and id number . Currently in the controller i have the following just to test the link but of course it display every table.
<h2>LAST 10 SUBMISSIONS</h2>
<%= #posts.each do |post| %>
<%end%>

Sorry, this is more of a comment than an answer but I don't have enough rep to leave a comment.
You could retrieve a bunch of #posts, which will be an array of ActiveRecord Relations. That means you can use Ruby's nifty Array methods. Here's an example:
#sorted_posts = #posts.sort_by { |p| p.created_at }.take(20)
And then pass in #sorted_posts where you currently have #posts in the code you posted above. But for performance and good practice you should probably retrieve that data in the proper format from the query itself.
#last_twenty_posts = Post.order("created_at DESC").limit(20) # limit by whatever number you want
Hope that helps!

You can simply order the posts by some attribute specifying the submission time (e.g., created_on) and limit the results to a number you want. For example:
Post.order("created_on DESC").limit(10)
This would return the last 10 Post objects based on their created_on attribute, with the newest first.

Related

RAILS Active record search with multiple ordering -- out of order

I want to display reports that meet criteria and display them in a particular order.
Sort by user, then by report creation date of the report, newest on top
#report_results.order('created_at DESC, user_id')
Above is the code I use, however, when the data is displayed, toward the end of each user's reports, they start to show up out of order.
How do I Fix this?
View:
<% #report_results.order('created_at DESC, user_id').each do |report| %>
You could do:
variable = report_results.order('created_at DESC')
#report_results = variable.group_by(&:user_id)
This should return a hash of user_id with the respective reports ordered.
<% #report_results.order('user_id').order('created_at DESC').each do |report| %>
Not sure why this works, I thought the last order command would overwrite the previous, but it seems like it retains it.
Items now show up grouped by user_id, in descending chronological order.

Show only unique results with collection_select

I have a series of reviews for a professor, I want users to be able to sort reviews based on the class taught. I have a collection_select but I'm having trouble filtering out duplicates, so for example if more than one user had a professor for "English" you will just see "English" twice in the list.
This is what I have:
<%= collection_select(:professor, :id, Review.where(professor_id: #professor.id), :id, :whatclass) %>
I've seen some solutions saying that I should add .uniq but that dosen't seem to do anything.
<%= collection_select(:professor, :id, Review.where(professor_id: #professor.id).uniq, :id, :whatclass) %> I'm pretty sure this is not working because it's referring to the Review.id rather than Review.whatclass
Your list contains duplicates because it has an entry for every review, not for every class taught, which is not unique for each review. I am not even sure you need to use collection_select to render a simple list of unique class names.
In the controller, try:
#unique_classes = Review.
where(professor_id: #professor.id).
pluck(:whatclass).uniq
Here, pluck returns an array of just the whatclass attributes of every review of the professor. Calling uniq on that will drop any duplicates in the array. If you have lots of reviews for each professor, you can get better performance by having the database filter the duplicates:
#unique_classes = Review.
where(professor_id: #professor.id).
pluck("DISTINCT whatclass")
This will generate a SELECT DISTINCT query, so the array pluck returns will already be unique.
Finally, you can plug this array of whatclass values into a simple select_tag:
select_tag :class_name, options_for_select(#unique_classes)
The code above is untested, so it might need some changes to work.

How can I set a fallback ordering system?

I'm printing a list, ordered as such:
<% #users.order(:number).each do |u| %>
<%= u.name %>
<% end %>
But some users will have the same value of :number, and in that case the records appear to be ordered based on time_created. How can I set a fallback or secondary ordering system to be used when records have the same value of the attribute used to order them?
You can just keep adding on to the order method.
#users.order(:number, :name, :last_logged_in, :id)
If the numbers are the same, it will break the tie with name, then last_logged_in, then id. This is all done in the database for you.
If you already had the data in memory, then you could use Ruby's sort_by method.
You're probably going to want to use sort_by instead of order.
#users.sort_by {|u| [u.number, u.second_option] }
that will sort first by number and then if number matches it will pull whatever the second option is and compare by that. Technically you can throw as many things to sort by as you want into that array.
Edit: Actually, there's a similar question already answered here

How does the query method #group work?

I'm learning rails and have been trying to read through documentation, but I just don't get how #group
works.
The documentation says that it: "Returns an array with distinct records based on the group attribute".
How do you then retrieve the records that belong to a certain group?
Say I want to group Articles by the month in which they were created? How would I do that?
The group method is generally used with the select method to do aggregating queries. For instance, if you wanted to count your articles by month, you could do this:
by_month = Article.group(:month).select("month", "COUNT(*) as count")
In this case, COUNT is the SQL aggregate function that counts rows, and we're putting the count result into an output column called "count".
Note: This assumes you have a column called "month". Of course you can do SQL here, so you might have, e.g. MONTH(created_at) instead, or whatever makes sense in your case.
You could then do this to output the month and its associated article count:
by_month.each do |row|
puts "Month #{row.month}: #{row.count}"
end
This probably seems mysterious because your model has no column "count", but that's the way select works: It defines new output columns for the query on the fly, and ActiveRecord happily maps those for you in the resulting instance objects.
This kind of query is dramatically more efficient than loading all the records and counting them yourself because you're letting the database do the heavy data work, and that's what it's good at.
It is perfectly legal to use group without select but the result is not usually what you want. If you group your articles by month, you'll get one object in the result for each month. The columns available in each object vary by database back end, but in MySQL they will have the values from the "first" row encountered for each group. If you aren't sorting, "first" is essentially undefined.
If by "group Articles by the month in which they were created" you mean you want this kind of grouping on a web page result, then you'll have to do it yourself, e.g.:
<% last_month = nil %>
<% #articles.each do |article| %>
<% if last_month != article.month %>
<h2><%= article.month %></h2>
<% last_month = article.month %>
<% end %>
# [output the article]
<% end %>
If you do something like this, you'll need to be sure #articles is ordered by month.

Count value of records which belong to other model in rails

This is probably pretty basic, but I'm trying to figure out how to show how many comments a post has in rails, on the post index page of my app.
comments belongs_to post, and post has_many comments
Just not sure how to show on the index page, the amount of comments for each post.
Thanks in advance!
Elliot
Try this.
<%= post.comments.size %>
You might also be interested in the pluralize method.
<%= pluralize(post.comments.size, 'comment') %>
This will output "3 comments" or "1 comment", etc.
I may be wrong here, but you should use
<%= post.comments.count %> rather than size.
ActiveRecord knows that 'count' is a special method, and will turn it into a SELECT count(id) from comments where post_id = x (which is what you want).
size however, is not a special method, and ActiveRecord will load all the comments into an array in memory (SELECT * from comments where post_id = x, and then tell you how long this array is, which may be unneccessary - if you're going to loop through the array of comments further down the page, then you may want to use size to load them into memory, because it will need to happen later anyway.
You should also use some of ActiveRecord's built in functionality here. The counter_cache. Check it out here

Resources