Rails: order items in nested view - ruby-on-rails

I have a model called Post which belongs_to another model named Group. So currently a user can navigate to a group and create a post, the post is displayed under the correct view. However, I'm trying to figure out how to make the posts display in descending order so that the newest post is on top for that particular group.
this is in the posts_controller. It places them in descending order correctly when I go to .../groups/:id/posts however I need the posts to display descending in .../groups/:id
# GET /groups/:group_id/posts
def index
#posts = #group.posts.order("created_at desc")
end
This is in the groups/show.html.erb view. Is there a way to add a descending order onto #group.posts.each ?
<%= link_to 'New Post', new_group_post_path(#group.id) %>
<!-- gets posts for the group -->
<div class="row">
<% #group.posts.each do |post| %>
<div class="col-lg-12">
<div class="card bottom-pad">
<div class="card-body">
<h4 class="card-title"><%= link_to post.title, group_post_path(#group, post), class: "text-primary" %></h4>
<p class="card-text"><%= truncate(post.content, length: 500) %><br><br>
<%= post.user.last_name %>
</p>
</div>
<div class="card-footer">
<small class="text-muted"><%= time_ago_in_words(post.created_at) + " ago" %></small>
</div>
</div>
<br><br>
</div><!--./col-->
<% end %><!--./#group.posts.each-->
</div><!--./row-->

You can do the ordering in your show.html.erb like this:
<%= link_to 'New Post', new_group_post_path(#group.id) %>
<!-- gets posts for the group -->
<div class="row">
<% #group.posts.order(created_at: :desc).each do |post| %>
<div class="col-lg-12">
<div class="card bottom-pad">
<div class="card-body">
<h4 class="card-title"><%= link_to post.title, group_post_path(#group, post), class: "text-primary" %></h4>
<p class="card-text"><%= truncate(post.content, length: 500) %><br><br>
<%= post.user.last_name %>
</p>
</div>
<div class="card-footer">
<small class="text-muted"><%= time_ago_in_words(post.created_at) + " ago" %></small>
</div>
</div>
<br><br>
</div><!--./col-->
<% end %><!--./#group.posts.each-->
</div><!--./row-->

Related

How to change code of every nth iteration

I got the following code in an .erb document:
<% #blog.order("created_at DESC").each do |d| %>
<!-- Blog Card -->
<div class="col-12 mb-3 mb-sm-7">
<article class="row align-items-lg-center">
<div class="col-lg-8">
<%= image_tag d.image.to_s, class:"img-fluid rounded" %>
</div>
<div class="col-lg-4">
<div class="py-5 px-lg-3">
<span class="d-block mb-2">
<p class="small text-body font-weight-bold text-cap"><%= d.tag_list %></p>
</span>
<h2>
<%= link_to d.title, d, class:"text-inherit" %>
</h2>
<p><%= d.summary.truncate(100) %></p>
<%= link_to "read more", d %>
</div>
</div>
</article>
</div>
<!-- End Blog Card -->
<% end %>
I want the code to change every nth time so i have multiple "layouts" (not in the ruby sense) in my blog. for this i added an if clause with following code:
<% if d.id % 5 == 0 %>
Unfortunately that does not work very well since i want to weave in the layout alternative into the regular layout like this:
┌─────────┐
└─────────┘
┌──┐┌──┐┌─┐
└──┘└──┘└─┘
┌─────────┐
└─────────┘
┌──┐┌──┐┌─┐
└──┘└──┘└─┘
So one large article, next row with three small ones etc.
Edit:
The alternating layout looks like this:
<div class="order-lg-1 col-sm-6 col-lg-4 mb-3 mb-sm-7">
<!-- Blog -->
<article
class="card align-items-start flex-wrap flex-row h-380rem gradient-y-overlay-sm-dark bg-img-hero rounded-pseudo transition-3d-hover"
style="background-image: url('<%= d.image.to_s %>');">
<div class="card-header border-0 bg-transparent w-100">
<p class="small text-white font-weight-bold text-cap mr-2"><%= d.tag_list %></p>
</div>
<div class="card-footer border-0 bg-transparent mt-auto">
<%= link_to d do %>
<h3 class="text-white"><%= d.title %></h3>
<span class="text-white-70">Read more<i class="fas fa-angle-right fa-sm ml-1"></i></span>
<% end %>
</div>
</article>
<!-- End Blog -->
</div>
How do i implement such a layout?
SOLUTION
I managed to do what i wanted with a combination of .each_with_index and using partials. like this:
<% #blog.order("created_at DESC").each_with_index do |d, index| %>
<%= index % 4 == 0 ? render("blog/var1", d: d) : render("blog/var2", d: d) %>
<% end %>
You can do something like this:
<% #blog.order("created_at DESC").each_with_index do |d, index| %>
<!-- Blog Card -->
<div class="col-#{index % 4 == 0 ? '12' : '4'} mb-3 mb-sm-7">
<article class="row align-items-lg-center">
<div class="col-lg-8">
<%= image_tag d.image.to_s, class:"img-fluid rounded" %>
</div>
<div class="col-lg-4">
<div class="py-5 px-lg-3">
<span class="d-block mb-2">
<p class="small text-body font-weight-bold text-cap"><%= d.tag_list %></p>
</span>
<h2>
<%= link_to d.title, d, class:"text-inherit" %>
</h2>
<p><%= d.summary.truncate(100) %></p>
<%= link_to "read more", d %>
</div>
</div>
</article>
</div>
<!-- End Blog Card -->
<% end %>
It means, for every 0, 4, 8, 12 .... index it'll add class col-12, otherwise it'll add class col-4
EDIT:
Yes, it is possible to insert whole partials as code:
Lets say, you created two separate files for small cards and big cards.
_small_blog_card.html.erb and _big_blog_card.html.erb
<% #blog.order("created_at DESC").each_with_index do |d, index| %>
<% if index % 4 == 0 %>
<%= render partial: 'big_blog_card', locals: {pass your data} %>
<% else %>
<%= render partial: 'small_blog_card', locals: {pass your data} %>
<% end %>
<% end %>

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 %>

Display last record in erb Rails with will_paginate

I am trying to display the last instanced record from my model Tribune with this layout :
Some random tribune
Some random tribune
Last
Last recorded tribune
I am using the gem will_paginate which allow me to display 10 tribunes / per page.
The issue is that the layout is working but applied to each page.
Every 10 tribunes, one is identified as "last". Obviously, I would like to have only one tribune identified as last.
Here is my code :
<div class="wrapping">
<% #tribunes.each do |tribune| %>
<div class="container">
<div class="mouse-out-container"></div>
<div class="row">
<% if tribune == #tribunes.last
%>
<h1>Last</h1>
<div class="col-xs-12 col-md-12">
<div class="card">
<div class="card-category">Popular</div>
<div class="card-description">
<h2><%= tribune.title %></h2>
<p><%= tribune.content.split[0...25].join(' ') %>...</p>
</div>
<img class="card-user" src="https://kitt.lewagon.com/placeholder/users/tgenaitay">
<%= link_to "", tribune, :class => "card-link" %>
</div>
<% else %>
<div class="col-xs-12 col-md-12">
<div class="card">
<div class="card-category">Popular</div>
<div class="card-description">
<h2><%= tribune.title %></h2>
<p><%= tribune.content.split[0...25].join(' ') %>...</p>
</div>
<img class="card-user" src="https://kitt.lewagon.com/placeholder/users/tgenaitay">
<%= link_to "", tribune, :class => "card-link" %>
</div>
</div>
<% end %>
<% end %>
</div>
<div class="center-paginate">
<%= will_paginate #tribunes, renderer: BootstrapPagination::Rails %>
</div>
</div>
</div>
When all Goole-fu fails, we have to dig in the source code. There we find some interesting methods:
# Any will_paginate-compatible collection should have these methods:
# current_page, per_page, offset, total_entries, total_pages
#
# It can also define some of these optional methods:
# out_of_bounds?, previous_page, next_page
From these, the method next_page looks interesting, as it seems to return nil if there are no more pages.
Now we can construct the loop:
<% #tribunes.each do |tribune| %>
<% if !#tribunes.next_page && tribune == #tribunes.last %>
<!-- We're on the last page and the last tribune of that page -->
Last tribune content
<% else %>
<!-- We still have tribunes to go -->
Normal tribune content
<% end %>
<% end %>

Trying to link reviews users actively input under the show page of the specific movie for which the review was written

Under app->controllers->reviews_controller.rb, I have the following code:
`def create
review = Review.new
review.movie_id = params["movie_id"]
review.rating = params["rating"]
review.content = params["content"]
review.save
redirect_to "/reviews"
end
I think that I need to use this information to link a review a user makes in real time to the view page for the movie (just basically building a mini IMDB page with about 12 movies currently)app->views->movies->show.html.erb.
<h2>Reviews</h2>
Do I need to use a params hash with "redirect_to" for the params["content"] above?
I hope this post is helpful to others seeking to gather user data and show in real time on the correct page.
This is reviews->index.
<h1>Reviews</h1>
<% for review in Review.order('created_at desc') %>
<% movie = Movie.find_by(id: review.movie_id) %>
<% if movie != nil %>
<div class="row mb-3">
<div class="col-sm-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<% 1.times do %>
<p>Howdy!</p>
<% end %>
★ ★ ★ ★ ★ ★
<p>
<%#= review.updated_at.strftime("%B %d, %Y %l:%M %P") %>
<%= time_ago_in_words(review.updated_at) %> ago.
</p>
<h6 class="card-subtitle mb-2 text-muted">
<%= movie.title %>
</h6>
</h5>
<p class="card-text">
<%= review.content %>
</p>
</div>
</div>
</div>
</div>
<% end %>
And this is the movies->show.
<% movie_id = params[:id] %>
<% movie = Movie.find_by(id: movie_id) %>
<div class="row">
<div class="col-sm-6">
<h2>
<%= movie.title %>
</h2>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<img src="<%= movie.poster_url %>" class="img-fluid">
</div>
<div class="col-sm-6">
<a href="/movies/<%= movie.id %>/edit" class="float-right">
<i class="fas fa-pen-square"></i>
Edit This Movie
</a>
<% director = Director.find_by(id: movie.director_id) %>
<% if director != nil %>
<p>
Directed by <%= director.name %>
</p>
<% end %>
<p class="lead">
<strong><%= movie.plot %></strong>
</p>
<div class="row mt-3">
<% characters_in_this_movie = Character.where(movie_id: movie.id) %>
<% characters_in_this_movie.each do |character| %>
<% the_actor = Actor.find_by(id: character.actor_id) %>
<div class="col-sm-3 text-center">
<%= image_tag(the_actor.photo_url, class: 'img-fluid mb-3') %>
<br>
<strong><%= the_actor.name %></strong>
<br>
as <%= character.name %>
</div>
<% end %>
</div>
</div>
</div>
<div class="row mt-5 justify-content-center">
<div class="col-sm-6">
<a href="/reviews/new?movie_id=<%= movie.id %>" class="float- right">
<i class="fas fa-pen-square"></i>
Write a Review
</a>
<h2>Reviews</h2>
</div>
</div>

Rails partial view repeat display

Here is part of my index.html
<div class="col-md-8">
<% #books.each do |book| %>
<div class="row">
<div class="col-md-4">
<%= image_from_amazon(book.amazon_id) %>
</div>
<div class="col-md-8">
<h3 class = "text-info">
<%= book.title %>
</h3>
<br>
<em class ="text-muted">
written by <%= book.author %>
</em>
<br>
<br>
<p>
<%= book.description %>
</p>
<% book.genres.each do |genres| %>
<span class="label label-primary">
<%= genres.name %>
</span>
&nbsp
<% end %>
</div>
</div>
<% end %>
</div>
Basically, it will display 3 books, and it works fine.
Then, I move that code into _book.html.erb and edit above code into
<%= render #books %>
However, it repeat 3 times, that is, it display 9 books. And the sequence is [1st,2nd,3rd] [1st,2nd,3rd] [1st,2nd,3rd] like this picture.
Update
update index.html.erb
<div class="clearfix">
<div class="col-md-12">
<%= render #books %>
<div class="col-md-4">
<h3>Genre (Click to filter books)</h3>
<br>
<li>
<span class = 'label label-danger'>
<%= link_to "No filter" ,books_path, style: 'color:#FFFFFD' %>
</span>
<br>
<br>
</li>
<% #genres.each do |genres| %>
<li>
<span class = 'label label-primary' style="color:#FFFFFD">
<%= link_to genres.name ,books_path(filter: genres.name),style: 'color:#FFFFFD' %>
</span>
</li>
<br>
<% end %>
</div>
</div>
<!-- clearfix -->
</div>
Try the following:
<div class="col-md-8">
<%= render #books %>
</div>
And make sure <% #books.each do |book| %> and its <% end %> tag aren't in the partial.
Rendering Collections Docs
Edit
#index.html.erb
<div class="col-md-8">
<%= render #books %>
</div>
# _book.html.erb
<div class="row">
<div class="col-md-4">
<%= image_from_amazon(book.amazon_id) %>
</div>
<div class="col-md-8">
<h3 class = "text-info">
<%= book.title %>
</h3>
<br>
<em class ="text-muted">
written by <%= book.author %>
</em>
<br>
<br>
<p>
<%= book.description %>
</p>
<% book.genres.each do |genres| %>
<span class="label label-primary">
<%= genres.name %>
</span>
&nbsp
<% end %>
</div>
</div>

Resources