Is there any way to avoid context switching in erb files - ruby-on-rails

Newbie here coming from Microsoft MVC3+razor.
Say I had:
<% if foo %>
<%= bar %>
<% end %>
Is there a way I can have:
<% if foo
magic_function_that_goes_to_output_buffer bar
end %>
Does this function exist?
Edit:
To be absolutely clear, I am looking for a solution I can use multiple times within <% %> blocks. Having a solution between <%= %> blocks just moves the problem.
An answer of "No" is acceptable as then I can stop being annoyed by it and just move on.
Solution accepted:
My application_helper looks like
def out(content)
#output_buffer.safe_concat(content)
end
My view looks like
prevReview = nil
#review.each do |review|
out render :partial => 'review',
:locals => { :review => review, :showDate => (prevReview.nil? ? true : prevReview.updated_at === review.updated_at) }
prevReview = review
end

Yes there is a way.
But before I tell it, please don't do this unless you have a really good reason. This is because you'll be tied to an implementation detail that may change anytime.
Just post a new question that target your specific problem, you'll certainly get good answers.
Here it is:
<% if foo
#output_buffer.concat("any string will do")
bar = call_what_you_want
#output_buffer.concat(bar.to_s)
end
%>
Okay, this works well on Rails 2.x but with Rails 3 you'll concat to a safe output buffer so you should maybe call #safe_concat instead of #concat on the #output_buffer variable.

It does, try this:
<%= bar if foo %>
Edit:
You can do that too:
<%= if true
"true"
else
"false"
end %>
But if you have much logic involved, you should better use a helper. So in you helper file:
def magic_function_that_goes_to_output_buffer(condition)
if condition
"true"
else
"false"
end
end
In your view:
<%= magic_function_that_goes_to_output_buffer(foo) %>

Maybe you want to look at the haml. With haml code looks cleaner and stylish.
<% if foo %>
<%= bar %>
<% end %>
This erb code transforms to:
- if foo
= bar
That's all. Couple of useful links haml site and haml-rails plugin page. Good luck!

Related

What syntax do I use if I want to confirm a user is on a certain page?

I have a rails app and in the the application layout view I want the header to show a link ONLY if a user is on a certain page.
How would I write that?
Currently I did
<% if welcome_index2_path? %>
blah...blah...blah
<% else %>
blah...blah...blah
<% end %>
But my if statement is not right, I need the correct syntax.
Just use the current_page? helper!
<% if current_page? welcome_index2_path %>
As Yuri said, you can also use yield.
You can use the yield with content_for:
In your layout:
<%= yield :links %>
In the view for some action, where you need the link:
<% content_for :links do %>
<%= link_to 'Foo', bar_path %>
<% end %>
You also have a content_for? helper method, which returns true, if the content for the given key is given:
content_for?(:foo) => false
content_for(:foo, :bar)
content_for?(:foo) => true
Try this
<% if request.request_uri == welcome_index2_path %>
....
it would be more useful for you to use an actual specific example from your code, as it might be that you want to ignore ids in the url path and just want to test the current controller and action, but i can't tell from your example.
You should do something like this.
<% if current_page?(:controller => 'yours', :action => 'yours') %>

Strings passed from controller to view in Rails arrive empty

I am trying to pass a string to my view from controller like this:
controller:
def index
#str = 'foo'
end
view:
String: <% #str %>
The variable itself seems to arrive because I get no error. However, it arrives empty (only "String" is in html, nothing else). And it seems to work great with other built-in types, e.g. Time. What am I missing here? I use Ruby 2.2.1 and Rails 4.
As others have said, you need to use
<%= #str %>
I'll give you an explanation as well - you use <% %> for when you need to run some Ruby code that you don't want displayed to the screen. For example, you might have conditional logic like
<% if user_signed_in? %>
<%= #welcome_string %>
<% end %>
Use <%= %> when you want to output, drop the '=' for conditional logic or anything that doesn't need to display.
in your view
String: <%= #str %>
In view user following code:
String: <%= #str %>
In your view, use:
<%= #str %>
As the other users have pointed out, you need to use <%=
The = is an ERB flag to so export the result of the code inside of the tags and put it into the DOM.
If you want to put some logic into your page that you don't want to evaluate, you leave the = out.
<% if user_wants_to_see_output? %>
<%= "User will see this" %>
<% end %>

How to obtain the same result as <%= var %> without the =?

In the Rails views, I regularly find lines like:
<%= my_var %>
What if I had a slightly more complex situation and I needed to trigger the printing with plain code instead of <%= %>?
Example:
<% .....
puts my_var
%>
I guess is a silly question but bear with me, I'm a ruby beginner.
Look at documentation of ERB
In <% %> you put expressions that are not for printing out.
In <%= %> you put code for printing out.
Example:
<% if #cost < 10 %>
<b>Only <%= #cost %>!!!</b>
<% else %>
Call for a price, today!
<% end %>
You can use helper method which is much more cleaner.

Rails - best way to display code only in production?

I have a few pieces of code that I would like to display only in production, for instance, the showing of disqus comments. What is the best way to go about doing that? Currently I have:
<% if RAILS_ENV.eql?('production') %>
disqus code here
<% end %>
But I am not sure if that's the best method, or is that it? Seems pretty verbose and I would need this in a few different places in the application.
The effective check is
<% if Rails.env.production? %>
disqus code here
<% end %>
There is no need to put it as a constant in your environment.rb or an initializer. Just keep your code simple and use Rails.env.production? in your main code base I say.
I'd suggest writing a helper method in your application_helper.rb file:
def render_disqus
return '' unless Rails.env.production?
#render disqus stuff here...
end
Then, in your view it gets really simple:
<%= render_disqus %>
If you want to display something in production, but not on a certain page(s), you can do something like this:
<% if !current_page?(controller: 'home', action: 'dashboard') %>
<% if Rails.env.production? %>
<!-- contant go here -->
<% end %>
<% end %>

How to output text in rthml without <%=variable%>

I've been looking around for a solution to this question for the last couple of days. It's a simple annoyance, but I hate not knowing how to do things...
Environment: Ruby, Rails, rhtml
The Problem: When I iterate a collection in rhtml I would like to reduce the number of <% %> and <%= %> tags I use. The following seems bloated:
Example
<% #products.each do |p| %>
<%= #p.name %>
<% end %>
EDIT: how do I exclude <%= %> inside of a block?
I would much rather do:
<% #products.each do |p|
puts #p.name
end %>
Certain situations could allow for use of either... However, I know that I could do this with jsp:
<% for(int i=0; i<10;i++){
System.out.print(i);
} %>
Thanks in advance for your input.
if you want to be less verbose look at haml, with your example it will be :
- #products.each do |p|
= #p.name
<% #products.each do |p|
_erbout << #p.name
end %>
_erbout is the default name of the variable that ERB (the class that's parsing your .rhtml template) uses to build its output. This is pretty ugly, and feels a bit hacky to me, but it works.
Use print instead of put.
Several other possibilities, depending on the context, if your view code seems too bloated:
Use partials. E.g.:
in your main file:
<%= render(:partial => "product", :collection => products) %>
and in the partial, just use:
<%= product.name %>
Now this seems contrived for a simple example such as this but assuming something more complex it abstracts away the looping and makes the code clearer.
Use helper methods
You could also try using something like haml to clean up the templates (along with helpers and partials).
You're going to have to use a <%= inside such a block. You can achieve the readability you want by using a <%= with a block:
<%= #products.map do |p|
p.name
end.join("\n") %>

Resources