aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijay Dev <vijaydev.cse@gmail.com>2012-05-23 23:26:39 +0530
committerVijay Dev <vijaydev.cse@gmail.com>2012-05-23 23:26:39 +0530
commit91305adef8e94c2bbc3b771747dc0fbb00e3a171 (patch)
tree64ee12feaa67a6ee671091e11ca802e978875546
parent9ae0c6678784379de3eab601d9ee39a17955b5e1 (diff)
parent1c94868033c631dcb44d705f70433a64d48e0938 (diff)
downloadrails-91305adef8e94c2bbc3b771747dc0fbb00e3a171.tar.gz
rails-91305adef8e94c2bbc3b771747dc0fbb00e3a171.tar.bz2
rails-91305adef8e94c2bbc3b771747dc0fbb00e3a171.zip
Merge branch 'master' of github.com:lifo/docrails
-rw-r--r--actionpack/lib/abstract_controller/base.rb16
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb2
-rw-r--r--activerecord/lib/active_record/aggregations.rb6
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb489
-rw-r--r--activerecord/lib/active_record/associations/preloader.rb2
-rw-r--r--guides/source/configuring.textile2
-rw-r--r--guides/source/debugging_rails_applications.textile2
-rw-r--r--guides/source/getting_started.textile2
-rw-r--r--guides/source/initialization.textile108
-rw-r--r--railties/lib/rails/generators/actions.rb3
10 files changed, 554 insertions, 78 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index 97a9eec144..9c3960961b 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -51,7 +51,7 @@ module AbstractController
# to specify particular actions as hidden.
#
# ==== Returns
- # * <tt>array</tt> - An array of method names that should not be considered actions.
+ # * <tt>Array</tt> - An array of method names that should not be considered actions.
def hidden_actions
[]
end
@@ -63,7 +63,7 @@ module AbstractController
# itself. Finally, #hidden_actions are removed.
#
# ==== Returns
- # * <tt>set</tt> - A set of all methods that should be considered actions.
+ # * <tt>Set</tt> - A set of all methods that should be considered actions.
def action_methods
@action_methods ||= begin
# All public instance methods of this class, including ancestors
@@ -92,11 +92,12 @@ module AbstractController
# controller_path.
#
# ==== Returns
- # * <tt>string</tt>
+ # * <tt>String</tt>
def controller_path
@controller_path ||= name.sub(/Controller$/, '').underscore unless anonymous?
end
+ # Refresh the cached action_methods when a new action_method is added.
def method_added(name)
super
clear_action_methods!
@@ -130,6 +131,7 @@ module AbstractController
self.class.controller_path
end
+ # Delegates to the class' #action_methods
def action_methods
self.class.action_methods
end
@@ -139,8 +141,14 @@ module AbstractController
#
# Notice that <tt>action_methods.include?("foo")</tt> may return
# false and <tt>available_action?("foo")</tt> returns true because
- # available action consider actions that are also available
+ # this method considers actions that are also available
# through other means, for example, implicit render ones.
+ #
+ # ==== Parameters
+ # * <tt>action_name</tt> - The name of an action to be tested
+ #
+ # ==== Returns
+ # * <tt>TrueClass</tt>, <tt>FalseClass</tt>
def available_action?(action_name)
method_for_action(action_name).present?
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index ad8885b708..ac150882b1 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -342,7 +342,7 @@ module ActionView
# Example:
#
# <%= form_for(@post) do |f| %>
- # <% f.fields_for(:comments, :include_id => false) do |cf| %>
+ # <%= f.fields_for(:comments, :include_id => false) do |cf| %>
# ...
# <% end %>
# <% end %>
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index f0b549e5ad..3ae7030caa 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -10,9 +10,9 @@ module ActiveRecord
# Active Record implements aggregation through a macro-like class method called +composed_of+
# for representing attributes as value objects. It expresses relationships like "Account [is]
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
- # to the macro adds a description of how the value objects are created from the attributes of
- # the entity object (when the entity is initialized either as a new object or from finding an
- # existing object) and how it can be turned back into attributes (when the entity is saved to
+ # to the macro adds a description of how the value objects are created from the attributes of
+ # the entity object (when the entity is initialized either as a new object or from finding an
+ # existing object) and how it can be turned back into attributes (when the entity is saved to
# the database).
#
# class Customer < ActiveRecord::Base
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index fa316a8c9d..100fb38dec 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -37,9 +37,107 @@ module ActiveRecord
delegate :target, :load_target, :loaded?, :to => :@association
##
+ # :method: select
+ #
+ # :call-seq:
+ # select(select = nil)
+ # select(&block)
+ #
+ # Works in two ways.
+ #
+ # *First:* Specify a subset of fields to be selected from the result set.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets
+ # end
+ #
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.select(:name)
+ # # => [
+ # # #<Pet id: nil, name: "Fancy-Fancy">,
+ # # #<Pet id: nil, name: "Spook">,
+ # # #<Pet id: nil, name: "Choo-Choo">
+ # # ]
+ #
+ # person.pets.select([:id, :name])
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy">,
+ # # #<Pet id: 2, name: "Spook">,
+ # # #<Pet id: 3, name: "Choo-Choo">
+ # # ]
+ #
+ # Be careful because this also means you’re initializing a model
+ # object with only the fields that you’ve selected. If you attempt
+ # to access a field that is not in the initialized record you’ll
+ # receive:
+ #
+ # person.pets.select(:name).first.person_id
+ # # => ActiveModel::MissingAttributeError: missing attribute: person_id
+ #
+ # *Second:* You can pass a block so it can be used just like Array#select.
+ # This build an array of objects from the database for the scope,
+ # converting them into an array and iterating through them using
+ # Array#select.
+ #
+ # person.pets.select { |pet| pet.name =~ /oo/ }
+ # # => [
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.select(:name) { |pet| pet.name =~ /oo/ }
+ # # => [
+ # # #<Pet id: 2, name: "Spook">,
+ # # #<Pet id: 3, name: "Choo-Choo">
+ # # ]
+
+ ##
+ # :method: find
+ #
+ # :call-seq:
+ # find(*args, &block)
+ #
+ # Finds an object in the collection responding to the +id+. Uses the same
+ # rules as +ActiveRecord::Base.find+. Returns +ActiveRecord::RecordNotFound++
+ # error if the object can not be found.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets
+ # end
+ #
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+ # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4
+ #
+ # person.pets.find(2) { |pet| pet.name.downcase! }
+ # # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
+ #
+ # person.pets.find(2, 3)
+ # # => [
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+
+ ##
# :method: first
+ #
+ # :call-seq:
+ # first(limit = nil)
+ #
# Returns the first record, or the first +n+ records, from the collection.
- # If the collection is empty, the first form returns nil, and the second
+ # If the collection is empty, the first form returns +nil+, and the second
# form returns an empty array.
#
# class Person < ActiveRecord::Base
@@ -67,8 +165,12 @@ module ActiveRecord
##
# :method: last
+ #
+ # :call-seq:
+ # last(limit = nil)
+ #
# Returns the last record, or the last +n+ records, from the collection.
- # If the collection is empty, the first form returns nil, and the second
+ # If the collection is empty, the first form returns +nil+, and the second
# form returns an empty array.
#
# class Person < ActiveRecord::Base
@@ -95,7 +197,95 @@ module ActiveRecord
# another_person_without.pets.last(3) # => []
##
+ # :method: build
+ #
+ # :call-seq:
+ # build(attributes = {}, options = {}, &block)
+ #
+ # Returns a new object of the collection type that has been instantiated
+ # with +attributes+ and linked to this object, but have not yet been saved.
+ # You can pass an array of attributes hashes, this will return an array
+ # with the new objects.
+ #
+ # class Person
+ # has_many :pets
+ # end
+ #
+ # person.pets.build
+ # # => #<Pet id: nil, name: nil, person_id: 1>
+ #
+ # person.pets.build(name: 'Fancy-Fancy')
+ # # => #<Pet id: nil, name: "Fancy-Fancy", person_id: 1>
+ #
+ # person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}])
+ # # => [
+ # # #<Pet id: nil, name: "Spook", person_id: 1>,
+ # # #<Pet id: nil, name: "Choo-Choo", person_id: 1>,
+ # # #<Pet id: nil, name: "Brain", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 5 # size of the collection
+ # person.pets.count # => 0 # count from database
+
+ ##
+ # :method: create
+ #
+ # :call-seq:
+ # create(attributes = {}, options = {}, &block)
+ #
+ # Returns a new object of the collection type that has been instantiated with
+ # attributes, linked to this object and that has already been saved (if it
+ # passes the validations).
+ #
+ # class Person
+ # has_many :pets
+ # end
+ #
+ # person.pets.create(name: 'Fancy-Fancy')
+ # # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+ #
+ # person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}])
+ # # => [
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 3
+ # person.pets.count # => 3
+ #
+ # person.pets.find(1, 2, 3)
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+
+ ##
+ # :method: create!
+ #
+ # :call-seq:
+ # create!(attributes = {}, options = {}, &block)
+ #
+ # Like +create+, except that if the record is invalid, raises an exception.
+ #
+ # class Person
+ # has_many :pets
+ # end
+ #
+ # class Pet
+ # attr_accessible :name
+ # validates :name, presence: true
+ # end
+ #
+ # person.pets.create!(name: nil)
+ # # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
+
+ ##
# :method: concat
+ #
+ # :call-seq:
+ # concat(*records)
+ #
# Add one or more records to the collection by setting their foreign keys
# to the association's primary key. Since << flattens its argument list and
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
@@ -123,6 +313,10 @@ module ActiveRecord
##
# :method: replace
+ #
+ # :call-seq:
+ # replace(other_array)
+ #
# Replace this collection with +other_array+. This will perform a diff
# and delete/add only records that have changed.
#
@@ -147,23 +341,249 @@ module ActiveRecord
# # => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
##
+ # :method: delete_all
+ #
+ # Deletes all the records from the collection. For +has_many+ asssociations,
+ # the deletion is done according to the strategy specified by the <tt>:dependent</tt>
+ # option. Returns an array with the deleted records.
+ #
+ # If no <tt>:dependent</tt> option is given, then it will follow the
+ # default strategy. The default strategy is <tt>:nullify</tt>. This
+ # sets the foreign keys to <tt>NULL</tt>. For, +has_many+ <tt>:through</tt>,
+ # the default strategy is +delete_all+.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets # dependent: :nullify option by default
+ # end
+ #
+ # person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.delete_all
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 0
+ # person.pets # => []
+ #
+ # Pet.find(1, 2, 3)
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>,
+ # # #<Pet id: 2, name: "Spook", person_id: nil>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
+ # # ]
+ #
+ # If it is set to <tt>:destroy</tt> all the objects from the collection
+ # are removed by calling their +destroy+ method. See +destroy+ for more
+ # information.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets, dependent: :destroy
+ # end
+ #
+ # person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.delete_all
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # Pet.find(1, 2, 3)
+ # # => ActiveRecord::RecordNotFound
+ #
+ # If it is set to <tt>:delete_all</tt>, all the objects are deleted
+ # *without* calling their +destroy+ method.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets, dependent: :delete_all
+ # end
+ #
+ # person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.delete_all
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # Pet.find(1, 2, 3)
+ # # => ActiveRecord::RecordNotFound
+
+ ##
# :method: destroy_all
- # Destroy all the records from this association.
+ #
+ # Deletes the records of the collection directly from the database.
+ # This will _always_ remove the records ignoring the +:dependent+
+ # option.
#
# class Person < ActiveRecord::Base
# has_many :pets
# end
#
# person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
#
# person.pets.destroy_all
#
# person.pets.size # => 0
# person.pets # => []
+ #
+ # Pet.find(1) # => Couldn't find Pet with id=1
+
+ ##
+ # :method: destroy
+ #
+ # :call-seq:
+ # destroy(*records)
+ #
+ # Destroy the +records+ supplied and remove them from the collection.
+ # This method will _always_ remove record from the database ignoring
+ # the +:dependent+ option. Returns an array with the removed records.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets
+ # end
+ #
+ # person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.destroy(Pet.find(1))
+ # # => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
+ #
+ # person.pets.size # => 2
+ # person.pets
+ # # => [
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.destroy(Pet.find(2), Pet.find(3))
+ # # => [
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 0
+ # person.pets # => []
+ #
+ # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 2, 3)
+ #
+ # You can pass +Fixnum+ or +String+ values, it finds the records
+ # responding to the +id+ and then deletes them from the database.
+ #
+ # person.pets.size # => 3
+ # person.pets
+ # # => [
+ # # #<Pet id: 4, name: "Benny", person_id: 1>,
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
+ # # ]
+ #
+ # person.pets.destroy("4")
+ # # => #<Pet id: 4, name: "Benny", person_id: 1>
+ #
+ # person.pets.size # => 2
+ # person.pets
+ # # => [
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
+ # # ]
+ #
+ # person.pets.destroy(5, 6)
+ # # => [
+ # # #<Pet id: 5, name: "Brain", person_id: 1>,
+ # # #<Pet id: 6, name: "Boss", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 0
+ # person.pets # => []
+ #
+ # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6)
+
+ ##
+ # :method: size
+ #
+ # Returns the size of the collection. If the collection hasn't been loaded,
+ # it executes a <tt>SELECT COUNT(*)</tt> query.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets
+ # end
+ #
+ # person.pets.size # => 3
+ # # executes something like SELECT COUNT(*) FROM "pets" WHERE "pets"."person_id" = 1
+ #
+ # person.pets # This will execute a SELECT * FROM query
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
+ #
+ # person.pets.size # => 3
+ # # Because the collection is already loaded, this will behave like
+ # # collection.size and no SQL count query is executed.
+
+ ##
+ # :method: length
+ #
+ # Returns the size of the collection calling +size+ on the target.
+ # If the collection has been already loaded, +length+ and +size+ are
+ # equivalent.
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :pets
+ # end
+ #
+ # person.pets.length # => 3
+ # # executes something like SELECT "pets".* FROM "pets" WHERE "pets"."person_id" = 1
+ #
+ # # Because the collection is loaded, you can
+ # # call the collection with no additional queries:
+ # person.pets
+ # # => [
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+ # # ]
##
# :method: empty?
- # Returns true if the collection is empty.
+ #
+ # Returns +true+ if the collection is empty.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -179,7 +599,12 @@ module ActiveRecord
##
# :method: any?
- # Returns true if the collection is not empty.
+ #
+ # :call-seq:
+ # any?
+ # any?{|item| block}
+ #
+ # Returns +true+ if the collection is not empty.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -211,8 +636,13 @@ module ActiveRecord
##
# :method: many?
+ #
+ # :call-seq:
+ # many?
+ # many?{|item| block}
+ #
# Returns true if the collection has more than one record.
- # Equivalent to +collection.size > 1+.
+ # Equivalent to <tt>collection.size > 1</tt>.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -248,7 +678,11 @@ module ActiveRecord
##
# :method: include?
- # Returns true if the given object is present in the collection.
+ #
+ # :call-seq:
+ # include?(record)
+ #
+ # Returns +true+ if the given object is present in the collection.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -331,37 +765,32 @@ module ActiveRecord
end
alias_method :push, :<<
- # Removes every object from the collection. This does not destroy
- # the objects, it sets their foreign keys to +NULL+. Returns +self+
- # so methods can be chained.
+ # Equivalent to +delete_all+. The difference is that returns +self+, instead
+ # of an array with the deleted objects, so methods can be chained. See
+ # +delete_all+ for more information.
+ def clear
+ delete_all
+ self
+ end
+
+ # Reloads the collection from the database. Returns +self+.
+ # Equivalent to <tt>collection(true)</tt>.
#
# class Person < ActiveRecord::Base
# has_many :pets
# end
#
- # person.pets # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
- # person.pets.clear # => []
- # person.pets.size # => 0
+ # person.pets # fetches pets from the database
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
#
- # Pet.find(1) # => #<Pet id: 1, name: "Snoop", group: "dogs", person_id: nil>
+ # person.pets # uses the pets cache
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
#
- # If they are associated with +dependent: :destroy+ option, it deletes
- # them directly from the database.
+ # person.pets.reload # fetches pets from the database
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
#
- # class Person < ActiveRecord::Base
- # has_many :pets, dependent: :destroy
- # end
- #
- # person.pets # => [#<Pet id: 2, name: "Gorby", group: "cats", person_id: 2>]
- # person.pets.clear # => []
- # person.pets.size # => 0
- #
- # Pet.find(2) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=2
- def clear
- delete_all
- self
- end
-
+ # person.pets(true)  # fetches pets from the database
+ # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
def reload
proxy_association.reload
self
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb
index fafed94ff2..54705e4950 100644
--- a/activerecord/lib/active_record/associations/preloader.rb
+++ b/activerecord/lib/active_record/associations/preloader.rb
@@ -12,7 +12,7 @@ module ActiveRecord
# and all of its books via a single query:
#
# SELECT * FROM authors
- # LEFT OUTER JOIN books ON authors.id = books.id
+ # LEFT OUTER JOIN books ON authors.id = books.author_id
# WHERE authors.name = 'Ken Akamatsu'
#
# However, this could result in many rows that contain redundant data. After
diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile
index f114075cae..af46538bf5 100644
--- a/guides/source/configuring.textile
+++ b/guides/source/configuring.textile
@@ -585,7 +585,7 @@ After loading the framework and any gems in your application, Rails turns to loa
NOTE: You can use subfolders to organize your initializers if you like, because Rails will look into the whole file hierarchy from the initializers folder on down.
-TIP: If you have any ordering dependency in your initializers, you can control the load order by naming. For example, +01_critical.rb+ will be loaded before +02_normal.rb+.
+TIP: If you have any ordering dependency in your initializers, you can control the load order through naming. Initializer files are loaded in alphabetical order by their path. For example, +01_critical.rb+ will be loaded before +02_normal.rb+.
h3. Initialization events
diff --git a/guides/source/debugging_rails_applications.textile b/guides/source/debugging_rails_applications.textile
index 45fa4ada78..0802a2db26 100644
--- a/guides/source/debugging_rails_applications.textile
+++ b/guides/source/debugging_rails_applications.textile
@@ -698,7 +698,7 @@ There are some Rails plugins to help you to find errors and debug your applicati
h3. References
-* "ruby-debug Homepage":http://www.datanoise.com/ruby-debug
+* "ruby-debug Homepage":http://bashdb.sourceforge.net/ruby-debug/home-page.html
* "debugger Homepage":http://github.com/cldwalker/debugger
* "Article: Debugging a Rails application with ruby-debug":http://www.sitepoint.com/article/debug-rails-app-ruby-debug/
* "ruby-debug Basics screencast":http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/
diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile
index e25dac22da..c129aeb2e1 100644
--- a/guides/source/getting_started.textile
+++ b/guides/source/getting_started.textile
@@ -13,8 +13,6 @@ endprologue.
WARNING. This Guide is based on Rails 3.2. Some of the code shown here will not
work in earlier versions of Rails.
-WARNING: The Edge version of this guide is currently being re-worked. Please excuse us while we re-arrange the place.
-
h3. Guide Assumptions
This guide is designed for beginners who want to get started with a Rails
diff --git a/guides/source/initialization.textile b/guides/source/initialization.textile
index 155a439e64..12b2eb7458 100644
--- a/guides/source/initialization.textile
+++ b/guides/source/initialization.textile
@@ -1,13 +1,15 @@
h2. The Rails Initialization Process
-This guide explains the internals of the initialization process in Rails as of Rails 3.1. It is an extremely in-depth guide and recommended for advanced Rails developers.
+This guide explains the internals of the initialization process in Rails
+as of Rails 4. It is an extremely in-depth guide and recommended for advanced Rails developers.
* Using +rails server+
* Using Passenger
endprologue.
-This guide goes through every single file, class and method call that is required to boot up the Ruby on Rails stack for a default Rails 3.1 application, explaining each part in detail along the way. For this guide, we will be focusing on how the two most common methods (+rails server+ and Passenger) boot a Rails application.
+This guide goes through every single file, class and method call that is
+required to boot up the Ruby on Rails stack for a default Rails 4 application, explaining each part in detail along the way. For this guide, we will be focusing on how the two most common methods (+rails server+ and Passenger) boot a Rails application.
NOTE: Paths in this guide are relative to Rails or a Rails application unless otherwise specified.
@@ -22,16 +24,15 @@ The actual +rails+ command is kept in _bin/rails_:
<ruby>
#!/usr/bin/env ruby
-begin
- require "rails/cli"
-rescue LoadError
- railties_path = File.expand_path('../../railties/lib', __FILE__)
+if File.exists?(File.join(File.expand_path('../../..', __FILE__), '.git'))
+ railties_path = File.expand_path('../../lib', __FILE__)
$:.unshift(railties_path)
- require "rails/cli"
end
+require "rails/cli"
</ruby>
-This file will attempt to load +rails/cli+. If it cannot find it then +railties/lib+ is added to the load path (+$:+) before retrying.
+This file will first attempt to push the +railties/lib+ directory if
+present, and then require +rails/cli+.
h4. +railties/lib/rails/cli.rb+
@@ -46,7 +47,7 @@ require 'rails/script_rails_loader'
Rails::ScriptRailsLoader.exec_script_rails!
require 'rails/ruby_version_check'
-Signal.trap("INT") { puts; exit }
+Signal.trap("INT") { puts; exit(1) }
if ARGV.first == 'plugin'
ARGV.shift
@@ -56,7 +57,7 @@ else
end
</ruby>
-The +rbconfig+ file from the Ruby standard library provides us with the +RbConfig+ class which contains detailed information about the Ruby environment, including how Ruby was compiled. We can see this in use in +railties/lib/rails/script_rails_loader+.
+The +rbconfig+ file from the Ruby standard library provides us with the +RbConfig+ class which contains detailed information about the Ruby environment, including how Ruby was compiled. We can see thisin use in +railties/lib/rails/script_rails_loader+.
<ruby>
require 'pathname'
@@ -120,6 +121,9 @@ exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
This is effectively the same as running +ruby script/rails [arguments]+, where +[arguments]+ at this point in time is simply "server".
+TIP: If you execute +script/rails+ directly from your Rails app you will
+avoid executing the code that we just described.
+
h4. +script/rails+
This file is as follows:
@@ -134,23 +138,23 @@ The +APP_PATH+ constant will be used later in +rails/commands+. The +config/boot
h4. +config/boot.rb+
-+config/boot.rb+ contains this:
++config/boot.rb+ contains:
<ruby>
# Set up gems listed in the Gemfile.
-gemfile = File.expand_path('../../Gemfile', __FILE__)
-begin
- ENV['BUNDLE_GEMFILE'] = gemfile
- require 'bundler'
- Bundler.setup
-rescue Bundler::GemNotFound => e
- STDERR.puts e.message
- STDERR.puts "Try running `bundle install`."
- exit!
-end if File.exist?(gemfile)
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
</ruby>
-In a standard Rails application, there's a +Gemfile+ which declares all dependencies of the application. +config/boot.rb+ sets +ENV["BUNDLE_GEMFILE"]+ to the location of this file, then requires Bundler and calls +Bundler.setup+ which adds the dependencies of the application (including all the Rails parts) to the load path, making them available for the application to load. The gems that a Rails 3.1 application depends on are as follows:
+In a standard Rails application, there's a +Gemfile+ which declares all
+dependencies of the application. +config/boot.rb+ sets
++ENV['BUNDLE_GEMFILE']+ to the location of this file. If the Gemfile
+exists, +bundler/setup+ is then required.
+
+The gems that a Rails 4 application depends on are as follows:
+
+TODO: change these when the Rails 4 release is near.
* abstract (1.0.0)
* actionmailer (3.1.0.beta)
@@ -183,6 +187,8 @@ h4. +rails/commands.rb+
Once +config/boot.rb+ has finished, the next file that is required is +rails/commands+ which will execute a command based on the arguments passed in. In this case, the +ARGV+ array simply contains +server+ which is extracted into the +command+ variable using these lines:
<ruby>
+ARGV << '--help' if ARGV.empty?
+
aliases = {
"g" => "generate",
"c" => "console",
@@ -195,6 +201,9 @@ command = ARGV.shift
command = aliases[command] || command
</ruby>
+TIP: As you can see, an empty ARGV list will make Rails show the help
+snippet.
+
If we used <tt>s</tt> rather than +server+, Rails will use the +aliases+ defined in the file and match them to their respective commands. With the +server+ command, Rails will run this code:
<ruby>
@@ -361,8 +370,9 @@ This method is defined like this:
<ruby>
def start
+ url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} on http://#{options[:Host]}:#{options[:Port]}"
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
puts "=> Call with -d to detach" unless options[:daemonize]
trap(:INT) { exit }
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
@@ -372,6 +382,15 @@ def start
FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
end
+ unless options[:daemonize]
+ wrapped_app # touch the app so the logger is set up
+
+ console = ActiveSupport::Logger.new($stdout)
+ console.formatter = Rails.logger.formatter
+
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
+ end
+
super
ensure
# The '-h' option calls exit before @options is set.
@@ -380,10 +399,18 @@ ensure
end
</ruby>
-This is where the first output of the Rails initialization happens. This method creates a trap for +INT+ signals, so if you +CTRL+C+ the server, it will exit the process. As we can see from the code here, it will create the +tmp/cache+, +tmp/pids+, +tmp/sessions+ and +tmp/sockets+ directories if they don't already exist prior to calling +super+. The +super+ method will call +Rack::Server.start+ which begins its definition like this:
+This is where the first output of the Rails initialization happens. This
+method creates a trap for +INT+ signals, so if you +CTRL-C+ the server,
+it will exit the process. As we can see from the code here, it will
+create the +tmp/cache+, +tmp/pids+, +tmp/sessions+ and +tmp/sockets+
+directories. It then calls +wrapped_app+ which is responsible for
+creating the Rack app, before creating and assignig an
+instance of +ActiveSupport::Logger+.
+
+The +super+ method will call +Rack::Server.start+ which begins its definition like this:
<ruby>
-def start
+def start &blk
if options[:warn]
$-w = true
end
@@ -403,22 +430,37 @@ def start
pp wrapped_app
pp app
end
-end
-</ruby>
-In a Rails application, these options are not set at all and therefore aren't used at all. The first line of code that's executed in this method is a call to this method:
+ check_pid! if options[:pid]
-<ruby>
-wrapped_app
+ # Touch the wrapped app, so that the config.ru is loaded before
+ # daemonization (i.e. before chdir, etc).
+ wrapped_app
+
+ daemonize_app if options[:daemonize]
+
+ write_pid if options[:pid]
+
+ trap(:INT) do
+ if server.respond_to?(:shutdown)
+ server.shutdown
+ else
+ exit
+ end
+ end
+
+ server.run wrapped_app, options, &blk
+end
</ruby>
-This method calls another method:
+The interesting part for a Rails app is the last line, +server.run+. Here we encounter the +wrapped_app+ method again, which this time
+we're going to explore more.
<ruby>
@wrapped_app ||= build_app app
</ruby>
-Then the +app+ method here is defined like so:
+The +app+ method here is defined like so:
<ruby>
def app
@@ -440,7 +482,7 @@ The +options[:config]+ value defaults to +config.ru+ which contains this:
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
-run YourApp::Application
+run <%= app_const %>
</ruby>
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 92f40b9e31..c41acc7841 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -5,8 +5,7 @@ module Rails
module Generators
module Actions
- # Adds an entry into Gemfile for the supplied gem. If env
- # is specified, add the gem to the given environment.
+ # Adds an entry into Gemfile for the supplied gem.
#
# gem "rspec", :group => :test
# gem "technoweenie-restful-authentication", :lib => "restful-authentication", :source => "http://gems.github.com/"