Kaminari not limiting collection in Spree - ruby-on-rails

For some reason Kaminari is not limiting child objects on the parent show view.
Can see the pagination links but the collection does not get limited.
What am I doing wrong?
View -
<% if #handbag.microposts.any? %>
<h3>Posts (<%= #handbag.microposts.count %>)</h3>
<div class="row">
<div class="col-md-8">
<ol class="microposts">
<% #handbag.microposts.each do |micropost| %>
<li id="micropost-<%= micropost.id %>">
<span class="user"><%= micropost.user.email %></span>
<span class="content"><%= micropost.content %></span>
<%= image_tag micropost.picture.url if micropost.picture? %>
<span class="timestamp">
Added <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</li>
<% end %>
</ol>
<%= paginate #microposts %>
Controller -
def show
#handbag = Spree::Handbag.find(params[:id])
#microposts = #handbag.microposts.page(params[:page] || 1).per(10)
end
Thanks for any help.

You're looping through #handbag.microposts, which is the entire collection, instead of #microposts, which is the paginated collection.
So just change #handbag.microposts.each to #microposts.each

Related

Haiving a problem to Paginate an iteration with Kaminari

I'm trying to paginate a result of an iteration using Kaminari. The pagination is showing well but its not cutting it into another page. All is showing on the same page even when I click on page 2, it still the same result as page 1
I'm using rails 6 and ruby 2.5
in my controller i have this
def dashboard
user_gigs = current_user.gigs
#user_gigs_pager = Kaminari.paginate_array(user_gigs).page(params[:page]).per(4)
end
then in my view I call the paginate
<div class="card">
<div class="card-header-title is-centered">
<%= paginate #user_gigs_pager %>
</div>
</div>
this my full view code
<% current_user.gigs.each do |gig| %>
<%# <% user_gigs = current_user.gigs %>
<div class="column is-one-third">
<div class="card">
<div class="card-image">
<%= link_to edit_gig_path(gig) do %>
<figure class="image is-4by3">
<!-- Gig Cover Image Here -->
<%= image_tag gig_cover(gig) %>
</figure>
<% end %>
</div>
<div class="card-content p-t-5 p-b-5">
<p class="subtitle is-6 m-b-5"><%= link_to gig.title.truncate(20), gig_path(gig) %></p>
<span class="star-review"><i class="fa fa-star"></i>
<%= gig.average_rating %> <span class="star-review">(<%= gig.reviews.count %>)</span>
</span>
</div>
<footer class="card-footer">
<p class="deletegig">
<%= link_to destroy_gig_path(gig), method: :delete, data: { confirm: "are you sure"} do %>
<span class="icon has-text-danger">
<i class="far fa-trash-alt"></i>
</span>
<% end %>
</p>
<% basic_price = gig.pricings.find{ |p| p.pricing_type == 'basic' }%>
<a class="has-text-danger is-block card-footer-item has-text-right">
<% if !basic_price.nil? %>
<span class="small-title">Points</span> <i class="fab fa-bitcoin"></i>
<strong><%= basic_price.price %></strong>
<% else %>
<strong>
<span class="small-title has-text-dark">Pas de point</span>
</strong>
<% end %>
</a>
</footer>
</div>
</div>
<% end %>
</div>
</div>
</div>
<div class="card">
<div class="card-header-title is-centered">
<%= paginate #user_gigs_pager %>
</div>
</div>
Kaminari.paginate_array(user_gigs).page(params[:page]).per(4)
expects page number as argument of page and number of records per page as argument of per.
Your params must contain page number (i.e. 1 or 2 or 3 ...) in :page key.
The solution was to apply the pagination on the ActiveRecord association instead of the array.
So in my controller it should be
#user_gigs_pager = current_user.gigs.page(params[:page]).per(4)
then in the view
<% #user_gigs_pager.each do |gig| %>
....
<%= paginate #user_gigs_pager %>

How to avoid same instance variables for footer

I have a footer in my rails application that shows all recent posts and categories produced by two instances variables in the welcome_controller.rb
But then if i go to another section that has a different controller responsible i get an error as the #posts and #categories instance variables are not there to loop through and list the latest posts and categories.
welcome_controller.rb (code extract)
#categories = Category.all
#posts = Post.order("created_at DESC")
_footer.html
<div class="row footer-black">
<div class="large-3 columns text-left">
<h4>Categories</h4>
<ul>
<% #categories.each do |c| %>
<% unless c.header? %>
<% if c.restriction %>
<% if check_for_free_questions_in_restricted_category(c) %>
<li> <%= link_to c.title, category_random_free_question_path(c),'data-no-turbolink' => true %> </li>
<% else %>
<li> <%= link_to c.title, new_subscription_path,'data-no-turbolink' => true %> </li>
<% end %>
<% else %>
<li> <%= link_to c.title, category_random_question_path(c),'data-no-turbolink' => true %> </li>
<% end %>
<% end %>
<% end %>
</ul>
</div>
<div class="large-5 columns text-left">
<h4>Latest Posts</h4>
<ul>
<% #posts.each do |p| %>
<li> <%= link_to truncate(p.title, length:70), blog_post_path(p) %> </li>
<% end %>
</ul>
</div>
<div class="large-4 columns text-left social-links">
<h4>Social</h4>
<a href="#">
<i class="fa fa-facebook-square fa-2x"></i>
</a>
<a href="#">
<i class="fa fa-twitter-square fa-2x"></i>
</a>
<a href="#">
<i class="fa fa-google-plus-square fa-2x"></i>
</a>
</div>
</div>
is there a way to show categories and posts in footer without instantiating same variables over and over again?
The short answer is 'no'. Every variable must be instantiated (initialized) before it can be used (in this case, in your view).
Now, there are some more efficient ways of instantiating these variables than writing:
#categories = Category.all
#posts = Post.order("created_at DESC")
in multiple controllers. But, that's a different question. If you're interested in that, then ask a new question or refine this one.

Ruby on Rails - Correct way of paginating two lists in one view

So I want to use will_paginate plugin two times on one page. My problem is that when I click next on one of the paginations (#articles pagination), it also goes to the next page on my other pagination (#comments pagination).
<div class="row">
<div class="span6">
<h3>Posted Articles (<%= #articles.count %>)</h3>
<ol class="user_articles">
<% #articles.each do |article| %>
<li>
<span class="content"><%= link_to article.title, article.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(article.created_at) %> ago to <%= article.article_type %>.
</span>
<div>
<% if current_user?(article.user) %>
<%= link_to "delete", article, method: :delete,
data: { confirm: "You sure?" },
title: article.title %>
<% end %>
</div>
</li>
<% end %>
</ol>
<%= will_paginate #articles %>
</div>
<div class="span6">
<h3>Comments (<%= #comments.count %>)</h3>
<ol class="user_comments">
<% #comments.each do |comment| %>
<li>
<span class="content"><%= comment.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(comment.created_at) %> ago to <%= link_to Article.find_by_id(comment.article_id).title, Article.find_by_id(comment.article_id) %>.
</span>
<div>
<% if current_user?(comment.user) %>
<%= link_to "delete", comment, method: :delete,
data: { confirm: "You sure?" },
title: comment.content %>
<% end %>
</div>
</li>
<% end %>
</ol>
<%= will_paginate #comments %>
</div>
</div>
I understand you can specify a :param_name option to tell will_paginate the name of the parameter to use for the page number, but I have no clue what :param_name I should use in order for it to work. Any help would be greatly appreciated!
EDIT:
Here is my user controller for the view:
def show
#user = User.find(params[:id])
#comments = #user.comments.paginate(page: params[:page], :per_page => 20)
#articles = #user.articles.paginate(page: params[:page], :per_page => 20)
end
Your :param_name should be something like :articles_page and :comments_page, specified on each of the pagination statements.

Displaying microposts' comments for user

Building upon Micropost's comments on users page (Ruby on Rails) , I was able to add new comments for each micropost. However, I'm having problem displaying back the comments for each post on the same page. The codes below didn't throw any error, so I'm thinking the each micropost's comments are not assigned correctly so it can't display.
Users > Microposts > Comments
users_controller.rb
def show
#user = Account.find(params[:id])
#microposts = #user.microposts
#micropost = Micropost.new
#comments = #micropost.comments
#comment = Comment.new
end
microposts/_micropost.html.erb
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<span class="comments">
<% if micropost.comments.any? %>
<ul class="comments">
<%= render #comments%>
</ul>
<% end %>
<%= render "shared/form_comment", micropost: micropost %>
</span>
</li>
comments/_comment.html.erb
<li>
<span class="content"><%= comment.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(comment.created_at) %> ago.
</span>
</li>
Change <%= render #comments%> to <%= render micropost.comments %> to loop through the specific post's comments instead of using generic comment loop.
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<span class="comments">
<ul class="comments">
<%= render micropost.comments %> # you can leave out the #any?
</ul>
</span>
</li>

Rails Odd Even If Statement

I have a loop for my Activity model
<% #activities.each do |activity| %>
<div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
</div>
<% end %>
I want to create a zig-zag effect, so I need to re-arrange the HTML for every even activity, so the markup will look like this:
<div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
</div>
Is there a way to do this with an if statement? Something like this:
<% if activity.odd? %>
<% #activities.each do |activity| %>
<div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
</div>
<% end %>
<% else %>
<% #activities.each do |activity| %>
<div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
</div>
<% end %>
There are a few ways to do this.
The first and best way is to do this with CSS's nth-child selector, assuming it's possible to achieve your desired effect purely through CSS. Use nth-child(odd) or nth-child(even), as described in Alternate table row color using CSS?
If you're iterating over a collection using .each, you can add a .with_index and check whether the index is odd or even:
<% #activities.each.with_index do |activity, index| %>
<% if index.odd? %>
...
<% else %>
...
<% end %>
<% end %>
Note that by default the index is zero-based, so your first element will be considered "even". You can pass a starting index of 1 to with_index if you want the alternating to start odd instead:
<% #activities.each.with_index(1) do |activity, index| %>
An alternative to using with_index is to use Rails' cycle helper, which "magically" returns the next argument in rotation each time its invoked:
<% #activities.each do |activity| %>
<% if cycle('odd', 'even') == 'odd' %>
...
<% end %>
<% end %>
Also note that this is a fantastic opportunity for refactoring. You should distill the two reused cell divs into their own partials and render them in the order you want:
<% if index.odd? %>
<%= render h4_part %>
<%= render img_part %>
<% else %>
<% render img_part %>
<% render h4_part %>
<% end %>

Resources