lib/active_data/model/attributable.rb in active_data-0.0.1 vs lib/active_data/model/attributable.rb in active_data-0.1.0
- old
+ new
@@ -1,63 +1,46 @@
-require 'active_data/model/serializable'
-
module ActiveData
module Model
module Attributable
- include Serializable
extend ActiveSupport::Concern
included do
class_attribute :_attributes, :instance_reader => false, :instance_writer => false
self._attributes = ActiveSupport::HashWithIndifferentAccess.new
+ extend generated_class_attributes_methods
+ include generated_instance_attributes_methods
+
delegate :attribute_default, :to => 'self.class'
end
module ClassMethods
- def attribute name, options = {}, &block
- default = options.is_a?(Hash) ? options[:default] : options
- type = options.is_a?(Hash) ? normalize_type(options[:type]) : String
- self._attributes = self._attributes.merge(name => {
- default: (block || default),
- type: type
- })
-
- define_method name do
- read_attribute(name)
+ def build_attribute name, options = {}, &block
+ klass = case options[:type].to_s
+ when 'Localized'
+ ActiveData::Attributes::Localized
+ else
+ ActiveData::Attributes::Base
end
- define_method "#{name}_before_type_cast" do
- read_attribute_before_type_cast(name)
- end
- define_method "#{name}?" do
- read_attribute(name).present?
- end
- define_method "#{name}=" do |value|
- write_attribute(name, value)
- end
+ klass.new name, options, &block
+ end
- if options.is_a?(Hash) && options[:in]
- define_singleton_method "#{name}_values" do
- options[:in].dup
- end
- end
+ def attribute name, options = {}, &block
+ attribute = build_attribute(name, options, &block)
+ self._attributes = _attributes.merge(attribute.name => attribute)
+
+ attribute.generate_instance_methods generated_instance_attributes_methods
+ attribute.generate_singleton_methods generated_class_attributes_methods
+ attribute
end
- def normalize_type type
- case type
- when String, Symbol then
- type.to_s.camelize.safe_constantize
- when nil then
- String
- else
- type
- end
+ def generated_class_attributes_methods
+ @generated_class_attributes_methods ||= Module.new
end
- def attribute_default name
- default = _attributes[name][:default]
- default.respond_to?(:call) ? default.call : default
+ def generated_instance_attributes_methods
+ @generated_instance_attributes_methods ||= Module.new
end
def initialize_attributes
_attributes.inject(ActiveSupport::HashWithIndifferentAccess.new) do |result, (name, value)|
result[name] = nil
@@ -65,21 +48,26 @@
end
end
end
def read_attribute name
- @attributes[name].nil? ? attribute_default(name) : @attributes[name]
+ attribute = self.class._attributes[name]
+ source = @attributes[name].nil? ? attribute.default_value(self) : @attributes[name]
+ attribute.type_cast source
end
alias_method :[], :read_attribute
+ def has_attribute? name
+ @attributes.key? name
+ end
+
def read_attribute_before_type_cast name
- deserialize(send(name))
+ @attributes[name]
end
def write_attribute name, value
- type = self.class._attributes[name][:type]
- @attributes[name] = serialize(value, type)
+ @attributes[name] = value
end
alias_method :[]=, :write_attribute
def attributes
Hash[attribute_names.map { |name| [name, send(name)] }]
@@ -102,14 +90,25 @@
def update_attributes attributes
self.attributes = attributes
end
+ def reverse_update_attributes attributes
+ reverse_assign_attributes(attributes)
+ end
+
private
def assign_attributes attributes
(attributes.presence || {}).each do |(name, value)|
send("#{name}=", value) if respond_to?("#{name}=")
+ end
+ self.attributes
+ end
+
+ def reverse_assign_attributes attributes
+ (attributes.presence || {}).each do |(name, value)|
+ send("#{name}=", value) if respond_to?("#{name}=") && respond_to?(name) && send(name).blank?
end
self.attributes
end
end