File: builder.rb

package info (click to toggle)
ruby-virtus 2.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 660 kB
  • sloc: ruby: 4,378; makefile: 2
file content (133 lines) | stat: -rw-r--r-- 2,890 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
module Virtus

  # Class to build a Virtus module with it's own config
  #
  # This allows for individual Virtus modules to be included in
  # classes and not impacted by the global Virtus config,
  # which is implemented using Virtus::config.
  #
  # @private
  class Builder

    # Return module
    #
    # @return [Module]
    #
    # @api private
    attr_reader :mod

    # Return config
    #
    # @return [config]
    #
    # @api private
    attr_reader :config

    # @api private
    def self.call(options, &block)
      new(Configuration.new(options, &block)).mod
    end

    # @api private
    def self.pending
      @pending ||= []
    end

    # Initializes a new Builder
    #
    # @param [Configuration] config
    # @param [Module] mod
    #
    # @return [undefined]
    #
    # @api private
    def initialize(conf, mod = Module.new)
      @config, @mod = conf, mod
      add_included_hook
      add_extended_hook
    end

    # @api private
    def extensions
      [Model::Core]
    end

    # @api private
    def options
      config.to_h
    end

    private

    # Adds the .included hook to the anonymous module which then defines the
    # .attribute method to override the default.
    #
    # @return [Module]
    #
    # @api private
    def add_included_hook
      with_hook_context do |context|
        mod.define_singleton_method :included do |object|
          Builder.pending << object unless context.finalize?
          context.modules.each { |mod| object.send(:include, mod) }
          object.define_singleton_method(:attribute, context.attribute_method)
        end
      end
    end

    # @api private
    def add_extended_hook
      with_hook_context do |context|
        mod.define_singleton_method :extended do |object|
          context.modules.each { |mod| object.extend(mod) }
          object.define_singleton_method(:attribute, context.attribute_method)
        end
      end
    end

    # @api private
    def with_hook_context
      yield(HookContext.new(self, config))
    end

  end # class Builder

  # @private
  class ModelBuilder < Builder
  end # ModelBuilder

  # @private
  class ModuleBuilder < Builder

    private

    # @api private
    def add_included_hook
      with_hook_context do |context|
        mod.define_singleton_method :included do |object|
          super(object)
          object.extend(ModuleExtensions)
          ModuleExtensions.setup(object, context.modules)
          object.define_singleton_method(:attribute, context.attribute_method)
        end
      end
    end

  end # ModuleBuilder

  # @private
  class ValueObjectBuilder < Builder

    # @api private
    def extensions
      super << ValueObject::AllowedWriterMethods << ValueObject::InstanceMethods
    end

    # @api private
    def options
      super.merge(:writer => :private)
    end

  end # ValueObjectBuilder

end # module Virtus