Module: Flows::Util::InheritableSingletonVars
- Defined in:
- lib/flows/util/inheritable_singleton_vars.rb,
lib/flows/util/inheritable_singleton_vars/dup_strategy.rb,
lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb
Overview
Namespace for utility classes which allows you to define specific behaviour for singleton variables in the context of inheritance.
When you're writing some abstraction in Ruby one of the ways is to provide some base class and allow child classes to configure behaviour through class-level DSL. Something like that:
class UserModel < BaseModel
field :name
field :username
end
The first problem here is where to store configuration values? In the most cases of such DSL it's singleton variables.
But what will happen if we do something like this:
class AdminModel < UserModel
field :pgp_key
end
Which fields are defined for admin? :name
, :username
and :pgp_key
?
Or :pgp_key
only? Both options are possible and can be implemented.
But working with singleton variables is confusing and related code is confusing also.
So, it's better to implement set of utility modules to define expected behaviour
in a human-friendly format.
The second problem is default values for singleton variables.
In case of instance variables everything is simple:
you have a constructor (#initializer
) and it's the right place to set instance variables defaults.
In case of singleton variables you can do it in .extended
or .included
callbacks.
But this callback will not be executed on child classes. So, we have to add .inherited
callback to the mix.
Confusing? Yes. So, it's better to not think about it each time and
use some helpers to explicitly define behaviour.
Modules under this namespace provide helpers for defining defaults and inheritance strategy for your singleton variables.
Each strategy here is using following way of injecting into yours abstract classes:
class BaseSomething
SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
**
)
include SingeltonVarsSetup # extend also will work
end
In case of extensions and mixins:
module MyExtension
SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
**
)
include SingeltonVarsSetup # extend also will work
end
class SomethingA
extend MyExtension
end
module MyMixin
SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
**
)
include SingeltonVarsSetup # extend also will work
end
class SomethingB
include MyMixin
end
Moreover, you can use multiple strategies in the same class.
Defined Under Namespace
Modules: DupStrategy, IsolationStrategy