lib/active_model/attribute_methods.rb in activemodel-3.0.0.beta vs lib/active_model/attribute_methods.rb in activemodel-3.0.0.beta2
- old
+ new
@@ -19,11 +19,10 @@
# * Define the various generic +_attribute+ methods that you have declared
#
# A minimal implementation could be:
#
# class Person
- #
# include ActiveModel::AttributeMethods
#
# attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
# attribute_method_suffix '_contrived?'
# attribute_method_prefix 'clear_'
@@ -42,17 +41,20 @@
# end
#
# def reset_attribute_to_default!(attr)
# send("#{attr}=", "Default Name")
# end
- #
# end
- #
+ #
+ # Please notice that whenever you include ActiveModel::AtributeMethods in your class,
+ # it requires you to implement a <tt>attributes</tt> methods which returns a hash with
+ # each attribute name in your model as hash key and the attribute value as hash value.
+ # Hash keys must be a string.
+ #
module AttributeMethods
extend ActiveSupport::Concern
- # Declare and check for suffixed attribute methods.
module ClassMethods
# Defines an "attribute" method (like +inheritance_column+ or
# +table_name+). A new (class) method will be created with the
# given name. If a value is specified, the new method will
# return that value (as a string). Otherwise, the given block
@@ -84,18 +86,25 @@
# # => "sysid"
# AttributePerson.inheritance_column = 'address'
# AttributePerson.inheritance_column
# # => 'address_id'
def define_attr_method(name, value=nil, &block)
- sing = metaclass
- sing.send :alias_method, "original_#{name}", name
+ sing = singleton_class
+ sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
+ if method_defined?(:original_#{name})
+ undef :original_#{name}
+ end
+ alias_method :original_#{name}, :#{name}
+ eorb
if block_given?
sing.send :define_method, name, &block
else
# use eval instead of a block to work around a memory leak in dev
# mode in fcgi
- sing.class_eval "def #{name}; #{value.to_s.inspect}; end"
+ sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
+ def #{name}; #{value.to_s.inspect}; end
+ eorb
end
end
# Declares a method available for all attributes with the given prefix.
# Uses +method_missing+ and <tt>respond_to?</tt> to rewrite the method.
@@ -252,12 +261,17 @@
generate_method = "define_method_#{matcher.prefix}attribute#{matcher.suffix}"
if respond_to?(generate_method)
send(generate_method, attr_name)
else
+ method_name = matcher.method_name(attr_name)
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__+1
- def #{matcher.method_name(attr_name)}(*args)
+ if method_defined?(:#{method_name})
+ undef :#{method_name}
+ end
+ def #{method_name}(*args)
send(:#{matcher.method_missing_target}, '#{attr_name}', *args)
end
STR
end
end
@@ -281,9 +295,10 @@
include mod
mod
end
end
+ # Returns true if the attribute methods defined have been generated.
def attribute_methods_generated?
@attribute_methods_generated ||= nil
end
protected