Class: Dialekt::Model::SetProperty

Inherits:
BasicProperty show all
Defined in:
lib/dialekt/model/set_property.rb

Overview

Base class for DSL set accessors

Defined Under Namespace

Classes: Entry

Instance Attribute Summary

Attributes inherited from BasicProperty

#name, #type

Instance Method Summary collapse

Methods inherited from BasicProperty

#access_value, #factory, #factory=, #get_value, #set_value, #transformer, #transformer=

Constructor Details

#initialize(name:, value_type: nil, type: Set, factory: -> { Set.new }, transformer: ->(value:) { value&.to_set }) ⇒ SetProperty

Returns a new instance of SetProperty.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/dialekt/model/set_property.rb', line 30

def initialize(
  name:,
  value_type: nil,
  type: Set,
  factory: -> { Set.new },
  transformer: ->(value:) { value&.to_set }
)
  super(
    name: name,
    type: type,
    factory: factory,
    transformer: transformer
  )

  @value_type = value_type
  @value_transformer = nil
  @entries = {}
end

Instance Method Details

#add_entry(entry:, target:, value:, &block) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/dialekt/model/set_property.rb', line 121

def add_entry(entry:, target:, value:, &block)
  set = get_value(shape: set_shape, target: target)

  if entry.value_transformer
    begin
      value = entry.value_transformer.call(object: target, value: value)
    rescue StandardError
      raise ArgumentError, "Cannot transform value '#{value}' for property '#{@name}' (#{entry.name})"
    end
  end

  unless target.class.dialekt_type_checker.valid?(type: entry.value_type, value: value)
    raise TypeError, "Illegal value type '#{value.class}' for property '#{@name}' (#{entry.name})"
  end

  set.add(value)

  Docile.dsl_eval(value, &block) if !value.nil? && block

  value
end

#entriesObject



49
50
51
# File 'lib/dialekt/model/set_property.rb', line 49

def entries
  @entries.dup.freeze
end

#entries=(entries) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/dialekt/model/set_property.rb', line 53

def entries=(entries)
  case entries
  when Hash
    @entries = {}

    entries.each do |name, entry|
      if name != entry.name
        raise ArgumentError, "Entry key '#{name}' does not match entry name for '#{entry.name}'"
      end

      define_entry(entry)
    end
  when Enumerable
    @entries = {}
    entries.each { |entry| define_entry(entry) }
  else
    raise ArgumentError, "Entries must be an Enumerable or a Hash"
  end
end

#entry(name, value_type: nil, value_transformer: nil) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/dialekt/model/set_property.rb', line 73

def entry(name, value_type: nil, value_transformer: nil)
  entry = Entry.new(
    name: name.to_sym,
    value_type: value_type || @value_type,
    value_transformer: value_transformer || @value_transformer
  )

  define_entry(entry)
end

#set_shapeObject



112
113
114
115
116
117
118
119
# File 'lib/dialekt/model/set_property.rb', line 112

def set_shape
  @set_shape ||= BasicProperty::Shape.new(
    name: @name,
    type: @type,
    factory: @factory,
    transformer: @transformer
  )
end

#setup(owner:) ⇒ Object



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
# File 'lib/dialekt/model/set_property.rb', line 83

def setup(owner:)
  super

  property = self

  if @entries.empty?
    raise StandardError, "Please specify a value type for property '#{@name}'" if @value_type.nil?

    define_entry(Entry.new(name: owner.dialekt_inflector.singularize(@name), value_type: @value_type))
  end

  @value_type ||= owner.class.type_checker.union_type(types: @entries.values.map(&:value_type))

  owner.define_method(@name) do |value = EMPTY, &block|
    value = property.access_value(shape: property.set_shape, target: self, value: value, &block)
    value.dup.freeze
  end

  owner.define_method(:"#{@name}=") do |value|
    property.set_value(shape: property.set_shape, target: self, value: value)
  end

  @entries.each_value do |entry|
    owner.define_method(entry.name) do |value, &block|
      property.add_entry(entry: entry, target: self, value: value, &block)
    end
  end
end

#to_sObject



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/dialekt/model/set_property.rb', line 155

def to_s
  result = StringIO.new

  result << @name << " (" << self.class.base_name << ") {"
  result << "type: " << @type
  result << ", value_type: " << @value_type
  result << ", factory: " << @factory.source_info if @factory
  result << ", transformer: " << @transformer.source_info if @transformer
  result << ", entries: [" << @entries.values.map(&:name).join(", ") << "]"
  result << "}"

  result.string
end

#value_factory(factory = EMPTY) ⇒ Object



151
152
153
# File 'lib/dialekt/model/set_property.rb', line 151

def value_factory(factory = EMPTY)
  factory == EMPTY ? @value_factory : (@value_factory = factory&.call_adapter)
end

#value_transformer(transformer = EMPTY) ⇒ Object



147
148
149
# File 'lib/dialekt/model/set_property.rb', line 147

def value_transformer(transformer = EMPTY)
  transformer == EMPTY ? @value_transformer : (@value_transformer = transformer&.call_adapter)
end

#value_type(type = EMPTY) ⇒ Object



143
144
145
# File 'lib/dialekt/model/set_property.rb', line 143

def value_type(type = EMPTY)
  type == EMPTY ? @value_type : (@value_type = type)
end