Loop through array of objects and print html - ruby-on-rails

Given a list of URLs and text, I want to print out links for each of them.
Is this set up correctly? I'm getting some strange errors (e.g. printing out the 2nd element 3 times).
<%
nav_links = [{
text: "hello",
href: "/hello.html"
},
{
text: "bye",
href: "/bye.html"
},
{
text: "whatever",
href: "/whatever.html"
}]
%>
Print the nav links.
<% nav_links.each do |nav_link| %>
<%= link_to nav_link['text'], nav_link['href'] %>
<% end %>

Your keys are symbols, not strings. It should be nav_link[:text] and nav_link[:href]

Your problem is that nav_link['text'] is not the same thing as nav_link[:text].
If you want to use text you need to say nav_link['text'.to_sym]
'text' is a string
:text is a symbol

Related

Filter and map by grouping data

I have an array of objects, where I have the following fields: title, name e url
My data:
#array = [
{ id: 1, title: '123', name: 123 },
{ id: 2, title: '123', name: 321 },
{ id: 3, title: '1234', name: 123 },
]
I need to group my data by title and then make the map with the names
<%= #array.map do |x| %>
<div class='col-md-12'>
<h3><%= x.title %></h3>
<div class="row">
<%= #array.filter do |y| %>
<div class="col-4">
<% if y.title === x.title %>
<p><%= t.name %></p>
<% end %>
</div>
<% end.join.html_safe %>
</div>
</div>
<% end.join.html_safe %>
The return is:
title = '123'
name = '123'
name = '321'
title = '123'
name = '123'
name = '321'
title = '123'
name = '123'
That is, my array comes duplicated ... how to proceed?
Remembering that I am inside the rails view
You're getting duplicate entries since you're mapping over all the elements and filtering the array for every element inside the block.
You can use Enumerable#group_by to group the array elements by title. You can then iterate over the groups and display the title and names of each group. Note that I'm using item[:name] to access the values from the hash since your question mentions an array of hashes. You should update it to item.name (and other places using hash access) if you're working with objects instead.
#groups = #array.group_by {|i| i[:title] }
<% #groups.each do |title, items| %>
<h3><%= title %></h3>
<% items.each do |item| %>
<p><%= item[:name] %></p>
<% end %>
<% end %>

parsing a comma in ruby for loop

So I'm looping through a object for loop in my ruby on rails app
currently this is the code:
<%overlays.by_time.each do |overlay| %>
{
"content": "<a href=''><img src='<%= overlay.imageurl %>'></a>",
start: <%=overlay.starttime %>,
end: <%=overlay.starttime %> + <%= overlay.duration %>,
style: {<%=raw theme.contact_us_overlay_style %>},
click_url: '<%= overlay.linkurl %>'
},
<%end>
the problem is the comma, which preventing my videojs player from running. I need the comma for next preceding overlay content, but i don't need it on the last one, which is the problem that causing it. How do i remove it on the last object iteration?
You have several possibilities. A quick (but not very elegant) one is to check whether the item is the latest one.
You can use for example each_with_index:
<% overlays.by_time.each_with_index do |overlay, index| %>
{
"content": "<a href=''><img src='<%= overlay.imageurl %>'></a>",
start: <%=overlay.starttime %>,
end: <%=overlay.starttime %> + <%= overlay.duration %>,
style: {<%=raw theme.contact_us_overlay_style %>},
click_url: '<%= overlay.linkurl %>'
}<%= "," unless index == (overlays.length - 1) %>
<% end %>
A better alternative, since you are essentially producing a string output, would be to generate (may be using an helper) the string output for each overlay as item into an array, then use join(",") to concatenate the array values into a single string.
This code should not be part of an ERB template, but may be a function or helper.
def json_for_overlays(overlays)
overlays.by_time.map do |overlay, index|
<<-JS
{
content: <img src="#{overlay.imageurl}">,
start: #{overlay.starttime},
end: #{overlay.starttime} + #{overlay.duration},
style: {#{raw(theme.contact_us_overlay_style)}},
click_url: '#{overlay.linkurl}'
}
JS
end.join(",")
end
You can look it this another way. Put the comma before each item. Then you just need to suppress the comma for the 0th index.
<% overlays.by_time.each_with_index do |overlay, index| %>
<%= "," unless index == 0 %>
{
"content": "<a href=''><img src='<%= overlay.imageurl %>'></a>",
start: <%=overlay.starttime %>,
end: <%=overlay.starttime %> + <%= overlay.duration %>,
style: {<%=raw theme.contact_us_overlay_style %>},
click_url: '<%= overlay.linkurl %>'
}
<% end %>

rails actionview: How to "not show" attributes if receiving nil or something else

Is there an easy way to remove options attributes for the tag or content_tag helper?
<%= content_tag :div, content, {
class: 'content',
style: styles_hash.map{|x| "#{x[0].underscore.dasherize}: #{x[1]}"}.join('; '),
data: {
hyperlink: (hyperlink if hyperlink.present?)
}
} %>
In this example, I'm wondering how to remove the data-hyperlink. Even if I throw a nil or false it stills displays as either data-hyperlink="null" or data-hyperlink="false" respectively. I need it to not display entirely if not present.
I've gotten a solution like this but I'd like to know if there is any better, or inside that data attribute?
<%= content_tag :div, content, {
class: 'content',
style: styles_hash.map{|x| "#{x[0].underscore.dasherize}: #{x[1]}"}.join('; '),
'data-hyperlink' => (hyperlink if hyperlink.present?)
} %>

Rails i18n list of items and looping in view

How can I list elements in my yml and loop through them in the view and access their properties? My current code only gets the last item in the list. I want to loop through in the view the list of items and display their title and description elements.
e.g.
yml:
en:
hello: "Hello world"
front_page:
index:
description_section:
title: "MyTitle"
items:
item:
title: "first item"
description: "a random description"
item:
title: "second item"
description: "another item description"
view:
<%= t('front_page.index.description_section.items')do |item| %>
<%= item.title %>
<%= item.description %>
<%end %>
Result:
{:item=>{:title=>"second item", :description=>"another item description"}}
Desired Result:
first item
a random description
second item
another item description
Use this instead:
<% t('front_page.index.description_section.items').each do |item| %>
# ^ no equal sign here
<%= item[:title] %>
#^^^^ this is a hash
<%= item[:description] %>
<% end %>
Also, your items list is not defined properly:
t('front_page.index.description_section.items.item.title')
# => returns "second item" because the key `item` has been overwritten
Use the following syntax to define an array in YAML:
items:
- title: "first item"
description: "a random description"
- title: "second item"
description: "another item description"
To check this, you can do in your IRB console:
h = {:items=>[{:title=>"first item", :description=>"desc1"}, {:title=>"second item", :description=>"desc2"}]}
puts h.to_yaml
# => returns
---
:items:
- :title: first item
:description: desc1
- :title: second item
:description: desc2

how would I add inline html to this erb image tag?

I want to add this html data tag inline
data-zoom-image="<% image_tag(step.i_connection.image.image.url(:large) %>"
to this erb tag, but am unsure how I would go about this. Any ideas?
<%= image_tag(step.i_connection.image.image.url(:medium), id: "iconnection#{n}") %>
You pass it in like data: { zoom_image: "large/image1.jpg" } and the data attribute gets converted to data-zoom-image="large/image1.jpg".
Try:
<%= image_tag(step.i_connection.image.image.url(:medium), id: "iconnection#{n}", data: { zoom_image: "large/image1.jpg" }) %>
Update:
I think you want to output the result of:
<% image_tag(step.i_connection.image.image.url(:large)) %> instead of just interpreting it.
Try:
data: { zoom_image: "#{ image_tag(step.i_connection.image.image.url(:large)) }" }

Resources