Class: NilClass

Inherits:
Object show all
Defined in:
activesupport/lib/active_support/whiny_nil.rb,
activesupport/lib/active_support/json/encoding.rb,
activesupport/lib/active_support/core_ext/object/try.rb,
activesupport/lib/active_support/core_ext/object/blank.rb,
activesupport/lib/active_support/core_ext/object/to_param.rb,
activesupport/lib/active_support/core_ext/object/duplicable.rb

Overview

Extensions to nil which allow for more helpful error messages for people who are new to Rails.

Ruby raises NoMethodError if you invoke a method on an object that does not respond to it:

$ ruby -e nil.destroy
-e:1: undefined method `destroy' for nil:NilClass (NoMethodError)

With these extensions, if the method belongs to the public interface of the classes in NilClass::WHINERS the error message suggests which could be the actual intended class:

$ rails runner nil.destroy
...
You might have expected an instance of ActiveRecord::Base.
...

NilClass#id exists in Ruby 1.8 (though it is deprecated). Since id is a fundamental method of Active Record models NilClass#id is redefined as well to raise a RuntimeError and warn the user. She probably wanted a model database identifier and the 4 returned by the original method could result in obscure bugs.

The flag config.whiny_nils determines whether this feature is enabled. By default it is on in development and test modes, and it is off in production mode.

Constant Summary collapse

METHOD_CLASS_MAP =
Hash.new
AS_JSON =
ActiveSupport::JSON::Variable.new('null').freeze

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object (private)



44
45
46
47
48
49
50
# File 'activesupport/lib/active_support/whiny_nil.rb', line 44

def method_missing(method, *args)
  if klass = METHOD_CLASS_MAP[method]
    raise_nil_warning_for klass, method, caller
  else
    super
  end
end

Class Method Details

.add_whiner(klass) ⇒ Object



30
31
32
33
34
# File 'activesupport/lib/active_support/whiny_nil.rb', line 30

def self.add_whiner(klass)
  methods = klass.public_instance_methods - public_instance_methods
  class_name = klass.name
  methods.each { |method| METHOD_CLASS_MAP[method.to_sym] = class_name }
end

Instance Method Details

#as_json(options = nil) ⇒ Object

:nodoc:



175
# File 'activesupport/lib/active_support/json/encoding.rb', line 175

def as_json(options = nil) AS_JSON end

#blank?Boolean

nil is blank:

nil.blank? # => true

Returns:

  • (Boolean)


45
46
47
# File 'activesupport/lib/active_support/core_ext/object/blank.rb', line 45

def blank?
  true
end

#duplicable?Boolean

nil is not duplicable:

nil.duplicable? # => false
nil.dup         # => TypeError: can't dup NilClass

Returns:

  • (Boolean)


35
36
37
# File 'activesupport/lib/active_support/core_ext/object/duplicable.rb', line 35

def duplicable?
  false
end

#idObject

Raises a RuntimeError when you attempt to call id on nil.

Raises:

  • (RuntimeError)


39
40
41
# File 'activesupport/lib/active_support/whiny_nil.rb', line 39

def id
  raise RuntimeError, "Called id for nil, which would mistakenly be #{object_id} -- if you really wanted the id of nil, use object_id", caller
end

#to_paramObject



9
10
11
# File 'activesupport/lib/active_support/core_ext/object/to_param.rb', line 9

def to_param
  self
end

#try(*args) ⇒ Object

Calling try on nil always returns nil. It becomes specially helpful when navigating through associations that may return nil.

Examples

nil.try(:name) # => nil

Without try

@person && !@person.children.blank? && @person.children.first.name

With try

@person.try(:children).try(:first).try(:name)


50
51
52
# File 'activesupport/lib/active_support/core_ext/object/try.rb', line 50

def try(*args)
  nil
end