lib/glimmer/data_binding/model_binding.rb in glimmer-0.5.2 vs lib/glimmer/data_binding/model_binding.rb in glimmer-0.5.3

- old
+ new

@@ -5,27 +5,19 @@ module DataBinding class ModelBinding include Observable include Observer - attr_reader :property_type, :binding_options + attr_reader :binding_options - PROPERTY_TYPE_CONVERTERS = { - :undefined => lambda { |value| value }, - :fixnum => lambda { |value| value.to_i }, - :array => lambda { |value| value.to_a } - } - - def initialize(base_model, property_name_expression, property_type = :undefined, binding_options = nil) - property_type = :undefined if property_type.nil? + def initialize(base_model, property_name_expression, binding_options = nil) @base_model = base_model @property_name_expression = property_name_expression - @property_type = property_type @binding_options = binding_options || {} if computed? @computed_model_bindings = computed_by.map do |computed_by_property_expression| - self.class.new(base_model, computed_by_property_expression, :undefined, computed_binding_options) + self.class.new(base_model, computed_by_property_expression) end end end def model @@ -57,10 +49,34 @@ def property_name nested_property? ? nested_property_name : property_name_expression end + def convert_on_read(value) + apply_converter(@binding_options[:on_read], value) + end + + def convert_on_write(value) + apply_converter(@binding_options[:on_write], value) + end + + def apply_converter(converter, value) + if converter.nil? + value + elsif converter.is_a?(String) || converter.is_a?(Symbol) + if value.respond_to?(converter) + value.send(converter) + else + raise Glimmer::Error, "Unsupported bind converter: #{converter.inspect}" + end + elsif converter.respond_to?(:call, value) + converter.call(value) + else + raise Glimmer::Error, "Unsupported bind converter: #{converter.inspect}" + end + end + # All nested property names # e.g. property name expression "address.state" gives ['address', 'state'] # If there are any indexed property names, this returns indexes as properties. # e.g. property name expression "addresses[1].state" gives ['addresses', '[1]', 'state'] def nested_property_names @@ -93,14 +109,10 @@ def computed_by [@binding_options[:computed_by]].flatten.compact end - def computed_binding_options - @binding_options.reject {|k,v| k == :computed_by} - end - 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( @@ -119,11 +131,14 @@ if computed? add_computed_observers(observer) elsif nested_property? add_nested_observers(observer) else - observer_registration = observer.observe(model, property_name) + model_binding_observer = Observer.proc do |new_value| + observer.call(evaluate_property) + end + observer_registration = model_binding_observer.observe(model, property_name) my_registration = observer.registration_for(self) observer.add_dependent(my_registration => observer_registration) end end @@ -181,11 +196,11 @@ end end def call(value) return if model.nil? - converted_value = PROPERTY_TYPE_CONVERTERS[@property_type].call(value) + converted_value = value invoke_property_writer(model, "#{property_name}=", converted_value) unless evaluate_property == converted_value end def evaluate_property invoke_property_reader(model, property_name) unless model.nil? @@ -198,24 +213,27 @@ def options_property_name self.property_name + "_options" end def property_indexed?(property_expression) - property_expression.start_with?('[') + property_expression.to_s.start_with?('[') end def invoke_property_reader(object, property_expression) + value = nil if property_indexed?(property_expression) property_method = '[]' property_argument = property_expression[1...-1] property_argument = property_argument.to_i if property_argument.match(/\d+/) - object.send(property_method, property_argument) + value = object.send(property_method, property_argument) else - object.send(property_expression) + value = object.send(property_expression) end + convert_on_read(value) end def invoke_property_writer(object, property_expression, value) + value = convert_on_write(value) if property_indexed?(property_expression) property_method = '[]=' property_argument = property_expression[1...-2] property_argument = property_argument.to_i if property_argument.match(/\d+/) object.send(property_method, property_argument, value)