I have a show page for my Users and each attribute should only be visible on that page, if it is not nil and not an empty string. Below I have my controller and it is quite annoying having to write the same line of code @user.city != nil && @user.city != "" for every variable. I am not too familiar with creating my own methods, but can I somehow create a shortcut to do something like this: @city = check_attr(@user.city)? Or is there a better way to shorten this procedure?
users_controller.rb
def show @city = @user.city != nil && @user.city != "" @state = @user.state != nil && @user.state != "" @bio = @user.bio != nil && @user.bio != "" @contact = @user.contact != nil && @user.contact != "" @twitter = @user.twitter != nil && @user.twitter != "" @mail = @user.mail != nil && @user.mail != ""
end 2 Answers
There's a method that does this for you:
def show @city = @user.city.present?
endThe present? method tests for not-nil plus has content. Empty strings, strings consisting of spaces or tabs, are considered not present.
Since this pattern is so common there's even a shortcut in ActiveRecord:
def show @city = @user.city?
endThis is roughly equivalent.
As a note, testing vs nil is almost always redundant. There are only two logically false values in Ruby: nil and false. Unless it's possible for a variable to be literal false, this would be sufficient:
if (variable) # ...
endThis is preferable to the usual if (!variable.nil?) or if (variable != nil) stuff that shows up occasionally. Ruby tends to wards a more reductionist type of expression.
One reason you'd want to compare vs. nil is if you have a tri-state variable that can be true, false or nil and you need to distinguish between the last two states.
You can use .present? which comes included with ActiveSupport.
@city = @user.city.present?
# etc ...You could even write it like this
def show %w(city state bio contact twitter mail).each do |attr| instance_variable_set "@#{attr}", @user[attr].present? end
endIt's worth noting that if you want to test if something is blank, you can use .blank? (this is the opposite of .present?)
Also, don't use foo == nil. Use foo.nil? instead.