Skip to content
Tags

,

Use of && in avoiding ‘undefined method on nil’ erros

June 22, 2011

Pasted from here: http://collectiveidea.com/blog/archives/2011/06/21/the-billy-baldwin-of-conditional-assignment/

The magic of the &&= operator is that it only sets variables that are… already set! The usefulness of this may not be immediately apparent, but maybe you’ve written code like this:

class Article < ActiveRecord::Base
  validates :title, :body, :presence => true

  before_save :clean_summary

  private
    def clean_summary
      self.summary = summary.squish
    end
end

The problem with this code is that the article summary isn’t required. What if an article’s summary is nil? We’ll get a NoMethodErrortrying to call squish1 on nil. Oftentimes, the fix looks like this:

def clean_summary
  self.summary = summary && summary.squish
end

which looks eerily similar to our current_user memoization expansion. So instead, try:

def clean_summary
  self.summary &&= summary.squish
end

What happens if the && and replaced with the ‘and’ operator:

while in both cases you will not get the nil error, (because the evaluation will be done using short circuit evaluation which will not call the .squish when there is a nil present, the value  that will be stored in summary will change when summary is not nil.

The ‘and’ operator necessarily gives the variable the value of the first variable before evaluating the expression, and not the value  returned by the expression

 
ruby-1.9.2-p180 :105 > a = nil
 => nil 
ruby-1.9.2-p180 :106 > c = a.compact
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.compact
	from (irb):106
	from /Users/gagan/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:44:in `start'
	from /Users/gagan/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:8:in `start'
	from /Users/gagan/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands.rb:23:in `<top (required)>'
	from script/rails:6:in `require'
	from script/rails:6:in `<main>'
ruby-1.9.2-p180 :107 > c = a and a.compact
 => nil 
ruby-1.9.2-p180 :108 > c
 => nil 
ruby-1.9.2-p180 :109 > c = a && a.compact
 => nil 
ruby-1.9.2-p180 :110 > c
 => nil 
ruby-1.9.2-p180 :111 > a = [1 , nil]
 => [1, nil] 
ruby-1.9.2-p180 :112 > c = a and a.compact
 => [1] 
ruby-1.9.2-p180 :113 > c
 => [1, nil] 
ruby-1.9.2-p180 :114 > c = a && a.compact
 => [1] 
ruby-1.9.2-p180 :115 > c
 => [1]

you want ‘&&’ !

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: