Skip to content

Commit a4398e4

Browse files
committed
Merge pull request rails#30919 from seanlinsley/17622-before_save_strict_arguments
Add strict argument checking to ActiveRecord callbacks
2 parents 9732195 + dfb0e4b commit a4398e4

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

activemodel/lib/active_model/callbacks.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,26 +127,28 @@ def define_model_callbacks(*callbacks)
127127
private
128128

129129
def _define_before_model_callback(klass, callback)
130-
klass.define_singleton_method("before_#{callback}") do |*args, &block|
131-
set_callback(:"#{callback}", :before, *args, &block)
130+
klass.define_singleton_method("before_#{callback}") do |*args, **options, &block|
131+
options.assert_valid_keys(:if, :unless, :prepend)
132+
set_callback(:"#{callback}", :before, *args, options, &block)
132133
end
133134
end
134135

135136
def _define_around_model_callback(klass, callback)
136-
klass.define_singleton_method("around_#{callback}") do |*args, &block|
137-
set_callback(:"#{callback}", :around, *args, &block)
137+
klass.define_singleton_method("around_#{callback}") do |*args, **options, &block|
138+
options.assert_valid_keys(:if, :unless, :prepend)
139+
set_callback(:"#{callback}", :around, *args, options, &block)
138140
end
139141
end
140142

141143
def _define_after_model_callback(klass, callback)
142-
klass.define_singleton_method("after_#{callback}") do |*args, &block|
143-
options = args.extract_options!
144+
klass.define_singleton_method("after_#{callback}") do |*args, **options, &block|
145+
options.assert_valid_keys(:if, :unless, :prepend)
144146
options[:prepend] = true
145147
conditional = ActiveSupport::Callbacks::Conditionals::Value.new { |v|
146148
v != false
147149
}
148150
options[:if] = Array(options[:if]) << conditional
149-
set_callback(:"#{callback}", :after, *(args << options), &block)
151+
set_callback(:"#{callback}", :after, *args, options, &block)
150152
end
151153
end
152154
end

activerecord/test/cases/callbacks_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,4 +476,31 @@ def test_inheritance_of_callbacks
476476
child.save
477477
assert child.after_save_called
478478
end
479+
480+
def test_before_save_doesnt_allow_on_option
481+
exception = assert_raises ArgumentError do
482+
Class.new(ActiveRecord::Base) do
483+
before_save(on: :create) {}
484+
end
485+
end
486+
assert_equal "Unknown key: :on. Valid keys are: :if, :unless, :prepend", exception.message
487+
end
488+
489+
def test_around_save_doesnt_allow_on_option
490+
exception = assert_raises ArgumentError do
491+
Class.new(ActiveRecord::Base) do
492+
around_save(on: :create) {}
493+
end
494+
end
495+
assert_equal "Unknown key: :on. Valid keys are: :if, :unless, :prepend", exception.message
496+
end
497+
498+
def test_after_save_doesnt_allow_on_option
499+
exception = assert_raises ArgumentError do
500+
Class.new(ActiveRecord::Base) do
501+
after_save(on: :create) {}
502+
end
503+
end
504+
assert_equal "Unknown key: :on. Valid keys are: :if, :unless, :prepend", exception.message
505+
end
479506
end

0 commit comments

Comments
 (0)