Avoiding nil in Ruby programs (and NULL in databases)
Most Ruby developers see the following exception in production, no matter how well taken care their codebase is:
1 NoMethodError: undefined method `name' for nil:NilClass
And the search begins. Was it a user? Or another object that would respond to
#name if present? Was it a typo? Many different statements can return
1 2 3 4 5 6 session[:blog_pozt] # => nil session[:current_user] # => nil @currentz_uzer # => nil array[length + 1] # => nil if false then 1 end # => nil empty_method() # => nil
Our preference is to return anything but nil. A quick improvement is to
return a symbol! Authentication Ruby gems return
default, but we can do better:
1 2 3 4 5 6 def current_user super || :guest_user end # Now the error would read: NoMethodError: undefined method `name' for :guest_user:Symbol
A symbol shows the source of the problem within the (otherwise generic) error message.
NOT NULL database constraints, or Rails validations?
Both! Our preference is to add a
null: false constraint to any new column in
migrations that store required values. The Rails presence validation ensures
forms and error messages work as intended, while the DB constraint will ensure
that no console session, bug, factory, ourselves when sleepy, or any connection
to our DB store invalid data.
Even when the field is not required, a constraint with a default value is
better than allowing nil (
null: false, default: ""). That way we ensure we
always deal with instances of
String and not also of
NilClass, avoiding type
checks and potential bugs.