Ask A Question

Notifications

You’re not receiving notifications from this thread.

Refactoring with the Null Object Pattern Discussion

Jamie Barton Jamie Barton

One thing to watch out for with NullObjects is Relations. Rails recently introduced a Relation#none method which will help in these cases. Imagine a Post has_many Comments, you'd want to create a NullObject for the Post and create a method called comments which returned Comment.none

See http://api.rubyonrails.org/... for more information.

Reply

Yes, the none method is super helpful for situations like that. I'm really glad they added it.

Reply

This is definitely more robust but is implicitly less expressive (in my opinion). My code can tend to suffer from IF-itis and maintainability down the road so this is useful as a pattern to consider when re-factoring. Thanks!

Reply

Definitely. You can use this a bit too early and it just is more painful than anything. The example of the navigation is bad because right now, I'd rather have the if statement, but in the future as it gets way more complex, null objects would make more sense.

There's certainly a balance to find when applying this (like any pattern).

Reply

This is super helpful man :)

Reply

Awesome, glad you liked it! :) Definitely want to cover more of these design patterns and their practical uses.

Reply

This is really cool. I am in a situation where I have many user roles and would love to be able to serve a navbar for each role. Yay! Thanks. Also in my views I have used the decorator pattern like `user_decorator.rb` and then made methods with a method `link_to_project` and then in that method done something like `object.project.present? ? h.link_to(object.project.name, project_path(object.project)) : ""` or, similar to your example in the video.

`comment_decorator.rb` with a method called `link_to_user` with `object.user.present? ? h.link_to(object.user.name, user_path(object.user)) : "Anonymous"`

I have done this everywhere so I might take the null object pattern to deal with the nav first then once I get familiar try and tackle all my decorator stuff.

Reply

A combination of decorators and the null object pattern can go together quite well. Curious to hear how it goes for you!

Reply

This is awesome! I'm glad you did a screencast on this, the talk from Sandi was just way too good not to share, and proliferate those ideas!

Reply

I agree! It was also awesome to meet you in person Jared!

Reply
Kohl Kohlbrenner Kohl Kohlbrenner

@excid3:disqus awesome episode! What are your thoughts on doing a screencast covering payments? I'm interested in seeing how paywalls are set up. Is it simple as using something like pundit? I've tried searching online for resources and have come up empty.

Reply
creativereason creativereason

Great episode Chris. FYI, your link to source code is missing. Found it on github, looks like a missing link.

Reply

Thanks! Fixed that link.

Reply

Really helpful, thanks for screencast

Reply

Really cool video, the null object pattern is definitely a cleaner way than using :try.
I'm trying to use it in combination with the globalize gem, and get stuck when I want to force the locale. Per example, the standard use is article.title and when I want to force the language I do article.title(:en). In this particular case, if no article is found, MissingArticle.new method is called and generates a wrong number of arguments given (1 for 0) error. Do you have any hint on this ?

Reply

simply use def name(*) 'name'; end did the trick

Reply

Chris, this one is awesome. I don't know how I missed this episode before, but I'm glad I just ran into it. Would be amazing to see a screencast where you collect the most important patterns/tricks. I guess there are a bunch of guys including me who don't even know about the existence of them, so you shouldn't even explain everything just let us know about it and mention some resources to read.

Reply

null object ftw

Reply

Something very interesting about this code is that with that "def user" you're overriding the definition of the parent class (ActiveRecord::Base) for the #user method, when actually there is none! :D Because of the way Active Record works, the #user method is generated at runtime. So, when you call super inside it, you're actually triggering that definition.

Reply

A really cool video Chris thanks!

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 82,329+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

    © 2024 GoRails, LLC. All rights reserved.