Using Null Objects can make life a lot easier and avoid having excessive nil?
checks.
Avdi Grimm made an excellent library called Naught which makes
working with and building Null Objects easier. Thank you Avdi for making
this possible!
This library makes ActiveRecord Models aware of Null Objects and act as you would hope they would when using null objects in your project.
This is specially useful when combined with a decorator library like Draper.
By knowing you have an object instead of the dreaded nil
you can just
decorate it and your view won't know any different.
Add this line to your application's Gemfile:
gem 'active_null'
And then execute:
$ bundle
Or install it yourself as:
$ gem install active_null
For each model you would like to be null aware, extend ActiveNull
.
class Post < ActiveRecord::Base
extend ActiveNull
has_many :comments
end
class Comment < ActiveRecord::Base
extend ActiveNull
belongs_to :post
end
You can now do things like this:
Post.null # => <null:Post>
Post.null.comments # => <ActiveRecord::Relation []>
Comment.null # => <null:Comment>
Comment.null.post # => <null:Post>
Comment.new.post # => <null:Post>
Post.find_by(id: 1) # => <null:Post>
You may find you want your Null Object to respond to certain methods in a specific way. These methods might be new or they might be overrides of the default Null Object definition. You can define this in your model:
class Post < ActiveRecord::Base
extend ActiveNull
null_model do
def some_method
# special functionality
end
end
end
When using polymorphic relationships, ActiveNull must be told a default model to use for the Null Object representation.
class Post < ActiveRecord::Base
extend ActiveNull
belongs_to :author, polymorphic: true
null_defaults_for_polymorphic author: 'User'
end
If you have Draper
included in your project, the Null Object versions of
your model will respond as expected to decorate
.
You can then safely do something like:
@post = Post.find_by(id: 1).decorate
You can also define an alias for your null
method for convenience
class User < ActiveRecord::Base
extend ActiveNull
null_model(:guest)
end
User.first # => <User>
User.null # => <null:User>
User.guest # => <null:User>
- Fork it ( https://github.com/Originate/active_null/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request