Class: ModelBinding

Inherits:
Object
  • Object
show all
Includes:
Observer
Defined in:
lib/command_handlers/models/model_binding.rb

Constant Summary collapse

@@property_type_converters =
{
  :undefined => lambda { |value| value },
  :fixnum => lambda { |value| value.to_i },
  :array => lambda { |value| value.to_a }
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_model, property_name_expression, property_type = :undefined, binding_options = nil) ⇒ ModelBinding

Returns a new instance of ModelBinding.



12
13
14
15
16
17
18
# File 'lib/command_handlers/models/model_binding.rb', line 12

def initialize(base_model, property_name_expression, property_type = :undefined, binding_options = nil)
  property_type = :undefined if property_type.nil?
  @base_model = base_model
  @property_name_expression = property_name_expression
  @property_type = property_type
  @binding_options = binding_options || {}
end

Instance Attribute Details

#binding_optionsObject (readonly)

Returns the value of attribute binding_options.



6
7
8
# File 'lib/command_handlers/models/model_binding.rb', line 6

def binding_options
  @binding_options
end

#property_typeObject (readonly)

Returns the value of attribute property_type.



6
7
8
# File 'lib/command_handlers/models/model_binding.rb', line 6

def property_type
  @property_type
end

Instance Method Details

#add_observer(observer) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/command_handlers/models/model_binding.rb', line 77

def add_observer(observer)
  if nested_property?
    nested_property_observers = nested_property_observers_for(observer)
    nested_models.zip(nested_property_names).each do |model, property_name|
      model.extend ObservableModel unless model.is_a?(ObservableModel)
      model.add_observer(property_name, nested_property_observers[property_name]) unless model.has_observer?(property_name, nested_property_observers[property_name])
    end
  else
    model.extend ObservableModel unless model.is_a?(ObservableModel)
    model.add_observer(property_name, observer)
  end
end

#base_modelObject



35
36
37
# File 'lib/command_handlers/models/model_binding.rb', line 35

def base_model
  @base_model
end

#evaluate_options_propertyObject



96
97
98
# File 'lib/command_handlers/models/model_binding.rb', line 96

def evaluate_options_property
  model.send(property_name + "_options")
end

#evaluate_propertyObject



93
94
95
# File 'lib/command_handlers/models/model_binding.rb', line 93

def evaluate_property
  model.send(property_name)
end

#modelObject



19
20
21
# File 'lib/command_handlers/models/model_binding.rb', line 19

def model
  nested_property? ? nested_model : base_model
end

#model_property_namesObject

Model representing nested property names e.g. property name expression “address.state” gives [:address]



53
54
55
# File 'lib/command_handlers/models/model_binding.rb', line 53

def model_property_names
  nested_property_names[0...-1]
end

#nested_modelObject



32
33
34
# File 'lib/command_handlers/models/model_binding.rb', line 32

def nested_model
  nested_models.last
end

#nested_modelsObject

e.g. person.address.state returns [person, person.address]



23
24
25
26
27
28
29
30
31
# File 'lib/command_handlers/models/model_binding.rb', line 23

def nested_models
  @nested_models = [base_model]
  model_property_names.reduce(base_model) do |reduced_model, nested_model_property_name|
    reduced_model.send(nested_model_property_name).tap do |new_reduced_model|
      @nested_models << new_reduced_model
    end
  end
  @nested_models
end

#nested_property?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/command_handlers/models/model_binding.rb', line 56

def nested_property?
  property_name_expression.include?(".")
end

#nested_property_nameObject

Final nested property name e.g. property name expression “address.state” gives :state



48
49
50
# File 'lib/command_handlers/models/model_binding.rb', line 48

def nested_property_name
  nested_property_names.last
end

#nested_property_namesObject

All nested property names e.g. property name expression “address.state” gives [:address, :state]



43
44
45
# File 'lib/command_handlers/models/model_binding.rb', line 43

def nested_property_names
  property_name_expression.split(".")
end

#nested_property_observers_for(observer) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/command_handlers/models/model_binding.rb', line 62

def nested_property_observers_for(observer)
  @nested_property_observers_collection ||= {}
  unless @nested_property_observers_collection.has_key?(observer)
    @nested_property_observers_collection[observer] = nested_property_names.reduce({}) do |output, property_name|
      output.merge(
        property_name => BlockObserver.new do |changed_value|
          # Ensure reattaching observers when a higher level nested property is updated (e.g. person.address changes reattaches person.address.street observer)
          add_observer(observer)
          observer.update(evaluate_property)
        end
      )
    end
  end
  @nested_property_observers_collection[observer]
end

#options_property_nameObject



99
100
101
# File 'lib/command_handlers/models/model_binding.rb', line 99

def options_property_name
  self.property_name + "_options"
end

#property_nameObject



38
39
40
# File 'lib/command_handlers/models/model_binding.rb', line 38

def property_name
  nested_property? ? nested_property_name : property_name_expression
end

#property_name_expressionObject



59
60
61
# File 'lib/command_handlers/models/model_binding.rb', line 59

def property_name_expression
  @property_name_expression
end

#update(value) ⇒ Object



89
90
91
92
# File 'lib/command_handlers/models/model_binding.rb', line 89

def update(value)
  converted_value = @@property_type_converters[@property_type].call(value)
  model.send(property_name + "=", converted_value) unless evaluate_property == converted_value
end