I'm trying to move a loop statement from my view that iterates with every element in a ActiveRecord_Relation and put it on my helpers.
This is the code I'm using in the views to generate a card for each post in the database:
<% @posts.each do |post|%>
<div class="post-container">
<div>
<h2 class="m-0-p-0"><%= post.title %></h2><br/>
<hr class="m-0-p-0" />
<%= second_useless_helper(user_signed_in?, post) %>
</div>
<div>
<h4><%= post.body %></h4>
</div>
</div>
<% end %>
But when I try to iterate through my helpers using this code:
def useless_loop
@posts.each do |item|
render inline: '<p>' + item.title + '</p>'.html_safe
end
end
This is what I got instead: Code returned from the loop in helpers
I tried a lot of different ways of looping, but every single one returns the same thing.
The only thing that I could do was access the values of every item through bracket notation (Ex: @posts[0].title or @posts[4].body). But I failed when I tried to loop it.
I searched a lot about what is happening and why the loop does not work, but I couldn't figure it out.
The full code is available here: https://github.com/luisvinicius09/members-area/tree/app
Your useless_loop
helper works fine. The reason it returns the posts collection is because Array#each
returns self
.
def useless_loop @posts.each do |item| render inline: '<p>' + item.title + '</p>'.html_safe end end
In the above the render
call is made, but the return value of render
is ignored since each
does not use the return value of a block. You could use a combination of map
and join
to collect all render results, then join them together into a single string.
def useless_loop
@posts
.map { |item| render inline: "<p>#{h item.title}</p>".html_safe }
.join
.html_safe
end
However there is no need for the render
call at all.
.map { |item| render inline: "<p>#{h item.title}</p>".html_safe }
# can be replaced with
.map { |item| "<p>#{h item.title}</p>".html_safe }
You could also use the tag
helper. This helper escapes special HTML characters in unsafe strings passed as content, which removes the need to use html_escape
(aliased as h
).
def useless_loop
@posts.map { |item| tag.p(item.title) }.join.html_safe
end
I'm not entirely sure if the final .html_safe
call is needed. If all elements in an array are marked as HTML safe the resulting string might be marked as HTML safe automatically. I currently don't have a Rails environment on hand, so you'll have to test that one yourself.