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