Elegant way to print HTML Lists with Ruby + ERB - ruby

I have the following code
<% if items.any? %>
<ul class="level1">
<% items.each do |item| %>
<li class="item">
<%= item.text %>
</li>
<% end %>
</ul>
<% end %>
While this works, I was wondering if there was a way to make it more elegant. The if and then each is not very pretty...
Anyone knows a more elegant syntax?

Try this, based on:
<% content_tag(:ul, class: 'level1') do %>
<% content_tag_for(:li, items, class: "item") do |item|
<%= link_to item.text, '#' %>
<% end %>
<% end if items.any? %>
5 lines, no extra partials, only rails helpers.

As suggested by sawa, you could use Slim:
- if items.any?
ul.level1
- items.each do |item|
li.item
a href="#"
= item.text
or Haml:
- if items.any?
%ul.level1
- items.each do |item|
%li.item
%a{href: "#"}= item.text
Both produce nicely formatted HTML.

I would go into something like this:
if items.any?
content_tag(:ul, class: 'level1') do
items.each do |item|
concat content_tag(:li, class: 'item', item)
end
end
end

That actually looks sufficiently elegant to me already, but you could do this to make a little cleaner:
<% if items.any? %>
<ul class="level1">
= render items
</ul>
<% end %>
And then have your li code in a partial called _items.html.erb, like so:
<li class="item">
<%= item.text %>
</li>

Related

How to output variable in sinatra without <%=

In Rails, there exist such helper as "concat" to output variables inside <% %> block for erb remplates. Which helper can I use in Sinatra to perform the same action, without using <%= %> block ? I mean, something like
<%
#code
concat "This should be rendered in HTML, not in console"
#code
%>
EDIT
The code in the view is something like this (yep, too much logic, but this is my first app in Ruby):
<% Dir.glob('uploaded/*').select do |entry| %>
<div class="singleFileItem">
<% if File.directory? entry %>
<img src="images/folder.png">
<% else
case entry.to_s.split(".")[1]
when "doc","docx" %>
<img class="pictogram" src='images/word.png'>
<% when "xls","xlsx" %>
<img class="pictogram" src='images/excel.png'>
<% when "pdf" %>
<img class="pictogram" src='images/pdf.png'>
<% when "png", "jpg", "jpeg" %>
<img class="pictogram" class="imageRaw" src="<%= entry.to_s %>">
<% else %>
<% end
end %>
<br>
<span class="subFileText">
<%= entry.to_s.split("/")[1][0..14] %>...
</span>
</div>
<% end %>
Thanks, guys, I have finally found it.
I have extended the app.rb file with
set :erb, :outvar => '#output_buffer'
def concat(text)
#output_buffer << text
end
And it works. Just type in the .erb view
<% concat "Text that should be added to render" %>
And you all done. Hope, this will help to someone with similar question

Add a class to the first child in a loop using Middleman

I am creating a slider for my blog and I want to add a collection of featured items to it, The slider requires that the first child load with the class selected.
How can I do something like if first child do this else do that
Here is what I have so far:
<ul class="cd-hero-slider">
<% blog.articles.select {|a| a.data[:featured] }.each do |article| %>
<li class="selected" style="background-image: url('https://images.unsplash.com/photo-1447014421976-7fec21d26d86?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&s=c82e04e1201234889daab5427f481731')">
<div class="cd-full-width">
<h2><%= link_to article.title, article %></h2>
<p><%= article.summary(250) %></p>
<%= link_to 'Read More', article, :class => 'cd-btn' %>
</div>
</li>
<% end %>
</ul>
Use each_with_index instead of each - this will give you the object but also the position into the array, first being 0:
<% blog.articles.select {|a| a.data[:featured] }.each_with_index do |article, index| %>
<% if index == 0 %>
<li>I'm the first!</li>
<% else %>
<li>Not the first</li>
<% end %>
<% end %>

erb template for nested array

I have nested array:
book= {"Dan Brown"=>["Angels and Demons", "The Da Vinci Code"], "Dale Carnegie"=>["How to Win Friends and Influence People", "How to Stop Worrying and Start Living"]}
I need this html result:
<h3 class="title">Book</h3>
<h4>Dan Brown</h4>
<ul>
<li>Angels and Demons</li>
<li>The Da Vinci Code</li>
</ul>
<h4>Dale Carnegie</h4>
<ul>
<li>How to Win Friends and Influence People</li>
<li>How to Stop Worrying and Start Living</li>
</ul>
Can't understand how to do it via erb template.
May be from this method:
book.each {|key, value| puts "#{key} is #{value}" }
But for me this method don't work, I think I can't understand how to use it.
Thank you for help.
Just like that:
<h3 class="title">Book</h3>
<% book.each do |key, value| %>
<h4><%= key %></h4>
<ul>
<% value.each do |title| %>
<li><%= title %></li>
<% end %>
</ul>
<% end %>
<h3 class="title">Book</h3>
<% book.each do |author,books| %>
<h4><%= author%></h4>
<ul>
<% books.each do |book| %>
<li><%= book%></li>
<% end %>
</ul>
<% end %>

Do I need an Enumerator for this?

I want to do this:
<div class="menu">
<%- render_menu do |title,path,children| %>
<%= link_to title, path %>
<div class="submenu">
<%= render_menu(children) do |title,path,children| %>
<%= link_to title, path %>
<%= children %>
<%- end %>
</div>
<% end %>
</div>
The method render_menu would look something like this:
def render_menu(children=nil)
children = Paths.roots if children.nil?
children.collect do |child|
[ child.title, child.path, child.children ]
end
end
I'm not sure what the render_menu needs to return to get the three params..
The render_menu will grab the default menu items if no argument is given..
You have to use yield and replace each for collect inside render_menu:
def render_menu(children=nil)
children = Paths.roots if children.nil?
children.each do |child|
yield([child.title, child.path, child.children])
end
end
You should also modify your template to not display the value returned by render_menu:
<div class="submenu">
<% render_menu(children) do |title,path,children| %>
<%= link_to title, path %>
<%= children %>
<% end %>
</div>

Ruby variable each loop substitution

I need to replace X_VARIABLE in 2 places.
For the first X_VARIABLE I want to keep the text 'remove'
For the second X_VARIABLE I want to keep 'd_cars_path'
<% #cars.each do |x| %>
<% #a = #b.send(x) %>
<% if #a == true %>
<%= button_to "removeX_VARIABLE", X_VARIABLEd_cars_path(:id => #user.id), class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
I am looking for some help with the variable substitution syntax. Thanks.
I'd write:
<% #cars.each do |x| %>
<% if #b.send(x) %>
<%= button_to "remove#{x}",
send(:"#{x}d_cars_path", id: #user.id),
class: "btn btn-large btn-primary" %>
<% end %>
<% end %>

Resources