Rails how to index with in_groups_of - ruby-on-rails

I am displaying pictures in a view using in_groups_of to create rows of 3. However, I need to do something different to the first item of the first row. How can I target this item?
<% images.in_groups_of(3) do |row| %>
<div class="row">
<% row.each_with_index do |image, index| %>
<div class="item-wrapper">
<% if image %>
<a class="flex-item" <img class="photo" src="<%= image.picture.medium.url %>" alt="" /></a>
<% end %>
</div>
<% end %>
</div>
<% end %>
I want to add this code below every anchor tag except the very first photo in the very first row.
<% if user.eql?(current_user) %>
<button class="btn btn-xs btn-danger delete-image" data-id="<%= image.id %>">
<i class="fa fa-trash-o fa-lg"></i>
</button>
<% end %>

To get the index of the current row, try this:
<% images.in_groups_of(3).each_with_index do |row, row_index| %>
Now you can just check that neither row_index or index are zero, and then print the wanted code.

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 display the last third and forth photos with `#photo.last()`

On my user profile, I want to add 4 of the latest photos uploaded by that user. Originally, I had <%- #user.photos.last(4).each do |photo| %>. This code works, but it doesn't work with my layout. So I need one row that displays the last 2 photos, while the second row displays the last 3-4 photos.
Here is what I came up with and the line <%- #user.photos.last(3,4).each do |photo| %> does not work. I've also tried (3-4)
<div class="photo-box">
<%- #user.photos.last(2).each do |photo| %>
<a href="<%= user_photo_path(#user.username, photo.id) %>" class="photo-thumbnail">
<div class="photo-mini">
<%= image_tag photo.url %>
</div>
</a>
<% end %>
</div>
<div class="photo-box">
<%- #user.photos.last(3,4).each do |photo| %>
<a href="<%= user_photo_path(#user.username, photo.id) %>" class="photo-thumbnail">
<div class="photo-mini">
<%= image_tag photo.url %>
</div>
</a>
<% end %>
</div>
You can use the [] method on the photos array.
-1 gets the last element, -2 gets the 2nd to last, and so on.
#user.photos[-2..-1].each #=> return the last two pictures
Of course, you can simply use the #user.photos.last(2).each in this case.
#user.photos[-4..-3].each #=> return the last 3-4 pictures.
This will throw an error unless #user.photos has a length of at least 4, otherwise, you will be trying to access values that does not exist. So, to check for that, you can wrap the div in an if statement.
<% if #user.photos.length >= 2 %>
<div class="photo-box">
<% #user.photos.last(2).each do |photo| %>
...
<% end %>
</div>
<% end %>
<% if #user.photos.length >= 4 %>
<div class="photo-box">
<% #user.photos[-4..-3].each do |photo| %>
...
<% end %>
</div>
<% end %>
I would get the last four in an array, and then divide them into two sets of two using #in_groups_of.
You can then iterate through the two arrays of two photos each to create the divs. This methods easily extends to n groups of m photos.
Something like:
<%- #user.photos.last(4).in_groups_of(2, false).each do |photo_group| %>
<div class="photo-box">
<%- photo_group.each do |photo| %>
<a href="<%= user_photo_path(#user.username, photo.id) %>" class="photo-thumbnail">
<div class="photo-mini">
<%= image_tag photo.url %>
</div>
</a>
<% end %>
</div>

How to put content under the first record rails 4

I am on Rails 4. I have two resources: subarticles and articles. Subarticles are nested in articles like so:
resources :articles do
resources :subarticles do
member do
put "like" => "subarticles#upvote"
put "dislike" => "subarticles#downvote"
end
end
end
On the articles show page, I display all of the subarticles. However, I would like to place some of the article attributes ( specifically pictures and videos) directly under the first subarticle.
I am having trouble finding any documentation on doing so.
Also note that I have subarticles ordered by number of votes. So if one gets voted higher than the other, it will go to the top. But I want to keep the same pictures and videos right under the first subarticle.
Here is a simplified version of my Article show page:
<div class="row">
<div class="col-md-9">
<div class="well" style="background:white; height:230px">
<%= #article.title.titleize %><br>
<%= social_share_button_tag %>
</div>
<% #subarticles.each do |subarticle| %>
<div class="well" style="background:white">
<%= subarticle.rating %><br>
<%= subarticle.whyrating %><br>
<div class="row" style="margin-top:40px;">
<div class="col-md-7 col-md-offset-1" style="margin-top:30px">
<%= link_to like_article_subarticle_path(#article, subarticle), class: "like", method: :put do %>
<button type="button" class="btn btn-success btn-lg" aria-label="Left Align" style="margin-right:5px">
<span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span> Helpful
</button><span class="badge" style="margin-right:10px"><%= subarticle.get_upvotes.size %></span>
<% end %>
<%= link_to dislike_article_subarticle_path(#article, subarticle), class: "like", method: :put do %>
<button type="button" class="btn btn-danger btn-lg" aria-label="Left Align" style="margin-right:5px">
<span class="glyphicon glyphicon-thumbs-down" aria-hidden="true"></span> Unhelpful
</button><span class="badge"><%= subarticle.get_downvotes.size %></span>
<% end %>
</div>
</div>
</div>
<% end %>
<div class="well" style="background:white; text-align:center">
<h4>Pictures & Videos</h4><br>
<%= image_tag #article.image1(:medium) %><br>
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src="<%= #article.video1 %>"></iframe>
</div>
</div>
</div>
</div>
Because of the #subarticles.each do it will push pictures and videos all the way to the bottom. What is the best way to show just the first subarticle, then pictures & videos, then the rest of the subarticles?
Let me know if I need to show any other code.
<% #subarticles.each_with_index do |subarticle, i| %>
<div class="well" style="background:white">
....... // subarticle contents
</div>
<% if i==0 %>
// put articles content here
<% end %>
<% end %>
In that way after the first subarticle the if condition checks the loop index, as the loop index is currently 0, then it will first show the subarticle first content, then for index 0 it shows the article contents.
You can always use a flag for that:
<% first_one = false %>
<% #subarticles.each do |subarticle| %>
<div class="well" style="background:white">
...
</div>
<% unless first_one %>
// article contents here....
<% first_one = true %>
<% end %>
<% end %>

Trying to have a view & block have access to a variable from a another block that is used to determine which element number in array

I am newer to rails: My side navigation partial takes each step and provides an icon and a link for it. I would like for the current active step, to have the same icon in the top navigation as the side navigation. However, <%= icon[i] %> will not work since [i] comes from a different block in a different view. How would I make it so that the active link top's navigation has the same icon[i] as the side navigation without having access to i? See below.
_side_navigation.html.erb
<% icon= ["icon-link", "icon-bar-chart", "icon-edit", "icon-beaker","icon-link", "icon-bar-chart", "icon-edit", "icon-beaker"] %>
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<li class="<%= nav_active step %>">
<a href = "
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% when 'excel' %>
<li class="<%= nav_active step %>">
<i class="<%= icon[i] %> icon-2x"></i> **<<I need this [i] in the other partial so I know which element of the array is chosen**
<span>Step <%= i %> </span>
</a>
</li>
<% else %>
<li class="<%= nav_active step %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %></span>
</a>
</li>
<% end %>
<% end %>
_top_navigation.html.erb
<div class="area-top clearfix">
<div class="pull-left header">
<% case #step.media_type %>
<% when 'video' %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i> <<<here is the problem since, it does not have access to the current "i" from the other block
Video
</h3>
<h5>
A video for the course is here
</h5>
<% when 'excel' %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i>
Excel
</h3>
<h5>
Please use the excel sheet below to complete the challenge.
</h5>
<% else %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i>
Multiple Choice
</h3>
<h5>
Please choose from a selection below
</h5>
<% end %>
</div>
Is there no natural order to these steps? You don't have an 'i' you can pass in when you include the partial (partial local variables)?
If not, it sounds like you need a slightly smarter 'Step' object that is aware of its index in the workflow.
You could also place the icon list in a helper, like so:
def icons
["icon-link", "icon-bar-chart", "icon-edit",
"icon-beaker","icon-link", "icon-bar-chart",
"icon-edit", "icon-beaker"]
end
Gets it out of your view.
Since I am newer to rails, I feel like this is a hack way of doing it but nonetheless works. I created the method below, which essentially takes in the step, and if it is the active step, save the current index to a variable. There is a method within that, which returns the variable while not requiring any inputs (so as to be able to be used freely)
def nav_active_icon(step, i)
#x = i if params[:id].to_s == step.id.to_s
def display
return #x
end
end
At the bottom, it takes in the step and the index for the method above
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<li class="<%= nav_active step %>">
<span class="glow"></span>
<a href = "
<%= course_level_step_path(#course.id, #level.id, step.id) %>" >
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% nav_active_icon(step, i) %>
Here it outputs the current index for the active step in display (in a different view from the block)
<% when 'excel' %>
<h3 class="title">
<i class="<%= icons[display] %>"></i></i>
Excel
</h3>
<h5>
Please use the excel sheet below to complete the challenge.
</h5>

Twitter Bootstrap Caurosel.js and Rails

How to realize TwitterBootstrap.Carousel.js "active item" tag in Rails to work everything right?
This recipe:
<div id="myCarousel" class="carousel">
<!-- Carousel items -->
<div class="carousel-inner">
<div class="active item">…</div>
<div class="item">…</div>
<div class="item">…</div>
</div>
<!-- Carousel nav -->
<a class="carousel-control left" href="#myCarousel" data-slide="prev">‹</a>
<a class="carousel-control right" href="#myCarousel" data-slide="next">›</a>
</div>
How to mix it with following one:
<% #items.each do |item| %>
<% item.item_images.each do |item_image| %>
<%= link_to(image_tag(item_image.image.url), item_image.image.url) %>
<% end %>
<% end %>
You need to add the class of active only to the first item in your list, otherwise they'll all show. I got around this by utilizing each_with_index.
<% #items.each do |item| %>
<% item.item_images.each_with_index do |item_image, index| %>
<div class="<% if index == 0 %>active<% end %>">
<%= link_to(image_tag(item_image.image.url), item_image.image.url, ) %>
</div>
<% end %>
<% end %>
Of course, this can be refactored quite a bit.

Resources