I ran into a very strange problem . I am trying to use if and else in rails it works perfect when I am comparing current_user.id with numbers but when I am trying to do it with params it did not work . Here is my code which work :
<%= #u = 2 %>
<% if current_user.id == #u %>
ssssss
<% else %>
aaaaaaaaa
<% end %>
And when I am trying to use this code :
<%= #u = params[:id] %>
<% if current_user.id == #u %>
ssssss
<% else %>
aaaaaaaaa
<% end %>
It is always giving me aaaaaaaaa value it would be helpful if anyone can help me to fix this
Use current_user.id == #u.to_i rather then #u because params gets a string and you compare with an integer.
Or you can compare by using current_user.id.to_s == #u
Here you are trying to compare string with number . Above answer is sufficient but I would like to correct your code simply add this to your code and you are done :
<%= #u = 2 %>
<% if current_user.id == #u.to_i %>
ssssss
<% else %>
aaaaaaaaa
<% end %>
The correct answer has been given. I usually, in cases like this, like to output the variables I'm interested in with ".inspect". This usually gives a clear information about what goes wrong.
In your specific case, this would have output 3 for the id and "3" for the param - easy to see that way.
Related
Say I have an instance variable #n, and I'm calling <%= #n.title %> in my view.
If #n equals a valid record, then this will print normally. But if #n is blank or invalid, then the entire page will show an error message, because of this one little line.
Is there a way to get #n.title to just print nil if #n is nil or invalid?
I'm looking for a way to do this without conditional statements. For example, if I wanted to print
<%= #v1.title %>,<%= #v2.title %>,<%= #v3.title %>,<%= #v4.title %>,
if I wanted to use conditionals to print without errors, it would require 12 lines of code:
<% if #v1 %>
<%= #v1.title %>,
<% end %>
<% if #v2 %>
<%= #v2.title %>,
<% end %>
<% elsif #v3 %>
<%= #v3.title %>,
<% end %>
<% elsif #v4 %>
<%= #v4.title %>,
<% end %>
It seems a shame to use 12 lines on this. It would be nice to be able to accomplish the error-handling right when printing.
You can totally do this easily with the try() method. I use it all the time.
<%= #n.try( :title ) %>
That will return nil if #n is nil or if the title method doesn't exist on #n.
You can also chain them together like this:
#n.try( :title ).try( :to_s )
Or even use it on a hash:
#n.try( :[], 'name' ) # Which is the same as #n['name']
See http://api.rubyonrails.org/classes/Object.html#method-i-try
EDIT (Jan 11, 2016)
You can now use the "safe navigation operator" as of Ruby 2.3.0.
#n&.title&.to_s
As well as the Array#dig and Hash#dig methods introduced in Ruby 2.3.0.
hash = { 'name' => 'bob' }
hash.dig( 'name' ) # Which is the safe way to do hash['name']
You can add some logic to your view that differentiates between development (where some errors can be ignored) and production environments (where errors should cause your app to fail in an obvious and ugly manner). Ruby's nil has a "falsey" nature, so you can use that concept to your benefit as well.
<% if Rails.env.development? %>
<% if #n %>
<%= #n.title %>
<% else %>
<%= nil %>
<% end %>
<% else %>
<%= #n.title %>
<% end %>
I have this block in my views:
<% video.members.each do |p| %>
<% if p.id == current_user.id %>
<%= "paid" %>
<% end %>
<% end %>
Basically I'm trying to work out if a member has paid for a video based on whether the id's match.
Maybe this a really bad way of doing it, which case I'd be happy to try and different method.
Assuming it is an ok way of checking this, how could I write a similar statement but as a helper method? I've tried, but it seems you can't write the same logic in helpers as the block just spits out the full array and not the id, meaning it doesn't work.
You should do this instead:
<% if video.members.exists?(id: current_user.id) %>
<%= 'Paid' %>
<% end %>
This will generate a single query to test if the video has been paid by the current_user ;-)
In a helper:
# application_helper.rb
def display_paid_or_not(video)
return '' if video.blank? # similar to .nil?
video.members.exists?(id: current_user.id) ? 'Paid' : ''
end
# in view
<%= display_paid_or_not(video) %>
Hope this helps!
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 %>
<% if defined?(#club.name) && !(#club.name).nil? %>
<%= #club.name %>
<% else %>
clubs:
<% end %>
first line looks ugly. any help is appreciated.
Perhaps:
<% if #club && #club.name %>
<%= #club.name %>
<% else %>
clubs:
<% end %>
Since #club will presumably either be set to a Club object or be set to nil, we don't really need to explicitly check whether or not the #club has a name method. Instead, we can just test that #club is set at all, and a truthiness test will suffice for that.
Similarly, we don't need an explicit nil check on #club.name. All values other than false and nil are considered "truthy," and, since a club's name presumably can't be set to false, simply testing its truthiness is equivalent to explicitly checking if it is nil.
Violet pointed out in the comments that this is actually a fairly common idiom in the Rails world, so a shortcut actually exists. In a Rails environment, all objects, including nil, have a method named try. try invokes the method name passed to it as an argument, and either returns that method's return value, or nil if that method is not defined.
So, for example:
no_name = Club.new
no_name.try(:name) # => nil
so = Club.new :name => 'StackOverflow'
so.try(:name) # => "StackOverflow"
nil.try(:name) # => nil
As such, the following is the exact equivalent to the first code block:
<% if #club.try(:name) %>
<%= #club.name %>
<% else %>
clubs:
<% end %>
Much prettier :)
<%= #club.name || "clubs:" %>
how about that?
Sorry if the title is not enough to understand what i am asking about.
I am rails developer and i used multiple lines of <% %> in my views but now i realized that it's not best practice so i came here and like to you all excellent guys what is the correct way in ROR?
For example if i required to something like following
<% user =User.all %>
<% name= [] %>
<% count = 0 %>
<% for user in users %>
<% name << user.name %>
<% count+=1%>
<% end %>
Can i do it as follows ?
<% user =User.all
name= []
count = 0
for user in users
name << user.name
count+=1
end
%>
I know better way of collecting element from array But above is just example.
But my question is, is it possible and if yes which is the correct way?
I think the correct way is something totally different: move logic out of views.
This blog post explains what I mean.
in start and end must has '<%' or '%>'
Like:
<% users = User.all
name= []
count = 0
for user in users
count+=1
end %>
Using just a single pair of tags per code block is certainly preferable if only because it makes the output smaller.
The code should really rather look like
<% names = User.all.map(&:name) %>
Note that "count" can be obtained via names.size.
If you need to mix <% and <%= you need to switch:
<% for user in User.all %>
<%= user.name %></br>
<% end %>