diff options
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/association.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/counter_cache.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/inheritance.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/batches.rb | 58 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/finder_methods.rb | 49 |
6 files changed, 96 insertions, 31 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index c428522842..ab1eb49286 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -170,8 +170,8 @@ *Olek Janiszewski* -* fixes bug introduced by #3329. Now, when autosaving associations, - deletions happen before inserts and saves. This prevents a 'duplicate +* fixes bug introduced by #3329. Now, when autosaving associations, + deletions happen before inserts and saves. This prevents a 'duplicate unique value' database error that would occur if a record being created had the same value on a unique indexed field as that of a record being destroyed. diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 608a6af16c..ee62298793 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -200,13 +200,14 @@ module ActiveRecord creation_attributes.each { |key, value| record[key] = value } end - # Should be true if there is a foreign key present on the owner which + # Returns true if there is a foreign key present on the owner which # references the target. This is used to determine whether we can load # the target if the owner is currently a new record (and therefore - # without a key). + # without a key). If the owner is a new record then foreign_key must + # be present in order to load target. # # Currently implemented by belongs_to (vanilla and polymorphic) and - # has_one/has_many :through associations which go through a belongs_to + # has_one/has_many :through associations which go through a belongs_to. def foreign_key_present? false end diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 81cca37939..e1faadf1ab 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -50,7 +50,7 @@ module ActiveRecord # ==== Parameters # # * +id+ - The id of the object you wish to update a counter on or an Array of ids. - # * +counters+ - An Array of Hashes containing the names of the fields + # * +counters+ - A Hash containing the names of the fields # to update as keys and the amount to update the field by as values. # # ==== Examples diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 40976bc29e..e826762def 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -5,7 +5,7 @@ module ActiveRecord extend ActiveSupport::Concern included do - # Determine whether to store the full constant name including namespace when using STI + # Determines whether to store the full constant name including namespace when using STI. class_attribute :store_full_sti_class, instance_writer: false self.store_full_sti_class = true end @@ -13,7 +13,7 @@ module ActiveRecord module ClassMethods # Determines if one of the attributes passed in is the inheritance column, # and if the inheritance column is attr accessible, it initializes an - # instance of the given subclass instead of the base class + # instance of the given subclass instead of the base class. def new(*args, &block) if abstract_class? || self == Base raise NotImplementedError, "#{self} is an abstract class and can not be instantiated." @@ -27,7 +27,8 @@ module ActiveRecord super end - # True if this isn't a concrete subclass needing a STI type condition. + # Returns +true+ if this does not need STI type condition. Returns + # +false+ if STI type condition needs to be applied. def descends_from_active_record? if self == Base false diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index b921f2eddb..41291844fc 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -11,7 +11,7 @@ module ActiveRecord # 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.find_each do |person| # person.do_awesome_stuff # end # @@ -19,8 +19,26 @@ module ActiveRecord # person.party_all_night! # end # - # You can also pass the +:start+ option to specify - # an offset to control the starting point. + # ==== Options + # * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000. + # * <tt>:start</tt> - Specifies the starting point for the batch processing. + # 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 +:start+ option on that worker). + # + # # Let's process for a batch of 2000 records, skiping the first 2000 rows + # Person.find_each(start: 2000, batch_size: 2000) do |person| + # person.party_all_night! + # end + # + # NOTE: It's not possible to set the order. That is automatically set to + # ascending on the primary key ("id ASC") to make the batch ordering + # work. This also means that this method only works with integer-based + # primary keys. + # + # NOTE: You can't set the limit either, that's used to control + # the batch sizes. def find_each(options = {}) find_in_batches(options) do |records| records.each { |record| yield record } @@ -28,31 +46,33 @@ 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 +:batch_size+ - # option; the default is 1000. - # - # You can control the starting point for the batch processing by - # 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 +:start+ - # option on that worker). - # - # It's not possible to set the order. That is automatically set to - # ascending on the primary key ("id ASC") to make the batch ordering - # work. This also means that this method only works with integer-based - # primary keys. You can't set the limit either, that's used to control - # the batch sizes. + # an array. # # Person.where("age > 21").find_in_batches do |group| # sleep(50) # Make sure it doesn't get too crowded in there! # group.each { |person| person.party_all_night! } # end # + # ==== Options + # * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000. + # * <tt>:start</tt> - Specifies the starting point for the batch processing. + # 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 +:start+ option on that worker). + # # # Let's process the next 2000 records - # Person.all.find_in_batches(start: 2000, batch_size: 2000) do |group| + # Person.find_in_batches(start: 2000, batch_size: 2000) do |group| # group.each { |person| person.party_all_night! } # end + # + # NOTE: It's not possible to set the order. That is automatically set to + # ascending on the primary key ("id ASC") to make the batch ordering + # work. This also means that this method only works with integer-based + # primary keys. + # + # NOTE: You can't set the limit either, that's used to control + # the batch sizes. def find_in_batches(options = {}) options.assert_valid_keys(:start, :batch_size) diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index cbb2803593..1550d702a6 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -11,9 +11,11 @@ module ActiveRecord # Person.find([1]) # returns an array for the object with ID = 1 # Person.where("administrator = 1").order("created_on DESC").find(1) # - # Note that returned records may not be in the same order as the ids you - # provide since database rows are unordered. Give an explicit <tt>order</tt> - # to ensure the results are sorted. + # <tt>ActiveRecord::RecordNotFound</tt> will be raised if one or more ids are not found. + # + # NOTE: The returned records may not be in the same order as the ids you + # provide since database rows are unordered. You'd need to provide an explicit <tt>order</tt> + # option if you want the results are sorted. # # ==== Find with lock # @@ -28,6 +30,34 @@ module ActiveRecord # person.visits += 1 # person.save! # end + # + # ==== Variations of +find+ + # + # Person.where(name: 'Spartacus', rating: 4) + # # returns a chainable list (which can be empty). + # + # Person.find_by(name: 'Spartacus', rating: 4) + # # returns the first item or nil. + # + # Person.where(name: 'Spartacus', rating: 4).first_or_initialize + # # returns the first item or returns a new instance (requires you call .save to persist against the database). + # + # Person.where(name: 'Spartacus', rating: 4).first_or_create + # # returns the first item or creates it and returns it, available since Rails 3.2.1. + # + # ==== Alternatives for +find+ + # + # Person.where(name: 'Spartacus', rating: 4).exists?(conditions = :none) + # # returns a boolean indicating if any record with the given conditions exist. + # + # Person.where(name: 'Spartacus', rating: 4).select("field1, field2, field3") + # # returns a chainable list of instances with only the mentioned fields. + # + # Person.where(name: 'Spartacus', rating: 4).ids + # # returns an Array of ids, available since Rails 3.2.1. + # + # Person.where(name: 'Spartacus', rating: 4).pluck(:field1, :field2) + # # returns an Array of the required fields, available since Rails 3.1. def find(*args) if block_given? to_a.find { |*block_args| yield(*block_args) } @@ -79,6 +109,19 @@ module ActiveRecord # Person.where(["user_name = :u", { u: user_name }]).first # Person.order("created_on DESC").offset(5).first # Person.first(3) # returns the first three objects fetched by SELECT * FROM people LIMIT 3 + # + # ==== Rails 3 + # + # Person.first # SELECT "people".* FROM "people" LIMIT 1 + # + # NOTE: Rails 3 may not order this query by the primary key and the order + # will depend on the database implementation. In order to ensure that behavior, + # use <tt>User.order(:id).first</tt> instead. + # + # ==== Rails 4 + # + # Person.first # SELECT "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT 1 + # def first(limit = nil) if limit if order_values.empty? && primary_key |