未验证 提交 a52c6989 编写于 作者: R Ryuta Kamizono 提交者: GitHub

Merge pull request #34122 from kamipo/generate_relation_methods

Generate delegation methods to named scope in the definition time
...@@ -17,6 +17,7 @@ def initialize_relation_delegate_cache ...@@ -17,6 +17,7 @@ def initialize_relation_delegate_cache
delegate = Class.new(klass) { delegate = Class.new(klass) {
include ClassSpecificRelation include ClassSpecificRelation
} }
include_relation_methods(delegate)
mangled_name = klass.name.gsub("::", "_") mangled_name = klass.name.gsub("::", "_")
const_set mangled_name, delegate const_set mangled_name, delegate
private_constant mangled_name private_constant mangled_name
...@@ -29,6 +30,35 @@ def inherited(child_class) ...@@ -29,6 +30,35 @@ def inherited(child_class)
child_class.initialize_relation_delegate_cache child_class.initialize_relation_delegate_cache
super super
end end
protected
def include_relation_methods(delegate)
superclass.include_relation_methods(delegate) unless base_class?
delegate.include generated_relation_methods
end
private
def generated_relation_methods
@generated_relation_methods ||= Module.new.tap do |mod|
mod_name = "GeneratedRelationMethods"
const_set mod_name, mod
private_constant mod_name
end
end
def generate_relation_method(method)
if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
generated_relation_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(*args, &block)
scoping { klass.#{method}(*args, &block) }
end
RUBY
else
generated_relation_methods.send(:define_method, method) do |*args, &block|
scoping { klass.public_send(method, *args, &block) }
end
end
end
end end
extend ActiveSupport::Concern extend ActiveSupport::Concern
......
...@@ -191,6 +191,8 @@ def scope(name, body, &block) ...@@ -191,6 +191,8 @@ def scope(name, body, &block)
scope scope
end end
end end
generate_relation_method(name)
end end
private private
......
...@@ -2433,6 +2433,7 @@ def test_replace_returns_target ...@@ -2433,6 +2433,7 @@ def test_replace_returns_target
def test_collection_association_with_private_kernel_method def test_collection_association_with_private_kernel_method
firm = companies(:first_firm) firm = companies(:first_firm)
assert_equal [accounts(:signals37)], firm.accounts.open assert_equal [accounts(:signals37)], firm.accounts.open
assert_equal [accounts(:signals37)], firm.accounts.available
end end
def test_association_with_or_doesnt_set_inverse_instance_key def test_association_with_or_doesnt_set_inverse_instance_key
......
...@@ -1812,6 +1812,16 @@ def test_relation_join_method ...@@ -1812,6 +1812,16 @@ def test_relation_join_method
assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.join(",") assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.join(",")
end end
def test_relation_with_private_kernel_method
accounts = Account.all
assert_equal [accounts(:signals37)], accounts.open
assert_equal [accounts(:signals37)], accounts.available
sub_accounts = SubAccount.all
assert_equal [accounts(:signals37)], sub_accounts.open
assert_equal [accounts(:signals37)], sub_accounts.available
end
test "#skip_query_cache!" do test "#skip_query_cache!" do
Post.cache do Post.cache do
assert_queries(1) do assert_queries(1) do
......
...@@ -11,9 +11,8 @@ def self.destroyed_account_ids ...@@ -11,9 +11,8 @@ def self.destroyed_account_ids
end end
# Test private kernel method through collection proxy using has_many. # Test private kernel method through collection proxy using has_many.
def self.open scope :open, -> { where("firm_name = ?", "37signals") }
where("firm_name = ?", "37signals") scope :available, -> { open }
end
before_destroy do |account| before_destroy do |account|
if account.firm if account.firm
...@@ -32,3 +31,11 @@ def private_method ...@@ -32,3 +31,11 @@ def private_method
"Sir, yes sir!" "Sir, yes sir!"
end end
end end
class SubAccount < Account
def self.instantiate_instance_of(klass, attributes, column_types = {}, &block)
klass = superclass
super
end
private_class_method :instantiate_instance_of
end
...@@ -297,8 +297,6 @@ class SubConditionalStiPost < ConditionalStiPost ...@@ -297,8 +297,6 @@ class SubConditionalStiPost < ConditionalStiPost
class FakeKlass class FakeKlass
extend ActiveRecord::Delegation::DelegateCache extend ActiveRecord::Delegation::DelegateCache
inherited self
class << self class << self
def connection def connection
Post.connection Post.connection
...@@ -335,5 +333,11 @@ def arel_table ...@@ -335,5 +333,11 @@ def arel_table
def predicate_builder def predicate_builder
Post.predicate_builder Post.predicate_builder
end end
def base_class?
true
end
end end
inherited self
end end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册