How to reuse ERB templating code in function? - ruby

I have this piece of code inside ERB template to render all articles in list.
<% #list.each do |a| %>
<article class="my-panel">
<header>
<h2><%= a[:name] %></h2>
<time datetime="<%= to_datetime(a[:time]) %>"><%= time_description(a[:time]) %></time>
</header>
... more stuff cut out
</article>
<% end %>
Now I am going to have to change it to something like this:
<% #list[content_splitter.before_ad_range].each do |a| %>
<%= render_article(a) %>
<% end %>
<%= AdCreator.between_content_ad %>
<% #list[content_splitter.after_ad_range].each do |a| %>
<%= render_article(a) %>
<% end %>
I thought it would be nice to have render_article defined in template as opposed to having html clutter my ruby code. But when I move that code inside function I get an error.
This is the function:
<% def render_article(a) %>
<article class="my-panel">
<header>
<h2><%= a[:name] %></h2>
<time datetime="<%= to_datetime(a[:time]) %>"><%= time_description(a[:time]) %></time>
</header>
<div class="image">
<img alt="" src="<%= rel_url_to a[:img_url_1x] %>" srcset="<%= rel_url_to a[:img_url_2x] %> 2x, <%= rel_url_to a[:img_url_3x] %> 3x">
</div>
<div class="text">
<%= a[:article_text] %>
</div>
</article>
<% end %>
This is the error:
undefined local variable or method `_erbout' for #<Html::FrontPage:0x0055fb94005c68>
Line of code producing this error is:
self.class.instance_variable_get(:#renderer).result(binding)
Why is this happening? How to find more informative error?
How to fix this? Can I avoid moving this obviously html dominant code into ruby helper file?
PS. I suspect problem is that functions to_datetime and time_description can't be accessed from inside ERB function.
I know that function render_article does get called because if I change it's signature to remove parameter I get an error
wrong number of arguments (given 1, expected 0)
# (erb):45:in `render_article'

What you are trying to do is not technically impossible, but rather difficult and not recommended as can be seen by reading comments and answers to this question.
As your error message points out your def won't quite happen in the context you "probably" expect and you certainly won't be able to "freely use erb features" while defining the method (since your context is completely different from what you expect).
The "railsy" way to do this is adding a helper or using a partial, but both come with their drawbacks. .erb files (as most templating-languages) do not "factor" well. If you want to factor things somewhat more freely you should look at the fortitude gem which provides what is basically a ruby-DSL for html which factors pretty easily. However, that is a rather drastic change from what you are probably used to.
If you really want to define a method inside an .erb-file then you would have to do it entirely within a single pair of <% ... %> brackets where you will have only access to your params, not your context. You would have to return what is basically a String in order to be able to use it in <%= ... %> and pay a hell of a lot of attention to escaping rules for everything to make it through. This is most probably more trouble than it is worth (but easy enough to do in fortitude :-).

Related

Simple If Then statement not working the way I think it should

I'm relatively new to VB and I'm being forced to use the in-line coding method. I would like to check for a not null value for a variable and then display an image. That's all I want it to do. Here's a couple of instances of what I've tried to do.
<% if ACTL is not nothing then %>
<img id="ACTLLogo" src="<%= ACTL %>" />
<% else end if %>
or this:
<% if ACTL is nothing then %>
<% else %>
<img id="ACTLLogo" src="<%= ACTL %>
<% end if %>
or this:
<% if String.IsNullOrEmpty(ACTL) then %>
<% else %>
<img id="ACTLLogo" src="<%= ACTL %>
<% end if %>
When I do just the part without the if statements, the logo shows up fine, so I'm thinking I just don't know how to do in-line coding IF statements in ASP Classic. Any thoughts?
To check whether a variable is NULL, use the IsNull function:
If Not IsNull(ACTL) Then
Response.Write "<img src='" & ACTL & "' id='ACTLLogo'>"
End If
You can also check whether the variable is EMPTY (which is what you get if, for example, you do a Request.Form("fld") and the form does not have a field called fld) using the, you guessed it, IsEmpty function:
If IsEmpty(Request.Form("fld")) Then
Response.Write "<p class='msg'>No such field!</p>"
End If
If all you care about is whether the variable has a value, any value, then you can do a quick-and-dirty string conversion:
If ACTL & "" <> "" Then
...
End If
This latter trick is very useful for avoiding the type mismatch errors you can get if a variable is unexpectedly NULL, without having to add If Not IsNull(...) all over the place.
In ASP Classic you can use <% if ACTL <>"" %>
You could also write your code like this, which removes the need to close the asp tag.
<%
if ACTL <>"" then
response.write("<img id=""ACTLLogo"" src="""&ACTL&""" />")
end if
%>
Might be a bit easier to read and maintain.

Divide loop iteration in an html.erb file over different sections for enhancing performance

This is part of my code in an html.erb file
<div class="list_carousel">
<ul id="products-carousel" class="carousel">
<% #posts.select{ |post| post.categories.include?(#categories.find_by_name("Productos")) }.each do |post|%>
[...]
<% end %>
</ul>
</div>
[...]
<div class="modals">
<% #posts.select{ |post| post.categories.include?(#categories.find_by_name("Productos")) }.each do |post|%>
[...]
<% end %>
</div>
The problem here is that I'm using several database queries to perform this loop and I would like to re-use the first loop in other parts of this files in order to enhance performance.
For example I would like to do something like each do |post| do something in this first section, don't do nothing in this second section and continue in the third one. This way I could re-use the instance of the selected postd over which I'm iterating.
In your controller, you can do this:
#posts = Post.all
#productos_category = #categories.where(name: "Productos").first
#productos = #posts.where(category_id: #productos_category.id)
Note that I changed the way you find the associated #productos to use the ActiveRecord query interface, as opposed to using pure ruby select and include? methods. This will allow for the query to be much more efficient. I implied some things, such as the child key for the categories being category_id. Change this where appropriate.
EDIT 1
I believe this will work, although my experience with many-to-many relationships is somewhat limited:
#productos_category = #categories.where(name: "Productos").first
#productos_posts = Post.joins(:join_table).where(join_table: {category_id: #productos_category.id})
Where :join_table is the name of the table that is used in the has_many association. If it is a HABTM relationship, this will probably be called categories_posts.
Then your view would change to this:
<div class="list_carousel">
<ul id="products-carousel" class="carousel">
<% #productos_posts.each do |post|%>
[...]
<% end %>
</ul>
</div>
[...]
<div class="modals">
<% #productos_posts.each do |post|%>
[...]
<% end %>
</div>

Rails Template Rendering ERB if Statement is rendered not in order

When I'm using an if-statement in an erb- template file, the if statement is evaluated delayed, which is mixing up the html:
<small>
<% if #applause_count == 1 %>
The author has been cheered up once!
<% elsif #applause_count > 1%>
The author has been cheered up <%= #applause_count %> times! <br/>Be the next!
<% end if %>
</small>
produces:
<small>
</small>
The author has been cheered up 100 times! <br/>Be the next!
Can someone explain me this strange behaviour?
As noted, the problem is with the <% end if %>
Use <% end %>
This produces the desired html:
<small>
The author has been cheered up 2 times! <br/>Be the next!
</small>

Puppet 3 loop execution only if variable is defined within a template

I am trying to create a loop only if index is defined. But it looks like
erb can't handle a loop within a if clause.
<% if(#index) %>
index <% index_files.each do |i| %> <%= i %> <% end %>;
<% end %>
Expected Result was:
index index.html index.php
or
""
Syntax error i got:
My flat approach failed as expected:
<% if(#index_files) %> try_files <% end %> <% index_files.each do |i| %> <%= i %> <% end %>
I defined index_files as undef => broke the each loop
I defined an empty array => since an empty array is defined it didn't work.
Maybe I can check the length of index_files?
Or do I need a complete different way to solve the problem?
I'm doing the same and it works for me, also for nginx ;).
For example:<% if #proxy_ignore_headers %> proxy_ignore_headers<% proxy_ignore_headers.each do |i| -%> <%= i %><% end -%>;
That works like a charm, the only difference with you is using () for the if condition, but I bet puppet supports (). It's weird, maybe you had pressed a bad combination generating a character that can't be seen but it's messing with your code, try writing all from scratch just in case.
You can see the full template here
Good luck
At first glance you just need to change
index_files.each
to
#index_files.each

Ruby if else syntax

I have an app where users can sign up with Facebook, in which case I take the Facebook image, or they can sign up using regular authentication, in which case they're uploading a photo using CarrierWave gem.
Because of some sort of conflict, I had to create a column in the database (:image)to store the url to the Facebook image, and then a different column (:dimage) to store the url for the image if they signed up using the non-facebook sign up.
So when it comes time to display the user, I'm checking to see if there's an :image, and, if not, then displaying the other :dimage.
However, I don't want to require them to upload an image, in which case, I want to display an anon image (here represented by the rails.png). However, the Rails.png isn't showing up (just a broken image path), so I'm assuming there's some sort of error with my if else syntax because the image_tag("rails.png") is taken straight from the api
<% if user.image %>
<%= image_tag user.image %>
<% elsif user.dimage %>
<%= image_tag user.dimage_url(:thumb).to_s %>
<% else %>
<%= image_tag("rails.png") %>
<% end %>
The generated html on the rails.png
<img alt="Assets" src="/assets/">
Use the present? method to check if the attribute is not empty:
<% if user.image.present? %>
<%= image_tag user.image %>
<% elsif user.dimage.present? %>
<%= image_tag user.dimage_url(:thumb).to_s %>
<% else %>
<%= image_tag("rails.png") %>
<% end %>
You'll save yourself a headache or two because in Ruby the only falsehoods are false and nil. This means that the empty string "" will actually return true.
You need to look at look into user.image.nil? user.image.empty? and user.image.blank? depending on what you're using and apply the same to the rest of your conditional. You need to find out specifically what your looking for or the if else won't give you what you want. I would try empty first which checks if something is nil or is an empty string.
When you create a new rails application, rails stores its logo in PROJECT_PATH/app/assets/images folder. Could you check if that image exists?

Resources