Last active
August 29, 2015 14:01
-
-
Save sbellware/f46d2636da005b379ae0 to your computer and use it in GitHub Desktop.
Declaring null object default dependencies using @avdi's Naught library, and templated modules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Example | |
| include NullDefault[:some_dependency] | |
| include NullDefault[:some_other_dependency] | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'naught' | |
| class NullDefault < Module | |
| def self.[](attr_name) | |
| new attr_name | |
| end | |
| def initialize(attr_name) | |
| reader_name = attr_name | |
| writer_name = :"#{attr_name}=" | |
| var_name = :"@#{attr_name}" | |
| mod = Module.new do | |
| define_method reader_name do | |
| val = instance_variable_get var_name | |
| if val.nil? | |
| val = Null.object | |
| instance_variable_set var_name, val | |
| end | |
| val | |
| end | |
| define_method writer_name do |val| | |
| instance_variable_set var_name, val | |
| end | |
| end | |
| include mod | |
| end | |
| module Null | |
| extend self | |
| def object | |
| ::Naught.build.new | |
| end | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ex = Example.new | |
| ex.some_dependency.some_method | |
| ex.some_other_dependency.another_method |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting approach. It does require annotations. Another way to achieve a similar result would be to implement a generic factory:
Example:
With this approach, you can use the
NullDefaultBuilderin your tests, but if you want null objects in your production code, you have to make it explicit.You could also create a small mix in to override the class'
newmethod and use the builder:This is one thing I really love about ruby, you can hide a bunch of explicit, decoupled code behind a small, implicit interface. Get the best of both worlds.