Run a block if a condition pass - ruby-on-rails

I want to run this block only a condition is satisfied
<% if condition %>
<% progressive_render do %>
SLOW CODE HERE
<% end %>
<% end %>
IF condition = true
SLOW CODE should be runnned wrapped by "progressive_render"
IF condition = true
SLOW CODE shoud be runned not wrapped by progressive_render. So runned anyway.

You can replace the if-else condition with a guard clause (plus unless condition):
<% SLOW CODE HERE unless condition %>
<% progressive_render { SLOW CODE HERE } %>

Related

get first 3 occurrence of an array

In my rails app I have below code to print some data from database.
<% #di.each do |d| %>
<% if d["visibility_team"] == 'for_all' %>
//my code goes here
<% end %>
<% end %>
I just want to print first 3 occurrence which fulfill the d["visibility_team"] == 'for_all' condition.
How can I do this?
If you can't get #di as 3 records from DB, how about keeping counter how many ds were printed?
Something like this (feel free to style it the way you want)
<% counter = 0 %>
<% #di.each do |d| %>
<% if d["visibility_team"] == 'for_all' %>
<% counter += 1 %>
<% break if counter == 3 %>
//your code goes here
<% end %>
<% end %>
However it's usually a bad taste to have so much logic in views.

How do I reference a hash in the view and write an if/else statement around it?

I have confirmed that app["rating"] == 0 in the rails console. Given this, I am trying to write an if/else statement that will print out certain text but am having trouble doing so.
Any advice?
<% if <%= app["rating"] %> == 0 %>
no rating
<% end %>
If you're using ERB templates, you should be doing:
<% if app["rating"] == 0 %>
no rating
<% end %>
I don't know why you would nest your template declarations like that.
Remember that anything inside <% ... %> is evaluated as literal Ruby code. If you would like the result of that evaluation to be displayed, use <%= ... %>. Since you have non-Ruby code in there, the if will have the effect of either showing or not showing that part.
Everything in between <% and %> is interpolated, so just do
<% if app["rating"] == 0 %>
html content
<% end %>
There is no need to nest the erb tags <% %> within your if statement. For example:
<% if app["rating"] == 0 %>
no raiting
<% end %>
However, you're blurring the lines that MVC draws when you put conditional logic into your view. Without diving into discussions about presenters or DSLS, the simplest way to handle this would be to add a helper method.
Assuming this is in a controller called apps_controller.rb you would have a apps_helper.rb within the /app/helpers folder. You could create a helper method that looked something like this:
def display_rating(rating)
rating = "No Rating" if rating == 0
concat(rating)
end
Then, in your view you can use this helper by using <%= display_rating(app["rating"]) %>
Assuming you are using ERB, to do an if/else statement you would do:
<%if app["rating"] == 0 %>
No Rating
<%elsif app["rating"] == 10 %>
rating 10
<%elsif app["rating"] == 20 %>
rating 20
etc...
<% end %>

Exit rails gracefully if conditions are met?

I have a code where I would need to exit (php version of die), if certain events occur
Snippet in trace_controller.rb
def show
rule=Rule.new
#order,#order_error=rule.get_order(#order_external_id)
#order_items, #order_items_error=rule.get_order_items(#order)
#order_item_units, #order_item_units_error=rule.get_order_item_units(#order_items)
#outbound_messages, #outbound_messages_error = rule.check_outbound_messages(#order_external_id)
#inbound_messages, #inbound_messages_error = rule.check_inbound_messages(#outbound_message)
......
In show.html.erb
<% unless #order_error.blank? %>
<%= #order_error.html_safe %>
<% else %>
<%= render "trace/display_tabular_data", :data => #order %>
<% end %>
.....
.....
<% unless #order_items_error.blank? %>
<%= #order_items_error.html_safe %>
<% else %>
<% #order_items.each do |order_item| %>
<h5>Order Item</h5>
<%= render "trace/display_tabular_data", :data => order_item %>
<% end %>
<% end %>
......
Most of my functions are dependent on outcome of previous functions. Now take get_order_items function which is dependent on orders. If the order does not exist, there is no need to calculate get_order function as it won't exist either. Additionally, it fires up an error, as it says I am passing it a NIL object when I perform operations on orders inside get_order_item.
Additionally in the show.html.erb - #order_items, and #order_items_error should not even exist if the order does not exist. I just wanna render the function till the order_error, and then stop.
Now, coming from PHP background, I forgot that rails does not have die. So is there an alternate of die? Abort isn't it. I need it to exit disgracefully. Or is my best shot using conditionals if, unless etc...But it will look ugly as the page will become full of them. How would you about it?
To cut off the current action and render the view, you can use return. This will crash with errors if you try to use an unitialized instance variable in the view though.
You can also use render nothing: true which stops the current action and renders nothing.
Perhaps consider redirecting back as well:
flash[:error] = 'There was no order!'
redirect_to :back
I am not sure what exactly you want to do. But this should meet with what you are asking for.
def show
rule=Rule.new
#order,#order_error=rule.get_order(#order_external_id)
unless #order.blank?
#order_items, #order_items_error=rule.get_order_items(#order)
#order_item_units, #order_item_units_error=rule.get_order_item_units(#order_items) unless #order_items.blank?
end
#outbound_messages, #outbound_messages_error = rule.check_outbound_messages(#order_external_id)
#inbound_messages, #inbound_messages_error = rule.check_inbound_messages(#outbound_message) unless #outbound_messages.blank?
end
Similarly, you can add conditions in your view file:
<% unless #order.blank? %>
<% unless #order_error.blank? %>
<%= #order_error.html_safe %>
<% else %>
<%= render "trace/display_tabular_data", :data => #order %>
<% end %>
.....
.....
<% unless #order_items.blank? %>
<% unless #order_items_error.blank? %>
<%= #order_items_error.html_safe %>
<% else %>
<% #order_items.each do |order_item| %>
<h5>Order Item</h5>
<%= render "trace/display_tabular_data", :data => order_item %>
<% end %>
<% end %>
<% end %>
.......
.......
<% end %>
It is just a basic idea what I get from your example, though it was not clear enough to show what you want to achieve. So, whole idea is to check the variable before using it!
One more point I would like to mention, avoid using unless - else, unless should be used alone, if you need to put some logic in else block, why not use if - else. That probably makes more sense than unless - else.

If else not working because it contains end within

I have a a helper that contains a simple on and off switch. I know I have it working because it's working on other pages. However, on this particular page it won't work.. I think its because theres an end within the if else, so it ends the if else early. Here's the code:
I believe this part is working:
<% if popup == "off" %>
<% content_for :main do %>
<% end %>
This part not so much:
<% if popup == "off" %>
<% end %> << this end should be displayed if popup = off
<% end %>
You could do this:
<% if popup == "off" %>
<%= "<% end %>" %> << this end should be displayed if popup = off
<% end %>
or try this:
<% if popup == "off" %>
<% end %> << this end should be displayed if popup = off
<% end %>
If you just want the word end to be displayed, don't enclose it in tags. Anything enclosed in tags is interpreted as Ruby code, anything not is printed exactly as it is.
<% if popup == "off" %>
end << this will now be interpreted as text, not ruby code
<% end %>
ERB (and Ruby) doesn't work like that.
I think you're treating it like you are trying to end an HTML tag instead of an end to a Ruby block, and that you want everything in between those two code segments to run in the content_for block.
Here's what you need. Everything in between will be included in the content_for block:
<% if popup == "off" %>
<% content_for :main do %>
your block code will be evaluated here.
<% end %>
<% end %>
Seems all the suggestions of doing <%= "<% end %>" %> results in a syntax error.. May seem like easy way out by ended up just restructuring my app and got rid of the requirement of <% content_for :main do %>

How to reduce number of hierarchical 'if statements'

I have hierarchical the statements like this
<% #descriptions.each_with_index do |description, i| %>
<% description.tale2.each do |tax_ref| %>
<% if condition %>
<% if condition %>
<% if condition %>
<%= $text_first_describe%> <%= $paren_author_yr %>
<% ref_sp_uniq.each_with_index do |ref, i| %>
<% if ref == tax_ref.ref_wo_brace%>
<% execution %>
<% elsif i == (ref_sp_uniq.size - 1)%>
<%# #ref_desc = "#{#ref_desc_numb}. #{tax_ref.ref_wo_brace}" %>
<% end %>
<% end %>
<% if condition %>
<% execution %>
<% elsif condition %>
<% execution %>
<% elsif taxon_name.emend_author_year %>
<%= print %>
<% else %>
<%= print %>
<% end %>
<% end %>
<% else %>
<% if condition %>
<%= print %>
<% ref_sp_uniq.each_with_index do |ref, i| %>
<% if condition %>
<% execution %>
<% elsif condition %>
<% execution %>
<% end %>
<% end %>
<% if condition %>
<% execution %>
<% elsif condition %>
<% execution %>
<% elsif condition %>
<% execution %>
<% else %>
<% execution %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
Kindly suggest me possible way to reduce this kind of junk "if statements".
If your nested IFs are becoming very complex, you might consider describing the entire structure with a state machine and processing it like that. That way you get the documentation of the formal state diagram and your code will be much simpler.
Edit:
Here is a better attempt to describe the process. The nice thing about
this is that once you have your initial state diagram and the code to
process it, adding new states is very easy to do. (Expecially if you
build a little tool to read your diagram and generate your table for
you).
Most people just use these in the context of regular expressions and
leave them alone otherwise, but it is a nice powerful tool to have in
your toolbox. A common example is implementing a full ftp server this
way is trivially easy.
Ok, to my better example, hope this helps.
Consider this IF psuedo code:
if (a < 5)
do_b
do_c
if (a < 3)
do_d
else
do_e
end-if
end-if
The state transition table to process this might look like:
State Transition Action Next state
----- ---------- ------ -----
1 a < 5 2
1 7
2 do_b 3
3 do_c 4
4 a < 3 5
4 6
5 do_d 7
6 do_e 7
7 exit
The code to process it would look like this:
currentState = 1
foreach table entry
if table_state == currentState
&& table_transition is true or blank
call table_action
currentState = table_next_state
Take a look at http://en.wikipedia.org/wiki/State_transition_table for a
more formal description.
first of all I would put this code in a helper, so you get rid of all the tags and you clean the view, then look if you can apply the case statement and latter remember maybe you can include line_of_code if condition or condition ? code_a : code_b.
Hard to do something without conditions (I suppose the condition change each if), why not to address the question to https://codereview.stackexchange.com/
?
Ruby's case syntax would probably be a good starting point for cleaning that up, but like others have mentioned you probably need to rethink whats going on in there. Ultimately you probably want to be moving as much of that logic into the model as you can.
My two cents.

Resources