Skip to content

Instantly share code, notes, and snippets.

@tylerhunt
Created February 28, 2015 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tylerhunt/462bde72ae2b681b4e36 to your computer and use it in GitHub Desktop.
Save tylerhunt/462bde72ae2b681b4e36 to your computer and use it in GitHub Desktop.
A macro to allow object dependencies to be specified at the class level with a block defining a default value. Based on attr_defaultable.
module Dependencies
# Ensure dependencies from the superclass are inherited by the subclass.
def inherited(subclass)
if superclass.respond_to?(:dependencies)
subclass.dependencies.concat dependencies
end
super
end
# Stores a list of dependency attributes for use by the initializer.
def dependencies
@dependencies ||= []
end
# Defines a new dependency attribute with a default value.
def dependency(attribute, default)
# Define a getter that lazily sets a default value.
define_method attribute do
if instance_variable_defined?(:"@#{attribute}")
instance_variable_get(:"@#{attribute}")
else
instance_variable_set(:"@#{attribute}", default.call)
end
end
# Define a setter that lazily sets a default value.
attr_writer attribute
# Mark the getter and setter as protected.
protected attribute, "#{attribute}="
# Add the attribute to the list of dependencies.
dependencies << attribute
end
end
require 'dependencies'
class Example
extend Dependencies
dependency :value, -> { :default }
end
class ExtendedExample < Example
dependency :another_value, -> { :another_default }
end
example = ExtendedExample.new
example.send(:value) # => :default
example.send(:another_value) # => :another_default
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment