@@ -17,53 +17,66 @@ def validate_each(record, attribute, value)
17
17
private
18
18
19
19
def setup! ( klass )
20
- klass . include ( LazilyDefineAttributes . new ( AttributeDefinition . new ( attributes ) ) )
20
+ klass . include ( LazilyDefineAttributes . new ( klass ) ) unless klass . ancestors . any? ( LazilyDefineAttributes )
21
21
end
22
22
23
23
def acceptable_option? ( value )
24
24
Array ( options [ :accept ] ) . include? ( value )
25
25
end
26
26
27
27
class LazilyDefineAttributes < Module
28
- def initialize ( attribute_definition )
28
+ attr_reader :removed
29
+
30
+ def initialize ( klass )
31
+ @klass = klass
32
+ @removed = false
33
+ mod = self
34
+
29
35
define_method ( :respond_to_missing? ) do |method_name , include_private = false |
30
- super ( method_name , include_private ) || attribute_definition . matches? ( method_name )
36
+ mod . define_attributes
37
+ super ( method_name , include_private ) || mod . matches? ( method_name )
31
38
end
32
39
33
40
define_method ( :method_missing ) do |method_name , *args , &block |
34
- if attribute_definition . matches? ( method_name )
35
- attribute_definition . define_on ( self . class )
41
+ mod . define_attributes
42
+ if mod . matches? ( method_name )
36
43
send ( method_name , *args , &block )
37
44
else
38
45
super ( method_name , *args , &block )
39
46
end
40
47
end
41
48
end
42
- end
43
-
44
- class AttributeDefinition
45
- def initialize ( attributes )
46
- @attributes = attributes . map ( &:to_s )
47
- end
48
49
49
50
def matches? ( method_name )
50
- attr_name = convert_to_reader_name ( method_name )
51
- attributes . include? ( attr_name )
51
+ attr_name = method_name . to_s . chomp ( "=" )
52
+ attributes . any? { | name | name . to_s == attr_name }
52
53
end
53
54
54
- def define_on ( klass )
55
+ def define_attributes
55
56
attr_readers = attributes . reject { |name | klass . attribute_method? ( name ) }
56
57
attr_writers = attributes . reject { |name | klass . attribute_method? ( "#{ name } =" ) }
57
- klass . define_attribute_methods
58
- klass . attr_reader ( *attr_readers )
59
- klass . attr_writer ( *attr_writers )
58
+
59
+ remove_methods
60
+
61
+ attr_reader ( *attr_readers )
62
+ attr_writer ( *attr_writers )
63
+ end
64
+
65
+ def self . ===( other )
66
+ super && !other . removed
60
67
end
61
68
62
69
private
63
- attr_reader :attributes
70
+ attr_reader :klass
71
+
72
+ def attributes
73
+ @attributes ||= klass . validators . grep ( AcceptanceValidator ) . flat_map ( &:attributes ) . uniq
74
+ end
64
75
65
- def convert_to_reader_name ( method_name )
66
- method_name . to_s . chomp ( "=" )
76
+ def remove_methods
77
+ remove_method :respond_to_missing?
78
+ remove_method :method_missing
79
+ @removed = true
67
80
end
68
81
end
69
82
end
0 commit comments