diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2009-12-26 02:53:10 +0530 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2009-12-26 03:06:51 +0530 |
commit | a7fd564ab197a376336ebfa8bceaf14553e7628f (patch) | |
tree | 306cdf377208c311d7f5a245581764f0b64c3c7f /activerecord/lib | |
parent | 8f6da9483b28ec82e4577bf4cbe5209e2c750c84 (diff) | |
download | rails-a7fd564ab197a376336ebfa8bceaf14553e7628f.tar.gz rails-a7fd564ab197a376336ebfa8bceaf14553e7628f.tar.bz2 rails-a7fd564ab197a376336ebfa8bceaf14553e7628f.zip |
Add Model.select/group/order/limit/joins/conditions/preload/eager_load class methods returning a lazy relation.
Examples :
posts = Post.select('id).order('name') # Returns a lazy relation
posts.each {|p| puts p.id } # Fires "select id from posts order by name"
Diffstat (limited to 'activerecord/lib')
-rwxr-xr-x | activerecord/lib/active_record/base.rb | 10 | ||||
-rw-r--r-- | activerecord/lib/active_record/named_scope.rb | 21 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 56 |
3 files changed, 55 insertions, 32 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 321bba466e..03324b7f24 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -13,6 +13,7 @@ require 'active_support/core_ext/hash/indifferent_access' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/string/behavior' require 'active_support/core_ext/object/metaclass' +require 'active_support/core_ext/module/delegation' module ActiveRecord #:nodoc: # Generic Active Record exception class. @@ -650,6 +651,8 @@ module ActiveRecord #:nodoc: end end + delegate :select, :group, :order, :limit, :joins, :conditions, :preload, :eager_load, :to => :arel_table + # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the # same arguments to this method as you can to <tt>find(:first)</tt>. def first(*args) @@ -1514,13 +1517,8 @@ module ActiveRecord #:nodoc: "(#{segments.join(') AND (')})" unless segments.empty? end - def arel_table(table = nil) - table = table_name if table.blank? - if @arel_table.nil? || @arel_table.name != table - @arel_table = Relation.new(self, Arel::Table.new(table)) - end - @arel_table + Relation.new(self, Arel::Table.new(table || table_name)) end private diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 321871104c..38d54fa8ec 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -23,7 +23,26 @@ module ActiveRecord # # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope. def scoped(options = {}, &block) - options.present? ? Scope.new(self, options, &block) : arel_table + if options.present? + Scope.new(self, options, &block) + else + if !scoped?(:find) + relation = arel_table + else + relation = construct_finder_arel + include_associations = scope(:find, :include) + + if include_associations.present? + if references_eager_loaded_tables?(options) + relation.eager_load(include_associations) + else + relation.preload(include_associations) + end + end + end + + relation + end end def scopes diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 5f0eec754f..28f04e5d85 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -4,20 +4,20 @@ module ActiveRecord delegate :length, :collect, :find, :map, :each, :to => :to_a attr_reader :relation, :klass - def initialize(klass, relation) + def initialize(klass, relation, readonly = false, preload = [], eager_load = []) @klass, @relation = klass, relation - @readonly = false - @associations_to_preload = [] - @eager_load_associations = [] + @readonly = readonly + @associations_to_preload = preload + @eager_load_associations = eager_load end - def preload(association) - @associations_to_preload += association + def preload(associations) + @associations_to_preload << associations self end - def eager_load(association) - @eager_load_associations += association + def eager_load(associations) + @eager_load_associations += Array.wrap(associations) self end @@ -45,7 +45,7 @@ module ActiveRecord @klass.find_by_sql(@relation.to_sql) end - @klass.send(:preload_associations, records, @associations_to_preload) unless @associations_to_preload.empty? + @associations_to_preload.each {|associations| @klass.send(:preload_associations, records, associations) } records.each { |record| record.readonly! } if @readonly records @@ -57,27 +57,27 @@ module ActiveRecord end def select(selects) - selects.blank? ? self : Relation.new(@klass, @relation.project(selects)) + selects.blank? ? self : create_new_relation(@relation.project(selects)) end def group(groups) - groups.blank? ? self : Relation.new(@klass, @relation.group(groups)) + groups.blank? ? self : create_new_relation(@relation.group(groups)) end def order(orders) - orders.blank? ? self : Relation.new(@klass, @relation.order(orders)) + orders.blank? ? self : create_new_relation(@relation.order(orders)) end def limit(limits) - limits.blank? ? self : Relation.new(@klass, @relation.take(limits)) + limits.blank? ? self : create_new_relation(@relation.take(limits)) end def offset(offsets) - offsets.blank? ? self : Relation.new(@klass, @relation.skip(offsets)) + offsets.blank? ? self : create_new_relation(@relation.skip(offsets)) end def on(join) - join.blank? ? self : Relation.new(@klass, @relation.on(join)) + join.blank? ? self : create_new_relation(@relation.on(join)) end def joins(join, join_type = nil) @@ -96,7 +96,7 @@ module ActiveRecord else @relation.join(join, join_type) end - Relation.new(@klass, join) + create_new_relation(join) end end @@ -105,7 +105,7 @@ module ActiveRecord self else conditions = @klass.send(:merge_conditions, conditions) if [String, Hash, Array].include?(conditions.class) - Relation.new(@klass, @relation.where(conditions)) + create_new_relation(@relation.where(conditions)) end end @@ -114,14 +114,20 @@ module ActiveRecord end private - def method_missing(method, *args, &block) - if @relation.respond_to?(method) - @relation.send(method, *args, &block) - elsif Array.method_defined?(method) - to_a.send(method, *args, &block) - else - super - end + + def method_missing(method, *args, &block) + if @relation.respond_to?(method) + @relation.send(method, *args, &block) + elsif Array.method_defined?(method) + to_a.send(method, *args, &block) + else + super end + end + + def create_new_relation(relation) + Relation.new(@klass, relation, @readonly, @associations_to_preload, @eager_load_associations) + end + end end |