Class: Attributor::DSLCompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/attributor/dsl_compiler.rb

Overview

The reference option for an attribute is passed if a block is given

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, **options) ⇒ DSLCompiler

Returns a new instance of DSLCompiler.



17
18
19
20
# File 'lib/attributor/dsl_compiler.rb', line 17

def initialize(target, **options)
  @target = target
  @options = options
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



15
16
17
# File 'lib/attributor/dsl_compiler.rb', line 15

def options
  @options
end

#targetObject

Returns the value of attribute target.



15
16
17
# File 'lib/attributor/dsl_compiler.rb', line 15

def target
  @target
end

Instance Method Details

#attribute(name, attr_type = nil, **opts, &block) ⇒ Object



36
37
38
39
# File 'lib/attributor/dsl_compiler.rb', line 36

def attribute(name, attr_type=nil, **opts, &block)
  raise AttributorException, "Attribute names must be symbols, got: #{name.inspect}" unless name.kind_of? ::Symbol
  target.attributes[name] = define(name, attr_type, **opts, &block)
end

#attributesObject



28
29
30
31
32
33
34
# File 'lib/attributor/dsl_compiler.rb', line 28

def attributes
  if target.respond_to?(:attributes)
    target.attributes
  else
    target.keys
  end
end

#define(name, type, opts, &block) ⇒ Object #define(name, opts, &block) ⇒ Object

Creates an Attributor:Attribute with given definition.

Overloads:

  • #define(name, type, opts, &block) ⇒ Object

    With an explicit type.

    Examples:

    attribute :email, String, example: /[:email:]/

    Parameters:

    • name (symbol)

      describe name param

    • type (Attributor::Type)

      describe type param

    • opts (Hash)

      describe opts param

    • block (Block)

      describe block param

  • #define(name, opts, &block) ⇒ Object

    Assume a type of Attributor::Struct

    Examples:

    attribute :address do
      attribute :number, String
      attribute :street, String
      attribute :city, String
      attribute :state, String
    end

    Parameters:

    • name (symbol)

      describe name param

    • opts (Hash)

      describe opts param

    • block (Block)

      describe block param



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
# File 'lib/attributor/dsl_compiler.rb', line 82

def define(name, attr_type=nil, **opts, &block)
  # add to existing attribute if present
  if (existing_attribute = attributes[name])
    if existing_attribute.attributes
      existing_attribute.type.attributes(&block)
      return existing_attribute
    end
  end

  # determine inherited attribute
  inherited_attribute = nil      
  if (reference = self.options[:reference])
    if (inherited_attribute = reference.attributes[name])
      opts = inherited_attribute.options.merge(opts) unless attr_type
      opts[:reference] = inherited_attribute.type if block_given?
    end
  end

  # determine attribute type to use
  if attr_type.nil?
    if block_given?
      attr_type = Attributor::Struct
    elsif inherited_attribute
      attr_type = inherited_attribute.type
    else
      raise AttributorException, "type for attribute with name: #{name} could not be determined"
    end
  end

  Attributor::Attribute.new(attr_type, opts, &block)
end

#extra(name, attr_type = nil, **opts, &block) ⇒ Object



48
49
50
51
52
53
54
55
56
57
# File 'lib/attributor/dsl_compiler.rb', line 48

def extra(name, attr_type=nil, **opts, &block)
  if attr_type.nil?
    attr_type = Attributor::Hash.of(key: target.key_type, value: target.value_type)
  end
  target.extra_keys = name
  target.options[:allow_extra] = true
  opts[:default] ||= {}
  attr_type.options[:allow_extra] = true
  key(name, attr_type, **opts, &block)
end

#key(name, attr_type = nil, **opts, &block) ⇒ Object



41
42
43
44
45
46
# File 'lib/attributor/dsl_compiler.rb', line 41

def key(name, attr_type=nil, **opts, &block)
  unless name.kind_of?(options.fetch(:key_type, Attributor::Object).native_type)
    raise "Invalid key: #{name.inspect}, must be instance of #{options[:key_type].native_type.name}"
  end
  target.keys[name] = define(name, attr_type, **opts, &block)
end

#parse(*blocks) ⇒ Object



22
23
24
25
26
# File 'lib/attributor/dsl_compiler.rb', line 22

def parse(*blocks)
  blocks.push(Proc.new) if block_given?
  blocks.each { |block| self.instance_eval(&block) }
  self
end