Permalink
Browse files

Move ActiveModel::AttributeMethods#attribute_methods_generated? to Ac…

…tiveRecord, so it's flexible now

[#6428 state:resolved]

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information...
wildchild authored and josevalim committed Feb 13, 2011
1 parent fd26afc commit 24faddd60c5fd148c8264898aeca2d5f36b25a4b
View
@@ -2,6 +2,8 @@
* Added ActiveModel::SecurePassword to encapsulate dead-simple password usage with BCrypt encryption and salting [DHH]
+* ActiveModel::AttributeMethods allows attributes to be defined on demand [Alexander Uvarov]
+
*Rails 3.0.2 (unreleased)*
@@ -260,38 +260,37 @@ def alias_attribute(new_name, old_name)
# end
# end
def define_attribute_methods(attr_names)
- return if attribute_methods_generated?
- attr_names.each do |attr_name|
- attribute_method_matchers.each do |matcher|
- unless instance_method_already_implemented?(matcher.method_name(attr_name))
- generate_method = "define_method_#{matcher.prefix}attribute#{matcher.suffix}"
+ attr_names.each { |attr_name| define_attribute_method(attr_name) }
+ end
+
+ def define_attribute_method(attr_name)
+ attribute_method_matchers.each do |matcher|
+ unless instance_method_already_implemented?(matcher.method_name(attr_name))
+ 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)
+ 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
- if method_defined?('#{method_name}')
- undef :'#{method_name}'
- end
- define_method('#{method_name}') do |*args|
- send('#{matcher.method_missing_target}', '#{attr_name}', *args)
- end
- STR
- end
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
+ if method_defined?('#{method_name}')
+ undef :'#{method_name}'
+ end
+ define_method('#{method_name}') do |*args|
+ send('#{matcher.method_missing_target}', '#{attr_name}', *args)
+ end
+ STR
end
end
end
- @attribute_methods_generated = true
end
# Removes all the previously dynamically defined methods from the class
def undefine_attribute_methods
generated_attribute_methods.module_eval do
instance_methods.each { |m| undef_method(m) }
end
- @attribute_methods_generated = nil
end
# Returns true if the attribute methods defined have been generated.
@@ -303,11 +302,6 @@ def generated_attribute_methods #:nodoc:
end
end
- # Returns true if the attribute methods defined have been generated.
- def attribute_methods_generated?
- @attribute_methods_generated ||= nil
- end
-
protected
def instance_method_already_implemented?(method_name)
method_defined?(method_name)
@@ -42,18 +42,23 @@ class AttributeMethodsTest < ActiveModel::TestCase
ModelWithAttributes2.send(:attribute_method_matchers)
end
+ test '#define_attribute_method generates attribute method' do
+ ModelWithAttributes.define_attribute_method(:foo)
+
+ assert_respond_to ModelWithAttributes.new, :foo
+ assert_equal "value of foo", ModelWithAttributes.new.foo
+ end
+
test '#define_attribute_methods generates attribute methods' do
ModelWithAttributes.define_attribute_methods([:foo])
- assert ModelWithAttributes.attribute_methods_generated?
assert_respond_to ModelWithAttributes.new, :foo
assert_equal "value of foo", ModelWithAttributes.new.foo
end
test '#define_attribute_methods generates attribute methods with spaces in their names' do
ModelWithAttributesWithSpaces.define_attribute_methods([:'foo bar'])
- assert ModelWithAttributesWithSpaces.attribute_methods_generated?
assert_respond_to ModelWithAttributesWithSpaces.new, :'foo bar'
assert_equal "value of foo bar", ModelWithAttributesWithSpaces.new.send(:'foo bar')
end
@@ -69,7 +74,6 @@ class AttributeMethodsTest < ActiveModel::TestCase
ModelWithAttributes.define_attribute_methods([:foo])
ModelWithAttributes.undefine_attribute_methods
- assert !ModelWithAttributes.attribute_methods_generated?
assert !ModelWithAttributes.new.respond_to?(:foo)
assert_raises(NoMethodError) { ModelWithAttributes.new.foo }
end
@@ -10,7 +10,18 @@ module ClassMethods
# Generates all the attribute related methods for columns in the database
# accessors, mutators and query methods.
def define_attribute_methods
+ return if attribute_methods_generated?
super(column_names)
+ @attribute_methods_generated = true
+ end
+
+ def attribute_methods_generated?
+ @attribute_methods_generated ||= false
+ end
+
+ def undefine_attribute_methods(*args)
+ super
+ @attribute_methods_generated = false
end
# Checks whether the method is defined in the model or any of its subclasses

0 comments on commit 24faddd

Please sign in to comment.