@@ -117,6 +117,9 @@ def attribute(*names, default: NOT_SET)
117
117
raise ArgumentError , "Restricted attribute names: #{ invalid_attribute_names . join ( ", " ) } "
118
118
end
119
119
120
+ Delegation . generate ( singleton_class , names , to : :instance , nilable : false , signature : "" )
121
+ Delegation . generate ( singleton_class , names . map { |n | "#{ n } =" } , to : :instance , nilable : false , signature : "value" )
122
+
120
123
ActiveSupport ::CodeGenerator . batch ( generated_attribute_methods , __FILE__ , __LINE__ ) do |owner |
121
124
names . each do |name |
122
125
owner . define_cached_method ( name , namespace : :current_attributes ) do |batch |
@@ -134,9 +137,6 @@ def attribute(*names, default: NOT_SET)
134
137
end
135
138
end
136
139
137
- Delegation . generate ( singleton_class , names , to : :instance , nilable : false , signature : "" )
138
- Delegation . generate ( singleton_class , names . map { |n | "#{ n } =" } , to : :instance , nilable : false , signature : "value" )
139
-
140
140
self . defaults = defaults . merge ( names . index_with { default } )
141
141
end
142
142
@@ -182,6 +182,21 @@ def method_missing(name, ...)
182
182
def respond_to_missing? ( name , _ )
183
183
instance . respond_to? ( name ) || super
184
184
end
185
+
186
+ def method_added ( name )
187
+ super
188
+
189
+ # We try to generate instance delegators early to not rely on method_missing.
190
+ return if name == :initialize
191
+
192
+ # If the added method isn't public, we don't delegate it.
193
+ return unless public_method_defined? ( name )
194
+
195
+ # If we already have a class method by that name, we don't override it.
196
+ return if singleton_class . method_defined? ( name ) || singleton_class . private_method_defined? ( name )
197
+
198
+ Delegation . generate ( singleton_class , [ name ] , to : :instance , as : self , nilable : false )
199
+ end
185
200
end
186
201
187
202
class_attribute :defaults , instance_writer : false , default : { } . freeze
0 commit comments