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(
    **options_here
  )

  include SingeltonVarsSetup # extend also will work
end

In case of extensions and mixins:

module MyExtension
  SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
    **options_here
  )

  include SingeltonVarsSetup # extend also will work
end

class SomethingA
  extend MyExtension
end

module MyMixin
  SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
    **options_here
  )

  include SingeltonVarsSetup # extend also will work
end

class SomethingB
  include MyMixin
end

Moreover, you can use multiple strategies in the same class.

Since:

  • 0.4.0

Defined Under Namespace

Modules: DupStrategy, IsolationStrategy