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
|