I am using will_paginate with rails 4 and have the following code in my users controller:
def index
#users = User.paginate(page: params[:page], :per_page => 10)
end
and in my view:
<% provide(:title, 'All users') %>
<h1>All Users</h1>
<%= will_paginate %>
<ul class="users">
<% #users.each do |user| %>
<%= render #users %>
<% end %>
</ul>
<%= will_paginate %>
This renders all the users however there are 40 per page, not 10. Each page has the correct users but 4 times. For example it renders users 1 .. 10 then 1 .. 10 again and so on. There are currently 101 users and if I set the per page limit to 1 it renders 101 pages with one user on each page as it should however any limit > 1 and it breaks.
Any insight on how to fix it so only 10 users appear on each page would be much appreciated.
I found your mistake. You need to render #users once. Hope it works on your side. :)
<ul class="users">
<%= render #users %>
</ul>
also you need to render pagination with following code
<%= will_paginate #users %>
You need to reference the block variable user within the render call, not #users
<ul class="users">
<% #users.each do |user| %>
<%= render user %>
<% end %>
</ul>
Related
I'm discovering the gem will_paginate which is great ! But I'm facing a problem of using. I'm building a group>post>comments app, so in my group show page i'm displaying posts and their comments. To limit the numbers of queries, i'm using includes method like this :
Group_controller :
def show
#posts = #group.posts.order(upd_at: :desc).includes(:user).includes(comments: :user).paginate(page: params[:page], per_page: 10)
end
So I would like to also paginate my comments. Do you know a way to do that ?
My code :
Group_show =
<h1>Groupe <%= #group.name %></h1>
<div class="post_list<%=#group.id%>">
<%= render #posts %>
</div>
<%= will_paginate #posts, renderer: BootstrapPagination::Rails %>
And my posts/_post =
<% #comments = post.comments %>
<ul id="comment_list<%=post.id%>">
<%- if #comments.any? %>
<%= render #comments, post: post %>
<%= will_paginate #comments, renderer: BootstrapPagination::Rails %>
<% end %>
</ul>
By the way if you have a method to define #comments directly in the Groups_controller(show), it can be really useful ;)
Not 100% tested, but I think this should work. Do you know how all these components work? If not, let me know and I can explain.
posts/_post
<% #comments = post.comments.order(created_at: :desc).limit(3) %>
<ul id="comment_list<%=post.id%>">
<%- if #comments.any? %>
<%= render #comments, post: post %>
<%- if post.comments.offset(3).exists? # this is more efficient than count > 3 bc it quits counting after 3 %>
<!-- the below link_to creates: href="/posts/:id/comments" ... -->
<!-- ... and `remote: true` makes that an ajax request -->
<li><%= link_to "more", comments_post_path(post), class: "more-comments-btn", remote: true %></li>
<% end %>
<% end %>
</ul>
config/routes.rb
resources :posts do
# `member do` is explained here: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
member do
get :comments
end
end
posts_controller.rb
# GET /posts/:id/comments
def comments
#post = Post.find(params[:id])
#comments = #post.comments.order(created_at: :desc)
# since you requested this url via ajax with `remote: true` rails will automatically render `posts/comments.js.erb` ...
# ... rather than a typical html request where rails would automatically render `posts/comments.html.erb`
end
views/posts/comments.js.erb
// some people like to use render #comments as shorthand like you did above. I'm a fan of being more explicit like the below
$("#comment_list<%= #post.id %>").html("<%= escape_javascript(render partial: 'comments/comments', locals: {comments: #comments, post: #post}) %>");
// now remove the more comments button
$("#comment_list<%= #post.id %>").find(".more-comments-btn").remove();
The documentation here explains the use of remote: true for ajax requests. Scroll down to section "3.1.2 link_to" and then section 5.1 for the controller and js.erb view.
My goal is to have a tag cloud within my posts page which will allow the user to filter posts by clicking on a tag. However, I am running into an undefined method 'total_pages" error after making the following changes to my Post_Controller method:
class PostsController < ApplicationController
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.visible_to(current_user).where("posts.created_at > ?", 7.days.ago).paginate(page: params[:page], per_page: 10)
end
end
end
I am trying to use the acts-as-taggable-on gem, and this logic will show me the posts with the appropriate tags.
The issue happens in the posts/index.html.erb view:
<div class="row">
<div class="col-md-8">
<h1> Trending </h1>
<p class="lead"> Active posts this week </p>
<div id="tag_cloud">
Tag Cloud:
<% tag_cloud Post.tag_counts, %w[s m l] do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
<% end %>
</div>
<%= render partial: 'posts/post', collection: #posts %>
<%= will_paginate #posts %>
</div>
<div class="col-md-4">
</div>
</div>
The will_paginate line will not render all the posts on that page. The work around is getting rid of <%= will_paginate #posts %> and replacing
#posts = Post.visible_to(current_user).where("posts.created_at > ?", 7.days.ago).paginate(page: params[:page], per_page: 10)
with #posts = Post.all. However, this gives me an entire page of posts, which is ugly. Does anyone know why I am running into an undefined method 'total_pages' error?
It looks like when you're sending a tag (params[:tag]) it is fetching posts with
#posts = Post.tagged_with(params[:tag])
which is lacking the will paginate call. I believe you could get it working by adding the will paginate scope, like this:
#posts = Post.tagged_with(params[:tag]).paginate(...)
I have set-up will_paginate to paginate an array (list of customer orders) and am using the following code in my show view (the orders are nested on the seller's page);
<ol>
<% #seller.trans.paginate(:page => 1, :per_page => 6).each do |buy| %>
<li><%= buy.customer.name %>£<%= buy.sum %><%= buy.date %></li>
<% end %>
</ol>
This has placed the right restriction on the array (6 per page) and I can manually filter through by changing the page number to 1, 2 or 3 (I have 13 orders) but the 'Next/Previous' links are missing from the view.
What is it I'm doing incorrectly? Thanks.
i think the code should be something like this
<ol>
<% #buys = #seller.trans.paginate(:page => 1, :per_page => 6) %>
<% #buys.each do |buy| %>
<li><%= buy.customer.name %>£<%= buy.sum %><%= buy.date %></li>
<% end %>
</ol>
<%= will_paginate(#buys) %>
take a look at the man page of the will_paginate gem from here, https://github.com/mislav/will_paginate
Okey, so this is how I would go about it:
View:
<%= will_paginate #seller, renderer: BootstrapPagination::Rails %>
Controller:
#seller = *Model*.paginate(:page => params[:page], :per_page => 6);
This has been tested using the gem will_paginate-bootstrap
Good luck!
I want to order users by descending. However, when I add .reverse it reverses the users a page at a time, not all together.
show_followers:
<%= render #users.reverse %>
<%= will_paginate %>
Users/_user:
<%= link_to user.name, user %>
<% unless #user.nil? %>
<% if request.path == "/users/#{#user.id}/listening_to" %>
<br/>
<span id="member_since"><%= "Listening Since" %> <%= #user.relationships.find_by_followed_id(user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% if request.path == "/users/#{#user.id}/listeners" %>
<br/>
<span id="member_since"><%= "Listener Since" %> <%= user.relationships.find_by_followed_id(#user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% end %>
Controller:
#users = #user.followed_users.paginate(page: params[:page])
It seems Rails intelligently orders by the relationships_create like I wanted but it's in ascending order. I want the most recent follower to show up on the top of the list.
In the controller action, you probably have some code that looks something like this: #users = User.paginate(:page => params[:page]).
You need to put the reverse in that statement, so it looks like this: #users = User.paginate(:page => params[:page]).order('id DESC') (perhaps with id replaced by created_at).
#users = #user.followed_users.reverse.paginate(page: params[:page])
Reverse at the controller level prior to pagination
In a Rails 3 blog type of app, I have a polymorphic comments model, with Posts having Comments (through :commentable). The Post#Show page has a form for comments that post through AJAX to a comment list below. Everything is working fine EXCEPT that Rails is for some reason dumping a full list of the database entries for all comments on that post in []'s at the very bottom of my comments list. I can't figure out where this is coming from and why!
Here are maybe the relevant code chunks, please feel free to request more! Thanks in advance.
views/posts/show
...
<%= render 'comments' %>
...
views/posts/_comments
<%= render :partial => 'comments/form' %>
<ul class="comments">
<% if #post.comments.empty? %>
<li>none yet</li>
<% else %>
<%= render :partial => 'comments/comment' %>
<% end %>
</ul>
views/comments/comment
<%= #comments.each do |comment| %>
<li>
<p class="comment_body">"<%= comment.body %>"</p>
<br/>
<p class="comment_info"><%= comment.name %> - <%= time_ago_in_words(comment.created_at) %> ago </p>
</li>
<% end %>
posts controller
def show
#post = Post.find(params[:id])
#comments = #post.comments
#commentable = #post
#comment = Comment.new(:commentable => #post)
#title = #post.author
end
And here's where the error creeps in (from Page Source). Right after the last comment closes and before the comments closes:
....
</li>
[#<Comment id: 97, name: "hmmm?", body: "hmmm", created_a...
</ul>
What is that thing and why is it here!? Thanks.
it's the = in the #comments.each tag. It is returning the result of each, which is the whole array.
For example:
irb> [1,2].each {|i| puts i }
1
2
=> [1, 2]
So:
<%= #comments.each do |comment| %>
Should simply be:
<% #comments.each do |comment| %>