Dynamically Render Database Records in Rails using Bootstrap Tabs - ruby-on-rails

I'm hoping to be able to render a tab for each of my project tasks. Currently, the only tab active is the first one (which I'm not terribly surprised since I'm including my index == 0 condition on the tabpanel div, but in my tinkering I haven't been able to select the proper tab) How can I change this to render the proper project task when selected? Is there an effective way to render this kind of content without using AJAX?
<div class='well col-xs-8 col-xs-offset-2'>
<ul class="nav nav-pills" role="tablist" id="myTabs">
<% #project.tasks.each_with_index do |task, index| %>
<li role="presentation" class="tab-pane <%= 'active' if index == 0 %>">
<a href="#<% task.title %>" aria-controls="<% task.title.downcase %>"
role="tab" data-toggle="tab"><%= task.title %></a>
</li>
<% end %>
</ul>
<div class="tab-content">
<% #project.tasks.each_with_index do |task, index| %>
<div role="tabpanel" class="tab-pane fade in <%= 'active' if index == 0 %>" id="<%= task.title.downcase %>">
<p><%= task.title %></p>
</div>
<% end %>
</div>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" %>
<%= javascript_include_tag "//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" %>
</div>
In this case, the tab body should read 'Support'

I would like to suggest using id with index number as shown in code below I merge the id with rails code <%=#{index}%>
below is some code sample that I created based your code above
<div class="panel with-nav-tabs panel-info">
<div class="panel-heading">
<ul class="nav nav-tabs">
<% #project.tasks.each_with_index do |task, index| %>
<% if index == 0 %>
<li class="active"><p><%= task.title %></p></li>
<% else %>
<li><%= task.title %></li>
<% end %>
<% end %>
</ul>
</div>
<div class="panel-body">
<div class="tab-content">
<% #project.tasks.each_with_index do |task, index| %>
<% if index == 0 %>
<div class="tab-pane fade in active" id="tab<%=#{index}%>">
<p><%= task.title %></p>
</div>
<% else %>
<div class="tab-pane fade" id="tab<%=#{index}%>">
<p><%= task.title %></p>
</div>
<% end %>
<% end %>
</div>
</div>

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

Best way to show empty lists in Rails

I have been working to follow the best practices in Rails in order to save time in the future.
I am displaying all terms in a view which has more than 0 results.
<% #terms.each do |t| %>
<li class="media">
<div class="media-body">
<div class="media-heading text-semibold"><%= link_to "#{t.name}", authenticated_root_path %></div>
<span class="text-muted"><%= link_to 'Settings', edit_account_term_path(#account, t) %></span>
</div>
</li>
<% end %>
What is the best way to display a different view if the term count is zero? I could do something like a simple if statement in the view doing a count but that seems cluttered. Any suggestions?
How about this:
<% #terms.each do |t| %>
<li class="media">
<div class="media-body">
<div class="media-heading text-semibold"><%= link_to "#{t.name}", authenticated_root_path %></div>
<span class="text-muted"><%= link_to 'Settings', edit_account_term_path(#account, t) %></span>
</div>
</li>
<% end.empty? and begin %>
<li class="media">
<!-- nothing to see -->
</li>
<% end %>
You can also move the code to a partial.
<%= render(:partial => 'terms', :collection => #terms) || 'There are no terms' %>
The partial:
<li class="media">
<div class="media-body">
<div class="media-heading text-semibold"><%= link_to "#{term.name}", authenticated_root_path %></div>
<span class="text-muted"><%= link_to 'Settings', edit_account_term_path(#account, term) %></span>
</div>
</li>
</li>

How do I detect the first iteration within my view? (Rails 4)

In my view I have:
<div class="item active">
<%= image_tag "2.jpg",size: "500x300", class: "no-resize" %>
<div class="carousel-caption">
Some tag.
</div>
</div>
<% #photos.each do |photo|%>
<div class="item">
<%= image_tag photo.attachment.url,size: "500x300",class: "no-resize" %>
<div class="carousel-caption">
Some tag.
</div>
</div>
<% end %>
Is there DRYer way of accomplishing this (as the only change I make is adding the class 'active' for the first photo) i.e. can I put the first item within the loop and detect the first iteration?
Try each_with_index
<% #photos.each_with_index do |photo, i |%>
<div class="item <%= "active" if i.zero? %>">
<%= image_tag photo.attachment.url,size: "500x300",class: "no-resize" %>
<div class="carousel-caption">
Some tag.
</div>
</div>
<% end %>
['apple', 'orange', 'pear'].each_with_index do |fruit, index|
p "first is #{fruit}" if index == 0
p fruit
end

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