Module: MetaRuby::ModelAsClass

Extended by:
Attributes
Includes:
Attributes, Registration
Defined in:
lib/metaruby/model_as_class.rb

Overview

Extend in classes that are used to represent models

Alternatively, you can create a module that describes the metamodel and extend the base model class with it

Examples:

class MyBaseClass
  extend MetaRuby::ModelAsClass
end
module MyBaseMetamodel
  include MetaRuby::ModelAsModule
end
class MyBaseModel
  extend MyBaseMetamodel
end

Constant Summary collapse

FROM_NEW_SUBMODEL_TLS =

This flag is used to notify #inherited that it is being called from new_submodel, in which case it should not

This mechanism works as:

- inherited(subclass) is called right away after class.new is called
  (so, we don't have to take recursive calls into account)
- it is a TLS, so thread safe
:metaruby_class_new_called_from_new_submodel

Constants included from Attributes

Attributes::ANCESTORS_ACCESS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Attributes

define_single_value_with_promotion, define_single_value_without_promotion, included, inherited_attribute, inherited_single_value_attribute, map_with_promotion, map_without_promotion, nomap_with_promotion, nomap_without_promotion

Methods included from Registration

accessible_by_name?, #accessible_by_name?, #clear_model, #clear_registration_as_constant, #clear_submodels, deregister_constant, #deregister_submodels, #each_submodel, #has_submodel?, #permanent_definition_context?, #permanent_model?, #register_submodel, #submodels

Instance Attribute Details

#definition_locationObject

The call stack at the point of definition of this model



26
27
28
# File 'lib/metaruby/model_as_class.rb', line 26

def definition_location
  @definition_location
end

#nameString

Sets a name on this model

Only use this on ‘anonymous models’, i.e. on models that are not meant to be assigned on a Ruby constant

Returns:

  • (String)

    the assigned name



39
40
41
# File 'lib/metaruby/model_as_class.rb', line 39

def name=(name)
    @name = name
end

Class Method Details

.extend_object(klass) ⇒ Object



124
125
126
127
# File 'lib/metaruby/model_as_class.rb', line 124

def self.extend_object(klass)
    super
    klass.instance_variable_set :@name, nil
end

Instance Method Details

#apply_block(&block) ⇒ Object

Called to apply a DSL block on this model



89
90
91
# File 'lib/metaruby/model_as_class.rb', line 89

def apply_block(&block)
    class_eval(&block)
end

#docString

Returns set or get the documentation text for this model.

Returns:

  • (String)

    set or get the documentation text for this model



29
# File 'lib/metaruby/model_as_class.rb', line 29

inherited_single_value_attribute :doc

#inherited(subclass) ⇒ Object

Registers submodels when a subclass is created



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/metaruby/model_as_class.rb', line 99

def inherited(subclass)
    from_new_submodel = Thread.current[FROM_NEW_SUBMODEL_TLS]
    Thread.current[FROM_NEW_SUBMODEL_TLS] = false

    subclass.definition_location = 
        if MetaRuby.keep_definition_location?
            caller_locations
        else Array.new
        end
    subclass.instance_variable_set :@name, nil
    super
    subclass.permanent_model = subclass.accessible_by_name? &&
        subclass.permanent_definition_context?
    if !from_new_submodel
        subclass.instance_variable_set :@name, nil
        setup_submodel(subclass)
        register_submodel(subclass)
    end
end

#new_submodel(name: nil, register: true, **submodel_options, &block) ⇒ Module

Creates a new submodel of self

Parameters:

  • options (Hash)

    a customizable set of options

Returns:

  • (Module)

    a subclass of self



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/metaruby/model_as_class.rb', line 75

def new_submodel(name: nil, register: true, **submodel_options, &block)
    Thread.current[FROM_NEW_SUBMODEL_TLS] = true
    model = self.class.new(self)
    model.permanent_model = false
    model.instance_variable_set :@name, nil
    model.name = name if name
    setup_submodel(model, **submodel_options, &block)
    if register
        register_submodel(model)
    end
    model
end

#provides(model_as_module) ⇒ Object

Call to declare that this model provides the given model-as-module



120
121
122
# File 'lib/metaruby/model_as_class.rb', line 120

def provides(model_as_module)
    include model_as_module
end

#provides?(model_as_module) ⇒ Boolean

Tests whether the given model-as-module is provided by self

Returns:

  • (Boolean)


130
131
132
# File 'lib/metaruby/model_as_class.rb', line 130

def provides?(model_as_module)
    self <= model_as_module
end

#setup_submodel(submodel, register: true, **options, &block) ⇒ Object

Called at the end of the definition of a new submodel



94
95
96
# File 'lib/metaruby/model_as_class.rb', line 94

def setup_submodel(submodel, register: true, **options, &block)
    submodel.apply_block(&block) if block
end

#supermodelClass

The model next in the ancestry chain, or nil if self is root

Returns:

  • (Class)


52
53
54
55
56
# File 'lib/metaruby/model_as_class.rb', line 52

def supermodel
    if superclass.respond_to?(:supermodel)
        return superclass
    end
end