'Only execute code in erb if variable exists?
Ruby newbie here who just started using Ruby with .erb templates and I'm having a problem with the code. I have a hangman game that's passing variables from the .rb file to the .erb file and everything was working fine until I tried to check it on initial load (no variables present) and it threw errors. So I figured I'd use defined?
with an if statement
to check if the variable exists and then execute the code if it does and ignore if doesn't. It works fine when I use:
<% if defined?bad_guesses %>
<%= bad_guesses %>
<% end %>
But the information I need is an array and when I try to use an .each or .times statement like this:
<% if defined?bad_guesses %>
<% bad_guesses.each do |i| %>
<%= i %>
<% end %>
<% end %>
I get:
NoMethodError at /
undefined method `each' for nil:NilClass
C:/Projects/hangman/views/index.erb in block in singleton class
<% bad_guesses.each do |i| %> hangman.rb in block in
erb :index, :locals => {:game_status => game_status, :bad_guesses => bad_guesses, :good_guesses => good_guesses, :word => word}
Any suggestions appreciated.
Also, is this even the proper way to do this? When you make an .erb template that uses variables passed in from a class in your .rb file, how do you ignore it until it exists to the template?
Passing variables using:
get '/' do
if params['make'] != nil
make = params['make'].to_i
game_status, bad_guesses, good_guesses, word = Hangman.get_word(make)
elsif params['guess'] != nil
guess = params['guess'].to_s
game_status, bad_guesses, good_guesses, word = Hangman.check_guess(guess)
end
erb :index, :locals => {:game_status => game_status, :bad_guesses => bad_guesses, :good_guesses => good_guesses, :word => word}
end
Solution 1:[1]
Looking at this:
<% if defined?bad_guesses %>
<% bad_guesses.each do |i| %>
<%= i %>
<% end %>
<% end %>
a few points:
defined?a
is bad style; usedefined?(bad_guesses)
ordefined? bad_guesses
instead.defined?
checks if it's defined, so if you sayfoo = nil; defined? foo
it will be true.
You could alternatively use this:
defined?(bad_guesses) && bad_guesses
On the other hand, undefined instance variables are nil
by default:
# it shows undefined
defined? @non_existing_var
# but you can still check if it's truthy:
puts "found" if @non_existing_var
# it won't print anything
Similar to instance variables in this regard are hashes. The default value of an unknown key is nil.
The problem with instance variables is they are not scoped to the partial. Instead, I recommend sending your local variables as a nested hash:
locals: { data: { foo: "bar" } }
Then you can safely check for values which may not exist:
if data[:foo]
# this runs
elsif data[:non_existent]
# this doesnt run
end
Solution 2:[2]
For my purposes, the following syntax worked:
<% if some_var %>
<%= some_var %>
<% end %>
This block is rendered if some_var is not nil.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | max pleaner |
Solution 2 |