Module: Tins::Concern

Defined in:
lib/tins/concern.rb,
lib/tins/xt/concern.rb

Overview

Concern provides a mechanism for module configuration that persists across inheritance and inclusion boundaries using thread-local storage.

This module implements a pattern where modules can be configured with arguments that are then available throughout the module’s lifecycle in a thread-safe manner. It’s particularly useful for implementing configuration-based concerns that need to maintain state across different scopes.

Examples:

Configured concern usage

module MyConcern
  extend Tins::Concern
end

# Configure the concern with parameters
include MyConcern.tins_concern_configure(:option1, :option2)

Defined Under Namespace

Modules: ModuleMixin

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object

Extends the base object with dependency tracking capabilities.

This method initializes an instance variable on the base object to store dependency information.

Parameters:

  • base (Object)

    the object being extended



38
39
40
# File 'lib/tins/concern.rb', line 38

def self.extended(base)
  base.instance_variable_set("@_dependencies", [])
end

Instance Method Details

#append_features(base) ⇒ Boolean

The append_features method includes dependencies and class methods in the base class.

Parameters:

  • base (Object)

    the base class to include features in

Returns:

  • (Boolean)

    true if features were appended, false otherwise



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/tins/concern.rb', line 47

def append_features(base)
  if base.instance_variable_defined?("@_dependencies")
    base.instance_variable_get("@_dependencies") << self
    false
  else
    return false if base < self
    @_dependencies.each { |dep| base.send(:include, dep) }
    super
    base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
    base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
    Thread.current[:tin_concern_args] = nil
    true
  end
end

#class_methods(&block) ⇒ Module

Defines a ClassMethods module for the current class and evaluates the given block within it.

ClassMethods module

Parameters:

  • block (Proc)

    The block to be evaluated in the context of the

Returns:

  • (Module)

    The ClassMethods module that was defined or retrieved



121
122
123
124
125
126
127
128
# File 'lib/tins/concern.rb', line 121

def class_methods(&block)
  modul = const_get(:ClassMethods) if const_defined?(:ClassMethods, false)
  unless modul
    modul = Module.new
    const_set(:ClassMethods, modul)
  end
  modul.module_eval(&block)
end

#included(base = nil, &block) ⇒ Object

The included method is called when the module is included in a class or module.

Parameters:

  • base (Object) (defaults to: nil)

    the class or module that includes this module

  • block (Proc)

    optional block to be executed when included



90
91
92
93
94
95
96
97
98
# File 'lib/tins/concern.rb', line 90

def included(base = nil, &block)
  if base.nil?
    instance_variable_defined?(:@_included_block) and
      raise StandardError, "included block already defined"
    @_included_block = block
  else
    super
  end
end

#prepend_features(base) ⇒ Boolean

Prepends the features of this module to the base class.

This method handles the inclusion of dependencies and class methods when a module is included in a class. It manages dependency tracking and ensures proper extension of the base class with ClassMethods.

Parameters:

  • base (Class)

    the class that includes this module

Returns:

  • (Boolean)

    true if the module was successfully prepended, false otherwise



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/tins/concern.rb', line 70

def prepend_features(base)
  if base.instance_variable_defined?("@_dependencies")
    base.instance_variable_get("@_dependencies") << self
    false
  else
    return false if base < self
    @_dependencies.each { |dep| base.send(:include, dep) }
    super
    base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
    base.class_eval(&@_prepended_block) if instance_variable_defined?("@_prepended_block")
    Thread.current[:tin_concern_args] = nil
    true
  end
end

#prepended(base = nil, &block) ⇒ Object

The prepended method handles the setup of a block for prepend functionality or delegates to the superclass implementation

Parameters:

  • base (Object) (defaults to: nil)

    the base object to prepend to, or nil to set up a block

  • block (Proc)

    the block to be used for prepend functionality



105
106
107
108
109
110
111
112
113
# File 'lib/tins/concern.rb', line 105

def prepended(base = nil, &block)
  if base.nil?
    instance_variable_defined?(:@_prepended_block) and
      raise StandardError, "prepended block already defined"
    @_prepended_block = block
  else
    super
  end
end