未验证 提交 86335671 编写于 作者: R Rafael Mendonça França

Merge pull request #31179 from kinnrot/scoping-reserved-names

Scoping reserved names
* Don't allow scopes to be defined which conflict with instance methods on `Relation`.
Fixes #31120.
*kinnrot*
## Rails 5.2.0.beta2 (November 28, 2017) ##
* No changes.
......
......@@ -221,6 +221,8 @@ def _enum_methods_module
def detect_enum_conflict!(enum_name, method_name, klass_method = false)
if klass_method && dangerous_class_method?(method_name)
raise_conflict_error(enum_name, method_name, type: "class")
elsif klass_method && method_defined_within?(method_name, Relation)
raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
elsif !klass_method && dangerous_attribute_method?(method_name)
raise_conflict_error(enum_name, method_name)
elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
......
......@@ -171,6 +171,12 @@ def scope(name, body, &block)
"a class method with the same name."
end
if method_defined_within?(name, Relation)
raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
"on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
"an instance method with the same name."
end
valid_scope_name?(name)
extension = Module.new(&block) if block
......
......@@ -308,6 +308,24 @@ class EnumTest < ActiveRecord::TestCase
end
end
test "reserved enum values for relation" do
relation_method_samples = [
:records,
:to_ary,
:scope_for_create
]
relation_method_samples.each do |value|
e = assert_raises(ArgumentError, "enum value `#{value}` should not be allowed") do
Class.new(ActiveRecord::Base) do
self.table_name = "books"
enum category: [:other, value]
end
end
assert_match(/You tried to define an enum named .* on the model/, e.message)
end
end
test "overriding enum method should not raise" do
assert_nothing_raised do
Class.new(ActiveRecord::Base) do
......
......@@ -151,6 +151,22 @@ def test_scopes_body_is_a_callable
assert_equal "The scope body needs to be callable.", e.message
end
def test_scopes_name_is_relation_method
conflicts = [
:records,
:to_ary,
:to_sql,
:explain
]
conflicts.each do |name|
e = assert_raises ArgumentError do
Class.new(Post).class_eval { scope name, -> { where(approved: true) } }
end
assert_match(/You tried to define a scope named \"#{name}\" on the model/, e.message)
end
end
def test_active_records_have_scope_named__all__
assert !Topic.all.empty?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册