未验证 提交 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
delegate = Class.new(klass) {
include ClassSpecificRelation
}
include_relation_methods(delegate)
mangled_name = klass.name.gsub("::", "_")
const_set mangled_name, delegate
private_constant mangled_name
......@@ -29,6 +30,35 @@ def inherited(child_class)
child_class.initialize_relation_delegate_cache
super
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
extend ActiveSupport::Concern
......
......@@ -191,6 +191,8 @@ def scope(name, body, &block)
scope
end
end
generate_relation_method(name)
end
private
......
......@@ -2433,6 +2433,7 @@ def test_replace_returns_target
def test_collection_association_with_private_kernel_method
firm = companies(:first_firm)
assert_equal [accounts(:signals37)], firm.accounts.open
assert_equal [accounts(:signals37)], firm.accounts.available
end
def test_association_with_or_doesnt_set_inverse_instance_key
......
......@@ -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(",")
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
Post.cache do
assert_queries(1) do
......
......@@ -11,9 +11,8 @@ def self.destroyed_account_ids
end
# Test private kernel method through collection proxy using has_many.
def self.open
where("firm_name = ?", "37signals")
end
scope :open, -> { where("firm_name = ?", "37signals") }
scope :available, -> { open }
before_destroy do |account|
if account.firm
......@@ -32,3 +31,11 @@ def private_method
"Sir, yes sir!"
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
class FakeKlass
extend ActiveRecord::Delegation::DelegateCache
inherited self
class << self
def connection
Post.connection
......@@ -335,5 +333,11 @@ def arel_table
def predicate_builder
Post.predicate_builder
end
def base_class?
true
end
end
inherited self
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册