Will Paginate + Rails with association - ruby-on-rails

I'm having a problem where pagination works properly in displaying the correct number of pages to display all objects, but it's simply repeating all of the same objects on each page. (eg. If there are 10 objects and my per_page is 10, it'll show one page and all 10 items; if per_page is 5, it'll show 2 pages, but in both cases it keeps repeating ALL of objects from 1-10 on every page)
There is a HMBTM relationship, and all images associated in this case with the product model is in a join model.
I'm using this pagination gem: https://github.com/mislav/will_paginate/wiki
Products Controller
def show
#products = #product.images.all.page(params[:page]).per_page(10)
end
View
<% #product.images.each_slice(2) do |f,g| %>
...
<% end %>
<%= will_paginate #products %>

I already defined #products in the controller so I had to adjust my view so it didn't repeat the same code and just used the defined instance variable.
<% #products.each_slice(2) do |f,g| %>
...
<% end %>
<%= will_paginate #products %>

Related

Paginate with Kaminari not working

I am trying to use basic Kaminari to do some pagination, but I am having trouble getting it to work properly.
I have installed the Kaminari gem and then in my controller I have the following code:
def new
#guestbook = Guestbook.new
#guestbooks = Guestbook.all.limit(5).page(params[:page])
end
In my associated new view I have this code...
<%= paginate #guestbooks %>
<div class="span1">
<% #guestbooks.each do |g| %>
<br/>
<h4><%= g.name %>, <%= g.created_at %><br/></h4>
<%= g.message %><br/>......
However when I reload my page I do not see any pagination.
You need to use this in your controller:
#guestbooks = Guestbook.all
#guestbooks = Kaminari.paginate_array(#guestbooks).page(params[:page]).per(5)
And add this in your view:
<%=paginate #guestbooks%>
I completely support #Yang answer, and also I would suggest to make sure you have given min number of entries which is greater than the per page value.
for example:
def index
#posts = Post.page(params[:page]).per(10)
end
In this case: you must be created more than ten entries to get the pagination.

Rails ERB iterate over array

I'm trying to experiment with blocks and how to iterate over collections in ERB. I have a models in a one-to-many relatinship (Channel and their corresponding types).
controller
class HomePageController < ActionController
def index
#channels = Channel.all
end
end
Then in the view, I iterate over all the attributes belonging to a Channel. When I want to print all types, this code gives me the desired output:
view
<% #channels.each do |channel| %>
<% #types.each do |type| %>
<%= Type.find(type).name %>
<% end %>
<% end %>
At first I tried to achieve this by using the yield keyword in a neat one-liner but I couldn't manage to print anything to the browser, only to the console
<% #types.each {|type| yield Type.find(type).name } %>
Is there an equivalent one-liner?
First of all this method is so inefficient, you are doing n-queries, to find each record of type Type instead convert those into an array of types by using a single query in the controller, assume that that array is in type_ids
# controller
#channels = Channel.includes(:types) # avoiding n+1 queries
# view
<% #channels.each do |channel| %>
# some channel info output
<% channel.types.each do |type| %>
<%= type.name %>
<% end %> # types loop
<% end %> # channel loop
As #Almaron mentioned, you could render a partial for more simplification, if you have a partial called _type.html.erb you can call render directly
# view
<%= render channel.types %>
Rails will do all the iterating and rendering.
First of all, this kind of code does not belong to the view. Don't tackle the database from the view (in your case Type.find()). Move it to the controller where it belongs.
The second thing to note is the difference between <%= and <% tags. The first one outputs the returned result, while the second one doesn't. The problem with .each is that it returns the object it has been used on, so in your case if you just go <%= #types.each {|type| Type.find(type).name } %> you'll get the #types array printed out.
If you want to simplify that code, you can use a helper method for iterating and a partial for rendering each item. That way you get something like this
<% collection_iterate #items, 'item_partial' %>

How to get my image collections display page to show the first 3 images for each collection

I've set up a my site so that my users can create individual product collections and add their listings to each collection. I then created a site page that shows all created collections by all users. Right now I have the collection name and the "by so-and-so" displaying there for each collection, all good. I now want to show the first 3 listing images for each collection on top. I am able to get the first 3 images from my listings database to show in each collection using #listings = Listings.all, but that's not correct. But at least that confirms everything connects. I'm having trouble with my controller to def the #listings by 'collection_id'. I've tried so many different variations and the one below is where I'm currently stuck and serves a blank collection and doesn't recognize any/or each collection's listings.
My Pages Controller:
#collections = Collection.all.order("created_at DESC")
#listings = Listing.where(collection_id: #collection)
My Collections View Page:
<% #collections.each do |collection| %>
<% #listings.limit(3).each do |listing| %>
<%= image_tag listing.image.url(:small) %>
<% end %>
<%= collection.name %>
<%= collection.user.business_name %>
<% end %>
What am I missing in my controller to get the images to show by :collection_id? Do I need to change anything in my view page? Additionally, is it okay to nest the #listings.limit(3).each within my #collections?
The listing you are querying is not related to the collection, you should do something like this instead
<% #collections.each do |collection| %>
<% collection.listings.limit(3).each do |listing| %>
So you don't need a #listings query, but what you need instead is eager loading so you don't keep querying in each loop
#collections = Collection.includes(:listings).order(created_at: :desc)
If images are another object too, then you could include them in the includes too
#collections = Collection.includes(listings: :images).order(created_at: :desc)

how do i display an objects attributes from a different table in rails

Apologies if my terminology is off here.
I have a model for Users. I have a model for Products. Users have many products and Products belong to Users.
I am trying to have a Users index page that shows all Users and their associated Products with links to the individual User pages. My SHOW page is operating as I expect but I don't know how to show the User's Products on the index view.
SHOW (this works)
Controller
def show
#user = User.find(params[:id])
#product = #user.products
end
View
<%= #user.name %>
<% if #user.products.any? %>
Product
<%= render #product %>
<% end %>
Product Partial (referenced above)
Serial Number: <%= product.serial %>
INDEX (this does not work)
Controller
def index
#users = User.paginate(page: params[:page])
#product = #users.product #trying to show
end
View
I am at a loss here. Anything I've thought made sense doesn't work for me.
I would like to do something like
<%= user.product.serialnumber %>
or
<%= user.product.id %>
How do I show attributes of the User's Products in a view? Why does it work in a partial in my SHOW action/view but not in my INDEX action? Do I have to use a partial?
For your index action, #users is a collection of users whereas in your show #user is a single user object.
When you say, #users.product, you are calling product on collection object and not user object. So what you have to do is, iterate #users collection in your view and call product on the object
Something like
<% #users.each do |user| %>
<%user.products.each do |product|%>
<%= user.name%>
<%= product.serialnumber%>
<%= product.id%>
<%end%>
<% end %>

Pagination links not showing on arrays

My app fetches the covers to each of their Facebook photo albums (I do this with Koala), and I'm trying to paginate the results with will_paginate. I have pagination working on other elements, but it doesn't seem to like working with arrays.
I've gone through the documentation, I've used require 'will_paginate/array', and I can get it to limit the amount of entries per page - I have seven albums, and will_paginate will display the first four with the below code:
albums = graph.get_connections("me", "albums")
#albums = albums.paginate(:page => params[:page], :per_page => 4)
But dropping <% will_paginate #albums %> anywhere into the view doesn't seem to affect anything, and certainly doesn't generate the pagination links. Is there something I'm missing/doing wrong?
Use <%= %> Instead of <% %>
i.e
Change
<% will_paginate #albums %>
To
<%= will_paginate #albums %>

Resources