From dca3de3bc766175f49b56202246d3625c58fd763 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 17 Jan 2010 23:22:11 +0530 Subject: Make relations work as scopes --- activerecord/lib/active_record/named_scope.rb | 26 +++++++++++++++++----- .../lib/active_record/relation/spawn_methods.rb | 10 ++++++--- activerecord/test/models/post.rb | 8 +++---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 5a1cb7e769..30e75534dd 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -106,7 +106,7 @@ module ActiveRecord scopes[name] = lambda do |parent_scope, *args| Scope.new(parent_scope, case options - when Hash + when Hash, Relation options when Proc options.call(*args) @@ -132,13 +132,21 @@ module ActiveRecord delegate :scopes, :with_scope, :scoped_methods, :unscoped, :to => :proxy_scope def initialize(proxy_scope, options, &block) - options ||= {} - [options[:extend]].flatten.each { |extension| extend extension } if options[:extend] extend Module.new(&block) if block_given? + + options ||= {} + if options.is_a?(Hash) + Array.wrap(options[:extend]).each {|extension| extend extension } + @proxy_options = options.except(:extend) + else + @proxy_options = options + end + unless Scope === proxy_scope @current_scoped_methods_when_defined = proxy_scope.send(:current_scoped_methods) end - @proxy_scope, @proxy_options = proxy_scope, options.except(:extend) + + @proxy_scope = proxy_scope end def reload @@ -193,7 +201,13 @@ module ActiveRecord protected def relation - @relation ||= unscoped.apply_finder_options(proxy_options) + @relation ||= begin + if proxy_options.is_a?(Hash) + unscoped.apply_finder_options(proxy_options) + else + unscoped.merge(proxy_options) + end + end end def proxy_found @@ -201,6 +215,7 @@ module ActiveRecord end private + def method_missing(method, *args, &block) if scopes.include?(method) scopes[method].call(self, *args) @@ -221,6 +236,7 @@ module ActiveRecord def load_found @found = find(:all) end + end end end diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 953ea5ea1c..2979f4b82d 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -19,7 +19,10 @@ module ActiveRecord raise ArgumentError, "Cannot merge a #{r.klass.name}(##{r.klass.object_id}) relation with #{@klass.name}(##{@klass.object_id}) relation" end - merged_relation = spawn.eager_load(r.eager_load_values).preload(r.preload_values).includes(r.includes_values) + merged_relation = spawn + return merged_relation unless r + + merged_relation = merged_relation.eager_load(r.eager_load_values).preload(r.preload_values).includes(r.includes_values) merged_relation.readonly_value = r.readonly_value unless r.readonly_value.nil? merged_relation.limit_value = r.limit_value if r.limit_value.present? @@ -94,9 +97,10 @@ module ActiveRecord :order, :select, :readonly, :group, :having, :from, :lock ] def apply_finder_options(options) - options.assert_valid_keys(VALID_FIND_OPTIONS) - relation = spawn + return relation unless options + + options.assert_valid_keys(VALID_FIND_OPTIONS) relation = relation.joins(options[:joins]). where(options[:conditions]). diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 662f75c39f..b5f9328139 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -1,7 +1,7 @@ class Post < ActiveRecord::Base - named_scope :containing_the_letter_a, :conditions => "body LIKE '%a%'" - named_scope :ranked_by_comments, :order => "comments_count DESC" - named_scope :limit_by, lambda {|limit| {:limit => limit} } + named_scope :containing_the_letter_a, where("body LIKE '%a%'") + named_scope :ranked_by_comments, order("comments_count DESC") + named_scope :limit_by, lambda {|l| limit(l) } named_scope :with_authors_at_address, lambda { |address| { :conditions => [ 'authors.author_address_id = ?', address.id ], :joins => 'JOIN authors ON authors.id = posts.author_id' @@ -20,7 +20,7 @@ class Post < ActiveRecord::Base has_one :last_comment, :class_name => 'Comment', :order => 'id desc' named_scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} } - named_scope :with_very_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'VerySpecialComment'} } + named_scope :with_very_special_comments, joins(:comments).where(:comments => {:type => 'VerySpecialComment'}) named_scope :with_post, lambda {|post_id| { :joins => :comments, :conditions => {:comments => {:post_id => post_id} } } } -- cgit v1.2.3