diff options
author | Vijay Dev <vijaydev.cse@gmail.com> | 2012-07-21 21:50:14 +0530 |
---|---|---|
committer | Vijay Dev <vijaydev.cse@gmail.com> | 2012-07-21 21:50:14 +0530 |
commit | dad5446a6c6341f4e3f820c5cdde96db9cea0f7c (patch) | |
tree | 783c5506cd62701180838e1e6792b35397b50062 /activerecord/lib/active_record | |
parent | db4fdb58effa7a31afc29da7a7d7fc1e1ddeff0e (diff) | |
parent | 8fe5f01c31c489548f1648b1c3269c2d1cb5e178 (diff) | |
download | rails-dad5446a6c6341f4e3f820c5cdde96db9cea0f7c.tar.gz rails-dad5446a6c6341f4e3f820c5cdde96db9cea0f7c.tar.bz2 rails-dad5446a6c6341f4e3f820c5cdde96db9cea0f7c.zip |
Merge branch 'master' of github.com:lifo/docrails
Diffstat (limited to 'activerecord/lib/active_record')
7 files changed, 108 insertions, 27 deletions
diff --git a/activerecord/lib/active_record/null_relation.rb b/activerecord/lib/active_record/null_relation.rb index aca8291d75..4c1c91e3df 100644 --- a/activerecord/lib/active_record/null_relation.rb +++ b/activerecord/lib/active_record/null_relation.rb @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- module ActiveRecord - # = Active Record Null Relation - module NullRelation + module NullRelation # :nodoc: def exec_queries @records = [] end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index dd1f77e925..3821c6122a 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -75,6 +75,18 @@ module ActiveRecord binds) end + # Initializes new record from relation while maintaining the current + # scope. + # + # Expects arguments in the same format as +Base.new+. + # + # users = User.where(name: 'DHH') + # user = users.new # => #<User id: nil, name: "DHH", created_at: nil, updated_at: nil> + # + # You can also pass a block to new with the new record as argument: + # + # user = users.new { |user| user.name = 'Oscar' } + # user.name # => Oscar def new(*args, &block) scoping { @klass.new(*args, &block) } end @@ -87,17 +99,38 @@ module ActiveRecord alias build new + # Tries to create a new record with the same scoped attributes + # defined in the relation. Returns the initialized object if validation fails. + # + # Expects arguments in the same format as +Base.create+. + # + # ==== Examples + # users = User.where(name: 'Oscar') + # users.create # #<User id: 3, name: "oscar", ...> + # + # users.create(name: 'fxn') + # users.create # #<User id: 4, name: "fxn", ...> + # + # users.create { |user| user.name = 'tenderlove' } + # # #<User id: 5, name: "tenderlove", ...> + # + # users.create(name: nil) # validation on name + # # #<User id: nil, name: nil, ...> def create(*args, &block) scoping { @klass.create(*args, &block) } end + # Similar to #create, but calls +create!+ on the base class. Raises + # an exception if a validation error occurs. + # + # Expects arguments in the same format as <tt>Base.create!</tt>. def create!(*args, &block) scoping { @klass.create!(*args, &block) } end # Tries to load the first record; if it fails, then <tt>create</tt> is called with the same arguments as this method. # - # Expects arguments in the same format as <tt>Base.create</tt>. + # Expects arguments in the same format as +Base.create+. # # ==== Examples # # Find the first user named Penélope or create a new one. @@ -145,12 +178,13 @@ module ActiveRecord # are needed by the next ones when eager loading is going on. # # Please see further details in the - # {Active Record Query Interface guide}[http://edgeguides.rubyonrails.org/active_record_querying.html#running-explain]. + # {Active Record Query Interface guide}[http://guides.rubyonrails.org/active_record_querying.html#running-explain]. def explain _, queries = collecting_queries_for_explain { exec_queries } exec_explain(queries) end + # Converts relation objects to Array. def to_a # We monitor here the entire execution rather than individual SELECTs # because from the point of view of the user fetching the records of a @@ -209,6 +243,7 @@ module ActiveRecord c.respond_to?(:zero?) ? c.zero? : c.empty? end + # Returns true if there are any records. def any? if block_given? to_a.any? { |*block_args| yield(*block_args) } @@ -217,6 +252,7 @@ module ActiveRecord end end + # Returns true if there is more than one record. def many? if block_given? to_a.many? { |*block_args| yield(*block_args) } @@ -227,8 +263,6 @@ module ActiveRecord # Scope all queries to the current scope. # - # ==== Example - # # Comment.where(:post_id => 1).scoping do # Comment.first # SELECT * FROM comments WHERE post_id = 1 # end @@ -250,17 +284,14 @@ module ActiveRecord # ==== Parameters # # * +updates+ - A string, array, or hash representing the SET part of an SQL statement. - # * +conditions+ - A string, array, or hash representing the WHERE part of an SQL statement. - # See conditions in the intro. - # * +options+ - Additional options are <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage. # # ==== Examples # # # Update all customers with the given attributes - # Customer.update_all :wants_email => true + # Customer.update_all wants_email: true # # # Update all books with 'Rails' in their title - # Book.where('title LIKE ?', '%Rails%').update_all(:author => 'David') + # Book.where('title LIKE ?', '%Rails%').update_all(author: 'David') # # # Update all books that match conditions, but limit it to 5 ordered by date # Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(:author => 'David') @@ -293,7 +324,7 @@ module ActiveRecord # ==== Examples # # # Updates one record - # Person.update(15, :user_name => 'Samuel', :group => 'expert') + # Person.update(15, user_name: 'Samuel', group: 'expert') # # # Updates multiple records # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } } @@ -333,7 +364,7 @@ module ActiveRecord # ==== Examples # # Person.destroy_all("last_login < '2004-04-04'") - # Person.destroy_all(:status => "inactive") + # Person.destroy_all(status: "inactive") # Person.where(:age => 0..18).destroy_all def destroy_all(conditions = nil) if conditions @@ -435,6 +466,7 @@ module ActiveRecord where(primary_key => id_or_array).delete_all end + # Forces reloading of relation. def reload reset to_a # force reload @@ -448,10 +480,18 @@ module ActiveRecord self end + # Returns sql statement for the relation. + # + # Users.where(name: 'Oscar').to_sql + # # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar' def to_sql @to_sql ||= klass.connection.to_sql(arel, bind_values.dup) end + # Returns a hash of where conditions + # + # Users.where(name: 'Oscar').where_values_hash + # # => {:name=>"oscar"} def where_values_hash equalities = with_default_scope.where_values.grep(Arel::Nodes::Equality).find_all { |node| node.left.relation.name == table_name @@ -469,6 +509,7 @@ module ActiveRecord @scope_for_create ||= where_values_hash.merge(create_with_value) end + # Returns true if relation needs eager loading. def eager_loading? @should_eager_load ||= eager_load_values.any? || @@ -483,6 +524,7 @@ module ActiveRecord includes_values & joins_values end + # Compares two relations for equality. def ==(other) case other when Relation @@ -506,6 +548,7 @@ module ActiveRecord end end + # Returns true if relation is blank. def blank? to_a.blank? end diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index fb4388d4b2..5b78b246ab 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -9,8 +9,8 @@ module ActiveRecord # In that case, batch processing methods allow you to work # with the records in batches, thereby greatly reducing memory consumption. # - # The <tt>find_each</tt> method uses <tt>find_in_batches</tt> with a batch size of 1000 (or as - # specified by the <tt>:batch_size</tt> option). + # The #find_each method uses #find_in_batches with a batch size of 1000 (or as + # specified by the +:batch_size+ option). # # Person.all.find_each do |person| # person.do_awesome_stuff @@ -20,7 +20,7 @@ module ActiveRecord # person.party_all_night! # end # - # You can also pass the <tt>:start</tt> option to specify + # You can also pass the +:start+ option to specify # an offset to control the starting point. def find_each(options = {}) find_in_batches(options) do |records| @@ -29,14 +29,14 @@ module ActiveRecord end # Yields each batch of records that was found by the find +options+ as - # an array. The size of each batch is set by the <tt>:batch_size</tt> + # an array. The size of each batch is set by the +:batch_size+ # option; the default is 1000. # # You can control the starting point for the batch processing by - # supplying the <tt>:start</tt> option. This is especially useful if you + # supplying the +:start+ option. This is especially useful if you # want multiple workers dealing with the same processing queue. You can # make worker 1 handle all the records between id 0 and 10,000 and - # worker 2 handle from 10,000 and beyond (by setting the <tt>:start</tt> + # worker 2 handle from 10,000 and beyond (by setting the +:start+ # option on that worker). # # It's not possible to set the order. That is automatically set to diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index 64dda4f35a..a1c7e5b549 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -1,7 +1,7 @@ require 'active_support/core_ext/module/delegation' module ActiveRecord - module Delegation + module Delegation # :nodoc: # Set up common delegations for performance (avoids method_missing) delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index 36f98c6480..b04dd7c6a7 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/hash/keys' module ActiveRecord class Relation - class HashMerger + class HashMerger # :nodoc: attr_reader :relation, :hash def initialize(relation, hash) @@ -28,7 +28,7 @@ module ActiveRecord end end - class Merger + class Merger # :nodoc: attr_reader :relation, :values def initialize(relation, other) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 1271b74ead..9df63d5485 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -35,7 +35,7 @@ module ActiveRecord CODE end - def create_with_value + def create_with_value # :nodoc: @values[:create_with] || {} end @@ -67,6 +67,7 @@ module ActiveRecord args.empty? ? self : spawn.includes!(*args) end + # Like #includes, but modifies the relation in place. def includes!(*args) args.reject! {|a| a.blank? } @@ -84,6 +85,7 @@ module ActiveRecord args.blank? ? self : spawn.eager_load!(*args) end + # Like #eager_load, but modifies relation in place. def eager_load!(*args) self.eager_load_values += args self @@ -97,6 +99,7 @@ module ActiveRecord args.blank? ? self : spawn.preload!(*args) end + # Like #preload, but modifies relation in place. def preload!(*args) self.preload_values += args self @@ -114,6 +117,7 @@ module ActiveRecord args.blank? ? self : spawn.references!(*args) end + # Like #references, but modifies relation in place. def references!(*args) args.flatten! @@ -158,6 +162,7 @@ module ActiveRecord end end + # Like #select, but modifies relation in place. def select!(value) self.select_values += Array.wrap(value) self @@ -179,6 +184,7 @@ module ActiveRecord args.blank? ? self : spawn.group!(*args) end + # Like #group, but modifies relation in place. def group!(*args) args.flatten! @@ -200,6 +206,7 @@ module ActiveRecord args.blank? ? self : spawn.order!(*args) end + # Like #order, but modifies relation in place. def order!(*args) args.flatten! @@ -224,6 +231,7 @@ module ActiveRecord args.blank? ? self : spawn.reorder!(*args) end + # Like #reorder, but modifies relation in place. def reorder!(*args) args.flatten! @@ -240,6 +248,7 @@ module ActiveRecord args.compact.blank? ? self : spawn.joins!(*args) end + # Like #joins, but modifies relation in place. def joins!(*args) args.flatten! @@ -367,6 +376,7 @@ module ActiveRecord opts.blank? ? self : spawn.having!(opts, *rest) end + # Like #having, but modifies relation in place. def having!(opts, *rest) references!(PredicateBuilder.references(opts)) if Hash === opts @@ -383,6 +393,7 @@ module ActiveRecord spawn.limit!(value) end + # Like #limit, but modifies relation in place. def limit!(value) self.limit_value = value self @@ -399,6 +410,7 @@ module ActiveRecord spawn.offset!(value) end + # Like #offset, but modifies relation in place. def offset!(value) self.offset_value = value self @@ -410,6 +422,7 @@ module ActiveRecord spawn.lock!(locks) end + # Like #lock, but modifies relation in place. def lock!(locks = true) case locks when String, TrueClass, NilClass @@ -422,11 +435,11 @@ module ActiveRecord end # Returns a chainable relation with zero records, specifically an - # instance of the NullRelation class. + # instance of the <tt>ActiveRecord::NullRelation</tt> class. # - # The returned NullRelation inherits from Relation and implements the - # Null Object pattern so it is an object with defined null behavior: - # it always returns an empty array of records and does not query the database. + # The returned <tt>ActiveRecord::NullRelation</tt> inherits from Relation and implements the + # Null Object pattern. It is an object with defined null behavior and always returns an empty + # array of records without quering the database. # # Any subsequent condition chained to the returned relation will continue # generating an empty relation and will not fire any query to the database. @@ -464,15 +477,34 @@ module ActiveRecord spawn.readonly!(value) end + # Like #readonly, but modifies relation in place. def readonly!(value = true) self.readonly_value = value self end + # Sets attributes to be used when creating new records from a + # relation object. + # + # users = User.where(name: 'Oscar') + # users.new.name # => 'Oscar' + # + # users = users.create_with(name: 'DHH') + # users.new.name # => 'DHH' + # + # You can pass +nil+ to +create_with+ to reset attributes: + # + # users = users.create_with(nil) + # users.new.name # => 'Oscar' def create_with(value) spawn.create_with!(value) end + # Like #create_with but modifies the relation in place. Raises + # +ImmutableRelation+ if the relation has already been loaded. + # + # users = User.scoped.create_with!(name: 'Oscar') + # users.new.name # => 'Oscar' def create_with!(value) self.create_with_value = value ? create_with_value.merge(value) : {} self @@ -495,6 +527,7 @@ module ActiveRecord spawn.from!(value, subquery_name) end + # Like #from, but modifies relation in place. def from!(value, subquery_name = nil) self.from_value = [value, subquery_name] self @@ -514,6 +547,7 @@ module ActiveRecord spawn.uniq!(value) end + # Like #uniq, but modifies relation in place. def uniq!(value = true) self.uniq_value = value self @@ -563,6 +597,7 @@ module ActiveRecord end end + # Like #extending, but modifies relation in place. def extending!(*modules, &block) modules << Module.new(&block) if block_given? @@ -579,15 +614,18 @@ module ActiveRecord spawn.reverse_order! end + # Like #reverse_order, but modifies relation in place. def reverse_order! self.reverse_order_value = !reverse_order_value self end + # Returns the Arel object associated with the relation. def arel @arel ||= with_default_scope.build_arel end + # Like #arel, but ignores the default scope of the model. def build_arel arel = Arel::SelectManager.new(table.engine, table) diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 80d087a9ea..d21f02cd5f 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -34,6 +34,7 @@ module ActiveRecord end end + # Like #merge, but applies changes in place. def merge!(other) klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger klass.new(self, other).merge |