lib/acfs/model/attributes.rb in acfs-0.7.0 vs lib/acfs/model/attributes.rb in acfs-0.8.0

- old
+ new

@@ -14,14 +14,15 @@ # For each attribute a setter and getter will be created and values will be # type casted when set. # module Attributes extend ActiveSupport::Concern + include ActiveModel::AttributeMethods def initialize(*attrs) # :nodoc: - self.class.attributes.each { |k, v| public_send :"#{k}=", v } - super *attrs + self.write_attributes self.class.attributes, change: false + super end # Returns ActiveModel compatible list of attributes and values. # # class User @@ -36,15 +37,54 @@ end # Update all attributes with given hash. # def attributes=(attributes) - self.attributes.each do |key, _| - send :"#{key}=", attributes[key] if attributes.has_key? key + write_attributes attributes + end + + # Read an attribute. + # + def read_attribute(name) + instance_variable_get :"@#{name}" + end + + # Write a hash of attributes and values. + # + def write_attributes(attributes, opts = {}) + procs = {} + + attributes.each do |key, _| + if attributes[key].is_a? Proc + procs[key] = attributes[key] + else + write_attribute key, attributes[key], opts + end end + + procs.each do |key, proc| + write_attribute key, instance_exec(&proc), opts + end end + # Write an attribute. + # + def write_attribute(name, value, opts = {}) + if (type = self.class.attribute_types[name.to_sym]).nil? + raise "Unknown attribute #{name}." + end + + write_raw_attribute name, value.nil? ? nil : type.cast(value), opts + end + + # Write an attribute without checking type and existence or casting + # value to attributes type. + # + def write_raw_attribute(name, value, _ = {}) + instance_variable_set :"@#{name}", value + end + module ClassMethods # :nodoc: # Define a model attribute by name and type. Will create getter and # setter for given attribute name. Existing methods will be overridden. # @@ -74,20 +114,29 @@ # def attributes @attributes ||= {} end + # Return hash of attributes and there types. + # + def attribute_types + @attribute_types ||= {} + end + private def define_attribute(name, type, opts = {}) # :nodoc: - @attributes ||= {} - @attributes[name] = type.cast opts.has_key?(:default) ? opts[:default] : nil + default_value = opts.has_key?(:default) ? opts[:default] : nil + default_value = type.cast default_value unless default_value.is_a? Proc or default_value.nil? + attributes[name] = default_value + attribute_types[name.to_sym] = type + define_attribute_method name self.send :define_method, name do - instance_variable_get :"@#{name}" + read_attribute name end self.send :define_method, :"#{name}=" do |value| - instance_variable_set :"@#{name}", type.cast(value) + write_attribute name, value end end end end end