diff options
author | Godfrey Chan <godfreykfc@gmail.com> | 2014-01-24 18:28:05 -0800 |
---|---|---|
committer | Godfrey Chan <godfreykfc@gmail.com> | 2014-01-29 10:54:51 -0800 |
commit | 7e8e91c439c1a877f867cd7ba634f7297ccef04b (patch) | |
tree | 4d800773aa5f59b9293c52b3b46c44d27b3a4d5e /activerecord/test/cases | |
parent | 9ed66648b59b160b43c83c349263e8cb97eaa088 (diff) | |
download | rails-7e8e91c439c1a877f867cd7ba634f7297ccef04b.tar.gz rails-7e8e91c439c1a877f867cd7ba634f7297ccef04b.tar.bz2 rails-7e8e91c439c1a877f867cd7ba634f7297ccef04b.zip |
`scope` now raises on "dangerous" name conflicts
Similar to dangerous attribute methods, a scope name conflict is
dangerous if it conflicts with an existing class method defined within
`ActiveRecord::Base` but not its ancestors.
See also #13389.
*Godfrey Chan*, *Philippe Creux*
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/scoping/named_scoping_test.rb | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb index 086977d9a2..9dc26cfd4d 100644 --- a/activerecord/test/cases/scoping/named_scoping_test.rb +++ b/activerecord/test/cases/scoping/named_scoping_test.rb @@ -266,6 +266,63 @@ class NamedScopingTest < ActiveRecord::TestCase assert_equal 'lifo', topic.author_name end + def test_reserved_scope_names + klass = Class.new(ActiveRecord::Base) do + self.table_name = "topics" + + scope :approved, -> { where(approved: true) } + + class << self + public + def pub; end + + private + def pri; end + + protected + def pro; end + end + end + + subklass = Class.new(klass) + + conflicts = [ + :create, # public class method on AR::Base + :relation, # private class method on AR::Base + :new, # redefined class method on AR::Base + :all, # a default scope + ] + + non_conflicts = [ + :find_by_title, # dynamic finder method + :approved, # existing scope + :pub, # existing public class method + :pri, # existing private class method + :pro, # existing protected class method + :open, # a ::Kernel method + ] + + conflicts.each do |name| + assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do + klass.class_eval { scope name, ->{ where(approved: true) } } + end + + assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do + subklass.class_eval { scope name, ->{ where(approved: true) } } + end + end + + non_conflicts.each do |name| + assert_nothing_raised do + klass.class_eval { scope name, ->{ where(approved: true) } } + end + + assert_nothing_raised do + subklass.class_eval { scope name, ->{ where(approved: true) } } + end + end + end + # Method delegation for scope names which look like /\A[a-zA-Z_]\w*[!?]?\z/ # has been done by evaluating a string with a plain def statement. For scope # names which contain spaces this approach doesn't work. |