lib/freeform/form/property.rb in freeform-0.0.4 vs lib/freeform/form/property.rb in freeform-1.0.0

- old
+ new

@@ -11,10 +11,14 @@ #------------------------------------------------------------------------ def models @models ||= [] end + def child_models + @child_models ||= [] + end + def declared_model(name, opts={}) @models ||= [] @models << name attr_accessor name end @@ -25,75 +29,111 @@ declared_model(name) end end alias_method :form_models, :declared_models + def child_model(name, opts={}, &block) + @models ||= [] + @models << name + @child_models ||= [] + @child_models << name + attr_accessor name + define_method("initialize_#{name}") do + instance_variable_set("@#{name}", instance_eval(&block)) + end + end + # Properties #------------------------------------------------------------------------ - def ignored_blank_params - @ignored_blank_params ||= [] + def property_mappings + # Take the form of {:property => {:model => model, :field => field, :ignore_blank => false}} + @property_mappings ||= Hash.new end def allow_destroy_on_save # Define _destroy method for marked-for-destruction handling attr_accessor :_destroy - alias_method :marked_for_destruction, :_destroy + define_method(:_destroy=) do |value| + false_values = [nil, 0 , false, "0", "false"] + @_destroy = !(false_values.include?(value)) + end + alias_method :marked_for_destruction?, :_destroy + define_method(:mark_for_destruction) do + @_destroy = true + end end def property(attribute, options={}) - if options[:on] - def_delegator options[:on], attribute - def_delegator options[:on], "#{attribute}=".to_sym - else + @property_mappings ||= Hash.new + model = options[:on] ? options [:on] : :self + field = options[:as] ? options[:as] : attribute.to_sym + ignore_blank = options[:ignore_blank] ? options[:ignore_blank] : false + @property_mappings.merge!({field => {:model => model, :field => attribute.to_sym, :ignore_blank => ignore_blank}}) + + if model == :self attr_accessor attribute + else + define_method("#{field}") do + send("#{model}").send("#{attribute}") + end + + define_method("#{field}=") do |value| + send("#{model}").send("#{attribute}=", value) + end end - @ignored_blank_params ||= [] - @ignored_blank_params << attribute if options[:ignore_blank] end end + attr_accessor :parent_form + + class DateParamsFilter + def call(params) + date_attributes = {} + + params.each do |attribute, value| + if value.is_a?(Hash) + call(value) # TODO: #validate should only handle local form params. + elsif matches = attribute.match(/^(\w+)\(.i\)$/) + date_attribute = matches[1] + date_attributes[date_attribute] = params_to_date( + params.delete("#{date_attribute}(1i)"), + params.delete("#{date_attribute}(2i)"), + params.delete("#{date_attribute}(3i)") + ) + end + end + params.merge!(date_attributes) + end + + private + def params_to_date(year, month, day) + day ||= 1 # FIXME: is that really what we want? test. + begin # TODO: test fails. + return Date.new(year.to_i, month.to_i, day.to_i) + rescue ArgumentError => e + return nil + end + end + end + def assign_params(params) - filter_dates(params) + DateParamsFilter.new.call(params) params.each_pair do |attribute, value| - self.send :"#{attribute}=", value unless ignore?(attribute, value) + assign_attribute(attribute, value) end self end alias_method :assign_attributes, :assign_params alias_method :populate, :assign_params alias_method :fill, :assign_params - - def ignore?(attribute, value) - ignored_if_blank = self.class.ignored_blank_params - return (ignored_if_blank.include?(attribute.to_sym) && value.blank?) + + private + def assign_attribute(attribute, value) + self.send :"#{attribute}=", value unless ignore?(attribute, value) end - private - #TODO: This should be its own model - def filter_dates(params) - date_attributes = {} - params.each do |attribute, value| - if attribute.to_s.include?("(1i)") || attribute.to_s.include?("(2i)") || attribute.to_s.include?("(3i)") - date_attribute = attribute.to_s.gsub(/(\(.*\))/, "") - date_attributes[date_attribute.to_sym] = params_to_date( - params.delete("#{date_attribute}(1i)"), - params.delete("#{date_attribute}(2i)"), - params.delete("#{date_attribute}(3i)") - ) - end - end - params.merge!(date_attributes) + def ignore?(attribute, value) + mapping = self.class.property_mappings[attribute.to_sym] + return (mapping[:ignore_blank] && value.blank?) unless mapping.nil? end - - def params_to_date(year, month, day) - day ||= 1 - begin - return Date.new(year.to_i, month.to_i, day.to_i) - rescue => e - return nil - end - end end - - #Instance Methods - #---------------------------------------------------------------------------- end \ No newline at end of file