How do I close the container <div> in a loop? - ruby-on-rails

I have a list of products and I want to show an ad in the product feed.
I want something like:
<div id="container">
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
</div>
<div id="add">
Adsense Stuff
</div>
<div id="container">
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
<div id="product">Bla..</div>
</div>
In ERB, I would have:
<div id="container">
<% productes.each_with_index do |product,index| %>
<div id="product"><%= product %></div>
<% if index == 2 %>
</div>
<div id="add">
Adsense Stuff
</div>
<div id="container">
<% end %>
<% end %>
</div>
How you translate this to Haml or Slim?
I don't want to break the loop in two loops for two reasons: I don't know the products count by page and I have some more elaborate code which uses the same HTML tricks with the Rails cycle() helper. So, it will help me a lot to find a trick to make it possible.

Haml lets you write raw HTML as output when you want it. Although weird, you can use this to achieve your goals here, as you did with Erb:
TEMPLATE = '
.container
- products.each_with_index do |product,index|
- if index == 2
</div>
<div class="ad">AdSense Stuff</div>
<div class="container">
.product<
= product
'
require 'haml'
products = %w[ cat box kitten shoes hounds ]
puts Haml::Engine.new(TEMPLATE).render binding
#=> <div class='container'>
#=> <div class='product'>cat</div>
#=> <div class='product'>box</div>
#=> </div>
#=> <div class="ad">AdSense Stuff</div>
#=> <div class="container">
#=> <div class='product'>kitten</div>
#=> <div class='product'>shoes</div>
#=> <div class='product'>hounds</div>
#=> </div>
The indentation looks weird, but you can see that you have two containers with the AdSense stuff outside either.

In HAML
-products.each_with_index do |product,index|
.product= product
-if index == 2
.ad= Adsense Stuff
I wouldn't bother with the container, just set up the css to deal with the product and ad classes. (Which also brings up the fact that you have multiple ids of the same name, these should be changed to classes).

- products.each_with_index do |product,index|
.product
= product
- if index == 2
.ad= Adsense Stuff
This should do it?

A possible Haml solution, using the surround helper:
.container
-products.each_with_index do |product,index|
.product=product
-if index == 2
=surround "</div>", "<div class='container'>" do
.add
Adsense stuff
This is a bit of a hack, in that we're "faking" closing and opening the container div; as far as Haml knows we're still in it. For this reason it also introduces a bit of repetition in that you have to specify the "container" class (and any other attributes that div might have) in two places.
This solution is similar to #Phrogz's solution but this is a bit more "Haml-ly" and allows you to use Haml syntax to define the add div.

Related

4 graphs for each user, need to show the fourth graph in different layout

In my app each user has 4X graphs to display.
I'm displaying 3X col-md-4 graphs for each user through the each loop below.
This code is in my view.
<div class="row">
<div class="container">
<% #user_overviews.each do |overview| %>
<div class="col-md-4 text-center">
<h4><%= overview.title %></h4>
<%= raw overview.graph%>
</div>
<% end %>
</div>
</div>
the problem is that I need to be able to show a fourth graph below the other three graphs in a col-md-12.
I'm using active admin to upload the graphs, so the four graphs for user 1 have ID 1,2,3,4 and the next four graphs for user 2 have ID 5, 6, 7, 8 and so on.
So in graph 4 and 8 are the once that should be displayed in the col-md-12
I find it hard to get around how I can display graph 4 and 8 in a col-md-12
can someone advise me on how I would do that?
First of all (unless I'm missing something), the row div should be the child of the container div.
Given that the overviews will always be of fixed sized 4, try using the each_with_index method as shown below:
<div class="container">
<div class="row">
<% #user_overviews.each_with_index do |overview, index| %>
<div class="col-md-<%= index == 3 ? '12' : '4' %> text-center">
<h4><%= overview.title %></h4>
<%= raw overview.graph%>
</div>
<% end %>
</div>
</div>
If each user has exactly 4 overviews, probably a simple solution is to iterate over all except the last one and then put another row for the last overview. You will need another row anyway if you want to have col-md-12.
Also, I think the container div has to wrap everything else.
Something like this maybe:
<div class="container">
<div class="row">
<% #user_overviews[0...-1].each do |overview| %>
<div class="col-md-4 text-center">
<h4><%= overview.title %></h4>
<%= raw overview.graph %>
</div>
<% end %>
</div>
<div class="row">
<div class="col-md-12 text-center">
<h4><%= #user_overviews.last.title %></h4>
<%= raw overview.graph %>
</div>
</div>
</div>
Edit: Lazarus' solution is more DRY, so I think it's better.

conditionally closing div haml

I need to achieve this
<div class="row">
<div class="col-sm-3">
<div class="row">1</div>
<div class="row">2</div>
</div>
<div class="col-sm-3">
<div class="row">3</div>
<div class="row">4</div>
</div>
<div class="col-sm-3">
<div class="row">5</div>
<div class="row">6</div>
</div>
<div class="col-sm-3">
<div class="row">7</div>
<div class="row">8</div>
</div>
</div>
if i % 2 == 0
then close existing .col-sm-3 and add a new one in HAML
I couldn't able to close div tag when the condition met,
I tried using
yield_content
but no avail, any help is appreciated.
and I need to loop through this array
facilities.each do |value|
How about splitting array using in_groups_of? E.g.:
.row
- values.in_groups_of(2, false).each do |group|
.col-sm-3
- group.each do |value|
.row= value
I would probably do something like this:
- [[0,1],[2,3],[4,5]].each do |group|
%div.col-sm-3
%div= group[0]
%div= group[1]
How I would create the array depends on what your actual data is and where it comes from.

Rails outputting two images when just one is wanted

I am currently working on a project that requires me to create a (real) estate agent website. I have imported an XML list with all the properties and created the database, but when I go to create a properties list and insert the first image for each property, it creates two images (one for each property in the list) and assigns both images to each property.
The code is:
<% #properties.each do |property| %>
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-3">
<% property.pictures.each do |picture| %>
<% if picture.name.eql?('Photo 10') %>
<img src="<%= picture.url %>" class="img-responsive center-block"/>
<% end %>
<% end %>
</div>
<div class="col-sm-9">
<h4><%= property.advert_heading %></h4>
<p><%= property.main_advert %></p>
</div>
</div>
</div>
</div>
<% end %>
The html output is:
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-3">
<img href="http://med01.expertagent.co.uk/in4glestates/{376a3e5b-f940-4181-bc8e-255859c03e51}/{0b306ad6-63d3-4af2-a3ac-0dfa0885b724}/main/P1000507.jpg" class="img-responsive center-block"/>
<img href="http://med01.expertagent.co.uk/in4glestates/{376a3e5b-f940-4181-bc8e-255859c03e51}/{5004cf3b-e189-48e9-a1a6-f029e402ddd3}/main/P1000507.jpg" class="img-responsive center-block"/>
</div>
<div class="col-sm-9">
<h4>Pen Y Bryn, Llanfairfechan</h4>
<p>A semi detached three bedroom family home located in a quiet cul de sac in the upper part of the village of Llanfairfechan. The property benefits from double glazed windows, gas central heating, gardens to front and rear. This would make an ideal family home or investment property.</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-3">
<img href="http://med01.expertagent.co.uk/in4glestates/{376a3e5b-f940-4181-bc8e-255859c03e51}/{0b306ad6-63d3-4af2-a3ac-0dfa0885b724}/main/P1000507.jpg" class="img-responsive center-block"/>
<img href="http://med01.expertagent.co.uk/in4glestates/{376a3e5b-f940-4181-bc8e-255859c03e51}/{5004cf3b-e189-48e9-a1a6-f029e402ddd3}/main/P1000507.jpg" class="img-responsive center-block"/>
</div>
<div class="col-sm-9">
<h4>33, Pen Y Bryn, Llanfairfechan LL33 0UH</h4>
<p>A semi detached three bedroom family home located in a quiet cul-de-sac in the upper part of Llanfairfechan village. The property benefits from double glazed windows, gas central heating, gardens to front and rear. Restrictions apply. Application fees apply. Deposit: &pound;750.</p>
</div>
</div>
</div>
</div>
To me it seems that rails is looping throught the property.picture.each twice (or I'm guessing more if I had more properties) and inserting the output twice but I can't see why.
Many thanks
It looks like you have duplicate pictures with a name attribute of 'Photo 10'. Use your rails console to run a query to confirm this.
Picture.where(name: 'Photo 10').count
How many records are returned? Is your expectation that each property would have one picture with a name of 'Photo 10'? If so you you should expect to have as many pictures returned as properties, if not then you have duplicate entries with the name 'Photo 10' for each property. which brings me to my next point.
You should normalize your database. The fact that you are relying on a non unique attribute, and that there are multiple picture entries that point to the same url tells me that. You are also creating a lot of unnecessary picture entries in the picture table. Instead, I'd create a join table between between properties and pictures, maybe called PropertyPictures. For each unique picture url, create one entry in the Picture table. For each property that uses a picture, create an entry in the join table with that property_id and the desired picture's picture_id. This will help in case your pictures change. As you have it now, if one picture url changes it doesn't change in all places, even if it should. As far as your view goes, now that you have a unique and consistent picture_id, use that, it will be impossible to have duplicates. Also, instead of pulling all pictures, just get the one you want. You could write a method in your property model to do this. It might look like this:
def special_picture
pictures.where(id: 1)
end
And in your view:
<% #properties.each do |property| %>
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-3">
<img src="<%= property.special_picture.url %>" class="img-responsive center-block"/>
</div>
<div class="col-sm-9">
<h4><%= property.advert_heading %></h4>
<p><%= property.main_advert %></p>
</div>
</div>
</div>
</div>
<% end %>
`
If you're only wanting the first image for each listing, why are you looping through all pictures for each listing?
You could do this instead:
<div class="col-sm-3">
<img src="<%= property.pictures.first.url %>" class="img-responsive center-block"/>
</div>

Reading erb form fields, Rails4

Question about Rails4, I trying to retrieve the "Find Stuff" variable, in the erb form. This
is a search field, using zurb foundation - so the extra styling annotations floating around.
I don't have a model as this is just a form for reading the search input field - which is
in the tag, with placeholder as "Find Stuff".
To use normal Rails4 terminology, I would
like to pass the value of the "Find Stuff" field to the salutation controller, and I tried
many ways, but was unsuccessful, when I used render params[:post].inpect, it shows nil -the
variables that I pass to the controller, on clicking on the "Search" link_to, link. I tried adding an id field to the tag, and that too showed nil on render params[:post].inspect.
Any help, thanks in anticipation.
hello.html.erb form below.
<html>
<body>
<nav class="top-bar" data-topbar>
<ul class="title-area">
<li class="name">
<h1>Hello World!</h1>
</li>
<li class="toggle-topbar menu-icon"><span>Menu</span>
</li>
</ul>
<ul class="right">
<li class="has-form">
<div class="row collapse">
<div class="large-8 small-9 columns">
<input type="text" placeholder="Find Stuff" >
</div>
<div class="large-4 small-3 columns">
<%= link_to "", :controller =>
'salutation', :action =>'hello',
:class=>"alert button expand" %>
</div>
</div>
</li>
</ul>
</section>
</nav>
</body>
</html>
Controller follows
Salutation Controller follows
class SalutationController < ApplicationController
def new
#test = ''
end
def hello
#message = 'Hello World!'
#test = params[:Find_Stuff]
end
end
Wrap your search box in a form element, give your input a name and away you go. You can use the rails form helpers as well - see http://guides.rubyonrails.org/form_helpers.html which has a nice intro to creating a search form
<div class="row collapse">
<%= form_tag("/salutation/hello", method: "post") do %>
<div class="large-8 small-9 columns">
<%= text_field_tag(:find_stuff) %>
</div>
<div class="large-4 small-3 columns">
<%= submit_tag("Search") %>
</div>
<% end %>
</div>
Further to #slapthelownote's answer, the reason you're getting an error is because you're not passing any params to your controller
We've got something like what you want working at http://firststopcosmeticshop.co.uk (top search box) -- using a form_tag
If you want to see live code, I'll be happy to post!
Params
Using a form allows you to set various variables & then submit them to the controller as you've set them. I'd recommend using the form in the other answer, but to understand how it works, you need to read up on the Rails forms tutorial
Basically, the params hash is populated in the middleware of Rails -- from any data sent by HTTP to your backend
With links, you can only send GET params (domain.com/route&params=value), whilst with HTML forms, you can set POST params which are passed through the browser (not the URL)

Need to move node inside another using Nokogiri, then iterate through the node's contents in view

Thanks for reading. Super frustrated (and maybe missing something fundamental, I've never been great with Nokogiri)
In short - I have a source:
<div class="schedule-page">
<h3>Sunday, September 1, 2013</h3>
<table class="views-table cols-1 schedule-table">
<div class="game">Game 1</div>
<div class="game">Game 2</div>
</table>
<h3>Sunday, September 7, 2013</h3>
<table class="views-table cols-1 schedule-table">
<div class="game">Game 1</div>
<div class="game">Game 2</div>
<div class="game">Game 3</div>
</table>
<!--and so forth.... -->
</div>
I am able to iterate through the source, grab each day and X number of games, and create the container for each day and fields for each game.
<% #schedule_array.each do |a_game| %> #
<div class="game-info">
<div class="date"><%= #the_date %></div>
<div class="single-game"> # this pulls info for each game, works fine.
<div class="game-home"><%= a_game.css('.field-home-team').text %></div>
<div class="game-score"><%= a_game.css('.field-score').text %></div>
<div class="game-away"><%= a_game.css('.field-away-team').text %></div>
<div class="game-time"><%= a_game.css('.field-game-date-start-time').text %</div>
</div>
</div>
<%end%>
But I really don't know how to retrieve the original date (h3) from the source and parse it in such a way so that I can use it as shown above.
I've tried a dozen variations of the example shown under Moving Nodes, here:
http://nokogiri.org/tutorials/modifying_an_html_xml_document.html
But nothing's working. Can anyone tell me the correct way to handle this? My method is gibberish and I'm not sure it's helpful to put it up.
I assume #schedule_array is coming from something like #schedule_array = Nokogiri::HTML( html_contents).css('.schedule-table').
In which case, you need to traverse back to the parent and go back to it's previous sibling and get the value:
game_date = a_game.parent.previous_element.text
So in your particular case, that line can be:
<div class="date"><%= a_game.parent.previous_element.text %></div>

Resources