On my template, I show books ordered by their child's created_at (reviews). But when I order it this way, the books are shown twice/thrice (varies). How can I resolve this?
My controller:
#pagy, #books = pagy_countless(Book.where(user_id: current_user.id).joins(:comments).order("comments.created_at DESC").group("books.id, comments.created_at"), items:10 )
# I am using pagy gem
As you can see, I've tried group(). Doesn't help. I've also tried adding .distinct to the end of the code (and in the middle). Doesn't help.
#pagy, #books = pagy_countless(Book.where(user_id: current_user.id).joins(:comments).order("comments.created_at DESC").distinct, items:10 )
I would suggest not using the pagy gem while you're debugging this. Add it back later when you've got a non-paged version working.
The joins will indeed produce multiple instances of Book. What you need is
#books = Book.where(user_id: current_user.id).includes(:comments)
Then in the template (you didn't show us, so I'm making assumptions":
<%- #books.each do |book| %>
<h2><%= book.title %></h2>
<ul>
<%- book.comments.each do |comment| %>
<li><%= comment.text %></li>
<%- end %>
</ul>
<%= end %>
(hope I got all the erb right there! I've been using haml for years!)
you could use select MAX each group instead oforder DESC
Book.joins(:comments)
.select("books.*, MAX(comments.created_at) as c_max")
.where(user_id: current_user.id)
.group("books.id")
Related
in view I have this
<div>
<% #readers.each do |reader| %>
<% user_profile_url = user_url(reader.user.username) %>
<div>
<%= link_to user_profile_url do %>
<%= reader.user.username %>
<% end %>
<span>[<%= reader.created_at.to_date %>]</span>
</div>
<% end %>
</div>
in the books_controller i have this
def readers_list
#book = Book.find(params[:id])
#readers = #book.downloads.order(created_at: :desc)
end
I have this problem: If an user download twince a book, in this list I see the username twince.
So, I know, I have to add uniq
I tried to add it at the end of the #readers, but it didn't work. How (and where) to add it?!
I also tried to make this #readers = #book.downloads.where(user_id: params[:user_id]).order(created_at: :desc), but it didn't work.
Use DISTINCT instead uniq. As you'll get everything and then do uniq, that's often considered as inefficient:
book
.downloads
.select('distinct on (downloads.user_id) downloads.*')
.order('downloads.user_id, downloads.created_at DESC')
downloads was scoped to a JOIN clause, so the created_at column was present in both tables, hence the explicit reference in both select and order.
Another alternative is to use "Group By", In rails it can be done like this
#book.downloads.order(created_at: :desc).group(:user_id)
If you want to check What's faster, 'DISTINCT' or 'GROUP BY' then here is a good place to get started.
Hi everyone I have a question , I looking for on google but I don't find an answer.
I'm actually want to display Post model and User model by search in same page and for this I want to use Will_paginate to display all of them .
I try this solution =>
**require 'will_paginate/array'
#posts =Post.search(params[:q]).order("created_at DESC")
#users=User.search(params[:q]).order("created_at DESC")
#all_records = (#posts + #users).paginate(:page =>params[:page], :per_page => 10)**
And In my view I want to display all query found ,so I try something like this =>
**<%unless #posts.nil?%>
<% #posts.each do |post| %>
....
**
**<% unless #users.nil?%>
<% #users.each do |user| %>
...**
<%= will_paginate #all_records %>
But it doesn't work nothing happend, so I want to know how to get #posts and #users records in #all_records to do something like this =>
**
<% #all_records[#posts].each do.. %>
<% #all_records[#usets].each do ..%>
**
I saw some solutions that suggest to use two differentes paginate in my view like =>
**<%= will_paginate #posts %>
<%= will_paginate #users %>**
**But It's not want I want , I would'like only one paginate for all, Please Help me cause I'm going crazy, Thank you **
I have question and category model. Question model has category_id column.
class Question
belongs_to :category
end
class Category
has_many :questions
end
In my controller I have this:
def index
#categories = Category.all
#questions = Question.all
end
I would like to display all categories and all questions that belongs_to specified category. Also, I would like to display question numbers below each category and made links of them and later it will open new page with clicked question.
This is how I tried to do that:
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% #questions.each do |question| %>
<ul>
<li><%= link_to question.id %></li>
</ul>
<% end %>
<% end %>
It should look like this but I get stuck:
Category1
1 2 3 4
Category2
1 2 3 4
Question: How to achieve that I display questions like is show above?
You can do it this way:
Controller:
def index
#categories = Category.all
end
View:
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% category.questions.each do |question| %>
<ul>
<li><%= link_to question.id, question_path %></li>
</ul>
<% end %>
<% end %>
Since you said you want to display all of the categories, and the questions that belong to each of those categories, I'm assuming that the index action that you pasted in comes from your categories_controller.
One solution I can think of would be to change the instance variables inside your index. I don't really see a purpose for having the instance variable that references all of your Question objects. This is the one I'm talking about:
#questions = Question.all
Yea, get rid of that. You should be fine with just
#categories = Category.all
Since you want to display all of your categories, that instance variable is necessary. And since you mentioned you want to also display all of the questions that belong to each category, that instance variable is sufficient with the right view. You were on the right track, but instead, just use the #categories instance variable; forget about #questions. Here is what your view should probably look like (you were on the right track above):
<% #categories.each do |category| %>
<h1><%= category.name %></h1>
<% category.questions.each do |question| %>
<ul>
<li><%= link_to question.id, question_path %></li>
</ul>
<% end %>
<% end %>
Also note that in that first line of code, when you start a block, you don't need the <%= , You only need the <%. That's because that first line of the block is purely ruby in itself, it isn't actually getting printed to the resulting html.
Hope I helped a little bit!
* Also: I saw another answer on here which is missing something: When you use the <%= link_to %> helper, you need to specify the first argument which is the resulting markup (In this case you wanted the question.id) , AND ALSO A SECOND ARGUMENT, which is the path for the link to follow *
I have this method at the moment:
<% for comment in #critical_process.review.comments %>
<div id="comment">
<%=h comment.comment %> <br/>
<span id="comment_email">
By: <%=h comment.user.email%>
</span>
</div>
<% end %>
however I need it to display the comments in order of the most recently updated at the top and work its way down.
Thanks
Assuming the Comment model has an updated_at column, and you are using Rails 3, you can just tell ActiveRecord to order the Comment records appropriately as follows:
<% for comment in #critical_process.review.comments.order('updated_at DESC') %>
The Rails 2.x equivalent would be:
<% for comment in #critical_process.review.comments.all(:order => 'updated_at DESC') %>
Whilst this will work perfectly well, it's generally considered best to move most of your query generation into the controller, in which case you might do the following in the controller:
#comments = #critical_process.review.comments.order('updated_at DESC')
... and then iterate over the #comments collection in the view.
Hy guys. I've created a simple blog app with the usual CRUD actions. I've also added a new action in the PostController called "archive" and an associated view. In this view I want to bring back all blog posts and group them by month, displaying them in this kind of format:
March
<ul>
<li>Hello World</li>
<li>Blah blah</li>
<li>Nothing to see here</li>
<li>Test post...</li>
</ul>
Febuary
<ul>
<li>My hangover sucks</li>
... etc ...
I can't for the life of me figure out the best way to do this. Assuming the Post model has the usual title, content, created_at etc fields, can someone help me out with the logic/code? I'm very new to RoR so please bear with me :)
group_by is a great method:
controller:
def archive
#this will return a hash in which the month names are the keys,
#and the values are arrays of the posts belonging to such months
#something like:
#{ "February" => [#<Post 0xb5c836a0>,#<Post 0xb5443a0>],
# 'March' => [#<Post 0x43443a0>] }
#posts_by_month = Posts.find(:all).group_by { |post| post.created_at.strftime("%B") }
end
view template:
<% #posts_by_month.each do |monthname, posts| %>
<%= monthname %>
<ul>
<% posts.each do |post| %>
<li><%= post.title %></li>
<% end %>
</ul>
<% end %>
#Maximiliano Guzman
Good answer! Thanks for adding value to the Rails community. I'm including my original source on How to Create a Blog Archive with Rails, just in case I butcher the author's reasoning. Based on the blog post, for new developers to Rails, I'd add a couple suggestions.
First, use Active Records Posts.all method to return the Post result set for increased speed and interoperability. The Posts.find(:all) method is known to have unforeseen issues.
Finally, along the same vein, use beginning_of_month method from the ActiveRecord core extensions. I find beginning_of_month much more readable than strftime("%B"). Of course, the choice is yours.
Below is an example of these suggestions. Please see the original blog post for further detail:
controllers/archives_controller.rb
def index
#posts = Post.all(:select => "title, id, posted_at", :order => "posted_at DESC")
#post_months = #posts.group_by { |t| t.posted_at.beginning_of_month }
end
views/archives/indext.html.erb
<div class="archives">
<h2>Blog Archive</h2>
<% #post_months.sort.reverse.each do |month, posts| %>
<h3><%=h month.strftime("%B %Y") %></h3>
<ul>
<% for post in posts %>
<li><%=h link_to post.title, post_path(post) %></li>
<% end %>
</ul>
<% end %>
</div>
Good luck and welcome to Rails!