aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
authorGodfrey Chan <godfreykfc@gmail.com>2014-01-24 18:28:05 -0800
committerGodfrey Chan <godfreykfc@gmail.com>2014-01-29 10:54:51 -0800
commit7e8e91c439c1a877f867cd7ba634f7297ccef04b (patch)
tree4d800773aa5f59b9293c52b3b46c44d27b3a4d5e /activerecord/test/cases
parent9ed66648b59b160b43c83c349263e8cb97eaa088 (diff)
downloadrails-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.rb57
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.