Reputation:
If an html.erb file is rendered without variables assigned in a controller (e.g. @user = params["user_name"] )
then why does it view @user
as nil
instead of throwing a NameError: undefined local variable
.
For Example:
<%= render partial: "greeting", locals: { user: @user } if @user %>
This will render the greeting if a controller passes it a @user
, but if the page is rendered for the first time and the user hasn't entered their username yet the greeting will simply not be there, instead of causing an error. It seems to me that @user
would never be declared in the local scope the html.erb is executing in, so it should cause the error.
What's happening here? Perhaps the @
is somehow preprocessed to mean treat the variable as a symbol and use that as the key in a params
hash and return the result?
Upvotes: 3
Views: 504
Reputation: 369468
then why does it view
@user
asnil
instead of throwing aNameError: undefined local variable
.
Well, it's not a local variable, it's an instance variable.
But even local variables behave the same way:
if false
local_var = 42 # needed so Ruby knows `local_var` isn't a method call
end
local_var
# => nil
@instance_variable
# => nil
$global_variable
# => nil
But strangely:
Constant
# NameError: uninitialized constant Constant
@@class_variable
# NameError: uninitialized class variable @@class_variable in Object
Upvotes: 0
Reputation: 12558
Uninitialized instance variables (@...
) evaluate to nil
. You can still check if an instance variable has been assigned (including assignment to nil
) by using the defined?
method:
[1] pry(main)> defined? @test
=> nil
[2] pry(main)> @test = nil
=> nil
[3] pry(main)> defined? @test
=> "instance-variable"
Upvotes: 5