Skip to content

Commit

Permalink
Use bind instead of instance_exec cause it may be causing memory leak…
Browse files Browse the repository at this point in the history
…s. Also, provide a simpler and sane implementation for scoped. [rails#5044 state:resolved]
  • Loading branch information
josevalim committed Jul 4, 2010
1 parent 67e18c5 commit bfbdeea
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions activerecord/lib/active_record/named_scope.rb
Expand Up @@ -8,17 +8,18 @@ module NamedScope
#
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
def self.included(base)
base.class_eval do
extend ClassMethods
named_scope :scoped, lambda { |scope| scope }
end
base.extend ClassMethods
end

module ClassMethods
def scopes
read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
end

def scoped(scope, &block)
Scope.new(self, scope, &block)
end

# Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
# such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.
#
Expand Down Expand Up @@ -84,22 +85,22 @@ def scopes
# assert_equal expected_options, Shirt.colored('red').proxy_options
def named_scope(name, options = {}, &block)
name = name.to_sym

scopes[name] = lambda do |parent_scope, *args|
Scope.new(parent_scope, case options
when Hash
options
when Proc
if self.model_name != parent_scope.model_name
parent_scope.instance_exec(*args, &options)
options.bind(parent_scope).call(*args)
else
options.call(*args)
end
end, &block)
end
(class << self; self end).instance_eval do
define_method name do |*args|
scopes[name].call(self, *args)
end

singleton_class.send :define_method, name do |*args|
scopes[name].call(self, *args)
end
end
end
Expand Down

0 comments on commit bfbdeea

Please sign in to comment.