How to access a single attribute of associated model inside a loop? - ruby-on-rails

I extremely need your assistance. I have many to many :through relationship models: Product, Category and Categorization(as intermediate model). In my view I want to iterate through #products and fetch category's
field "title" on each iteration.
Here's my view:
<div class="col-md-9">
<div class="row">
<section id="projects">
<ul id="thumbs">
<!-- Item Project and Filter Name -->
<% #products.each do |product| %>
<% product.categories.each do |category| %>
<li class="item-thumbs col-md-4 <%= category.title %> ">
<% end %>
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="The City" >
<span class="overlay-img"></span>
<%= icon 'font-icon-plus' %>
</a>
<!-- Thumb Image and Description -->
<%= image_tag product.product_images, alt: product.description %>
<p><%= product.price %></p>
</li>
<!-- End Item Project -->
<% end %>
</ul>
</section>
</div>
As you see, I need to get category's title on each iteration so as to insert it to li "class" and link each product tab to a menu "li".
The problem is that when I iterate through #categories inside #products loop, it executes just once therefore I don't get category's title for each product.

It looks to me like your loop is repeatedly creating the opening li tag rather than collecting all the category titles like you want, resulting in invalid HTML. Try writing your markup like so instead:
<div class="col-md-9">
<div class="row">
<section id="projects">
<ul id="thumbs">
<!-- Item Project and Filter Name -->
<% #products.each do |product| %>
<!-- RELEVANT CHANGES RIGHT HERE! -->
<li class="item-thumbs col-md-4 <%= product.categories.pluck(:title).join(' ') %>">
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="The City" >
<span class="overlay-img"></span>
<%= icon 'font-icon-plus' %>
</a>
<!-- Thumb Image and Description -->
<%= image_tag product.product_images, alt: product.description %>
<p><%= product.price %></p>
</li>
<!-- End Item Project -->
<% end %>
</ul>
</section>
</div>
</div>
This uses Rails' handy pluck method to grab all the relevant category titles directly from the database, then joins them together with spaces to make a valid class string. Is this the effect you were looking for?

Related

How to display specific range in do loop in Ruby?

I'm having trouble display specific range of data in do-loop in Ruby.
I Have this example code:
Post
<!-- Display loop only 9 sections -->
<div class="row">
<% #post.each do |post| %>
<div clas="blog">
<h3 class="heading"><%= post.title %></h3>
</div>
</div>
<!-- END => Display loop only 9 sections -->
<div class="row">
<div clas="banner">
<img src="images/banner.jpg" alt="banner">
</div>
</div>
<!-- Continue display loop for 10 and until latest sections -->
<div class="row">
<% #post.each do |post| %>
<div clas="blog">
<h3 class="heading"><%= post.title %></h3>
</div>
</div>
<!-- END => -->
In this situation I want to add a banner section after it displays 9 posts:
<div class="row">
<% #post.each do |post| %>
<div clas="blog">
<h3 class="heading"><%= post.title %></h3>
</div>
</div>
<!-- END => Display loop only 9 sections -->
<!-- I will add this banner section after posts displays 9 posts -->
<div class="row">
<div clas="banner">
<img src="images/banner.jpg" alt="banner">
</div>
</div>
and then I want to continue the post display from post 10 up to latest posts after I added the banner section:
<!-- Continue display loop for 10 and until latest sections -->
<div class="row">
<% #post.each do |post| %>
<div clas="blog">
<h3 class="heading"><%= post.title %></h3>
</div>
</div>
<!-- END => -->
In my situation, the two post sections will display all the data in post. How do you limit 9 posts in the 1st div element, and continue the latest posts in the 3rd div element below the banner section using the do loop? I want to continue the latest posts in my 3rd section.
Is there any easy way to do this?
I'm currently new to rails app and I'm still exploring the syntax of the program.
You can use .each_with_index method to determine if this exact element of the collection is 9th, here is the documentation link: https://ruby-doc.org/core-2.7.1/Enumerable.html#method-i-each_with_index
<!-- Display loop only 9 sections -->
<div class="row">
<% #post.each_with_index do |post, index| %>
<div clas="blog">
<h3 class="heading"><%= post.title %></h3>
</div>
</div>
<% if index == 8 %>
<div class="row">
<div clas="banner">
<img src="images/banner.jpg" alt="banner">
</div>
</div>
<% end %>
<% end %>
Something like this should work
For the first 9 posts:
<% #post.limit(9).each do |post| %>
And the other posts below the banner:
<% #post.drop(9).each do |post| %>
Maybe:
<% #post[0..8].each do |post| %>
...
<% #post[9..-1].each do |post| %>
or:
BANNER_POSITION = 9
<% #post[0...BANNER_POSITION].each do |post| %>
...
<% #post[BANNER_POSITION..-1].each do |post| %>

Rails - How To Transfer Data With Button Press

I'm very new to Rails, so this has been tough for me to understand. The front end guy in my group for a school project designed this so that when I tap the "More Info" button on a displayed product, a pop up box shows up on the screen with more information about the product.
How do I make the selected product's info accessible to me so I could display it in the pop up box? I've tried button_to with an :action but I apparently needs a view template, but I don't want that. I simply want to display the selected product's info in the pop up box that shows up when the user taps the "More Info" button.
This is the code I'm working with:
<!-- Container for the Catalog Content -->
<div class="Catalog_page">
<!-- List all products -->
<% #products.each do |product| %>
<div class="product_item">
<span class="img"><%= image_tag product.image, size: "200x100" %></span>
<h1><%= product.name %></h1>
<!--<%= product.description %> Saved this just incase we needed it-->
<%= number_to_currency(product.price) %>
<!-- Button that creates light box -->
<button class="lightbox" id="button">More Info</button>
</div>
<%end%>
<!-- backdrop is the black background of lightbox -->
<div class="backdrop"></div>
<!-- the box that we need to plug information to -->
<div class="box"><div class="close"></div>
I DON'T KNOW HOW TO PULL THIS INFORMATION FROM DATA BASE
</div>
</div>
There are two ways to do your task:
You can render these "more info" and keep it hidden, and then you show the modal these info.
<% #products.each do |product| %>
<div class="product_item">
<span class="img"><%= image_tag product.image, size: "200x100" %></span>
<h1><%= product.name %></h1>
<!--<%= product.description %> Saved this just incase we needed it-->
<%= number_to_currency(product.price) %>
<!-- Button that creates light box -->
<!-- here is the link for each product to open its modal -->
<a data-toggle="modal" data-target="#more-info-<%= product.id %>" class="lightbox">More Info</a>
<!-- here is the modal content -->
<div id="more-info-<%= product.id %>" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">More Info</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
</div>
<% end %>
Or you can fetch these info by ajax and then show it on the modal
<% #products.each do |product| %>
<div class="product_item">
<span class="img"><%= image_tag product.image, size: "200x100" %></span>
<h1><%= product.name %></h1>
<!--<%= product.description %> Saved this just incase we needed it-->
<%= number_to_currency(product.price) %>
<!-- Button that creates light box -->
<button class="lightbox fetch-info" data-product-id="<%= product.id %>">More Info</button>
</div>
<%end%>
<!-- backdrop is the black background of lightbox -->
<div class="backdrop"></div>
<!-- the box that we need to plug information to -->
<div class="box"><div class="close"></div>
<div id="fetch-result"></div>
</div>
and then, create a JS to fetch the data:
$(".fetch-info").click(function() {
var $input = $(this);
$.ajax({
type: "GET",
url: "/product_info",
data: {
id: $input.data("product-id")
},
success: function(response) {
$("#fetch-result").html(response);
}
});
});
Then, create an action to provide the product info:
def product_info
#product = Product.find(params[:id])
render layout: false
end
and create your view with your custom product info...
That's it!
Tip: if you choose the second option, you can improve by calling the action as JSON (fetch just the product info, and then in your success callback, you add the html there)
This is an index page, www.example.com/products. It is showing a list of the products and when clicked they will open a lightbox. What you are going to have to do is pass the id of each individual product into the button so that when the lightbox is opened it is showing the correct information for that product. Alessandro's code is not going to help you because product.attribute1 will not be defined.

Dashing - reorder/sorting widgets

is it possible to reorder/move widgets by given property on the dashboard ?
i am adding widgets dynamically to the dashboard by pushing data from a job to the erb file:
<div class="gridster">
<ul>
<% settings.servers.each do |data| %>
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
<div data-id="<%=data['webHost']%>" data-title="<%=data['name']%>" data-version="<%=data['Version']%>" >
</li>
<% end %>
</div>
You can organize your widgets changing data-row and data-col.
If there are some property on your data that can be used to sort them the widgets, you could use it on data-row and data-col
Ex.:
<% settings.servers.each do |data| %>
<li data-row="<%= data['row'] %>" data-col="<%= data['col'] %>" data-sizex="1" data-sizey="1">
<div data-id="<%=data['webHost']%>" data-title="<%=data['name']%>" data-version="<%=data['Version']%>" >
</li>
<% end %>

Each_with_index not working properly

I m using carousel to display the images. I ve uploaded the images in the cloud. But somehow it is repeating it self.
Here is my code
div id="myCarousel" class="carousel slide">
<div class="carousell-inner">
<% #img.each_with_index do |i|%>
<% if i.gallery == "Art"%>
<div class="active item">
<%= image_tag (i.image.url) %>
</div>
<% i.next%> <!-- For incrementing the i value but it is not working-->
<div class="item">
<%= image_tag (i.image.url)%>
</div>
<%end%>
<%end%>
</div>
</div>
What i want is in the active item it should display the first url of the image array and in the inactive item (which ll be active afterwards) should have the other images. It should not repeat the images. Here it is repeating the image since the value of i is not changing.
I am starting to understand what you want :)
You can make your logic very simple, if you will separate your data.
<div id="myCarousel" class="carousel slide">
<div class="carousell-inner">
<% #img.keep_if{|i| i.gallery == "Art"}.each do |i|%>
<div class="active item">
<%= image_tag (i.image.url) %>
</div>
<%end%>
<% #img.keep_if{|i| i.gallery != "Art"}.each do |i|%>
<div class="item">
<%= image_tag (i.image.url)%>
</div>
<%end%>
</div>
</div>
And better to prepare your data in controller, not in view.
I first thought you needed each_with_index, but actually, you are only interested in images from the Art gallery, no telling if the first image is actually an Art image, so I tried as follows:
<div id="myCarousel" class="carousel slide">
<div class="carousell-inner">
<% art_images_counter = 0 %>
<% #img.each do |image|%>
<% if image.gallery == "Art" %>
<% if art_images_counter == 0 %>
<div class="active item">
<%= image_tag (image.image.url) %>
</div>
<% else %>
<div class="item">
<%= image_tag (image.image.url)%>
</div>
<% end %>
<% art_images_counter += 1 %>
<%end%>
<%end%>
</div>
</div>
Hope this helps.
ive found out the answer by doing it manually. First of all in the controller i ve found out all the images which belong to the Art Gallery by this code.
#image = Image.find_all_by_gallery("Art")
Now to display the first element of the array #image, we can use the simply #image.first and then we can call that first element of the array in the active item of carousel. Then for the item part the basic thing to understand is that if we directly call and display all the elements of the array then the first element of the array will also be display in this part. So the repetition can happen. To avoid this we can do like this:
i = #image.count
#image[1..i]
So that the first element will not repeat in the `item' part of the carousel.
Hope it might help others. Thanks for giving time.

How can I display every 4th product with different markup?

I'm just starting out with Ruby from a java background. I'm trying to code a particular loop but can't figure out the right syntax:
Could someone help me troubleshoot this please? I'm trying to write a loop but use different css classes to change the style of each block.
Realise this is probably easy, but help is appreciated....
<%= #products.each do |product, i| %>
<% if i % 1 %>
<div class="items-row clearfix">
<div class="one_fourth">
<div class="item-thumb">
<img src="<%= image_path "thumb.png" %>" alt="" class="thumb" width="162" height="230" />
</div>
<p><%= product.name %></p>
<p class="bold">$79.95 AUD</p>
<p class="color-wrap">
<span class="color" style="background:#ddd;"></span>
<span class="color" style="background:#f9f9f9;"></span>
<span class="color" style="background:green;"></span>
<span class="color" style="background:red;"></span>
</p>
</div>
<% elsif i % 4 %>
<div class="one_fourth last">
<div class="item-thumb">
<img src="<%= image_path "thumb.png" %>" alt="" class="thumb" width="162" height="230" />
</div>
<p><%= product.name %></p>
<p class="bold">$79.95 AUD</p>
</div>
</div><!-- end row -->
<% else %>
<div class="one_fourth">
<div class="item-thumb">
<img src="<%= image_path "thumb.png" %>" alt="" class="thumb" width="162" height="230" />
</div>
<p>Item Name</p>
<p class="bold">$79.95 AUD</p>
</div>
<% end %>
<% end %>
You can do something like this using cycle:
<% products.each_slice(4) do |slice| %>
<div class="items-row clearfix">
<% slice.each_with_index do |product,i| %>
<div class="one_fourth <%= cycle("first", "second", "third", "fourth") %>">
<%= render product %>
<% if i != 3 %>
<p class="color-wrap">
<span class="color" style="background:#ddd;"></span>
<span class="color" style="background:#f9f9f9;"></span>
<span class="color" style="background:green;"></span>
<span class="color" style="background:red;"></span>
</p>
<% end %>
</div>
<% end %>
</div>
<% end %>
_product.html.erb:
<div class="item-thumb">
<img src="<%= image_path "thumb.png" %>" alt="" class="thumb" width="162" height="230" />
</div>
<p><%= product.name %></p>
<p class="bold">$79.95 AUD</p>
Rather than if/else statements and CSS markup in your views, you should probably externalize your CSS, make a few partials, and make use of ActionView::Helpers::TextHelper#cycle. For example:
<%= #products.each do |product| %>
<div class="<%= cycle('first', 'second', 'third', 'fourth') -%>">
<!-- 1. let the CSS class handle display differences -->
<!-- 2. render a partial based on #current_cycle -->
<%= render :partial => current_cycle %>
</div>
<% end %>
I'd say the mod's are your problem. It's never going to go into the first block as n%1 will always return 0. Try your logic out using irb to get you going.
You may want to try jQuery nth-child
I got part of the answer. Slight change of syntax to use "each_with_index" instead of just each.
Still trying to work out there's a lot of variations of when a product can be the last tile and require closing, first on row, first in set, last in a row.....
Thanks guys, I think I've answered my own question.

Resources