aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/lib/action_mailer/base.rb2
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb2
-rw-r--r--actionpack/lib/action_view/helpers/sanitize_helper.rb2
-rw-r--r--activemodel/lib/active_model/errors.rb2
-rw-r--r--activeresource/lib/active_resource/base.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb9
-rw-r--r--railties/guides/source/active_record_basics.textile135
-rw-r--r--railties/guides/source/active_support_overview.textile295
-rw-r--r--railties/guides/source/activerecord_validations_callbacks.textile41
-rw-r--r--railties/guides/source/ajax_on_rails.textile322
-rw-r--r--railties/guides/source/configuring.textile174
-rw-r--r--railties/guides/source/contributing_to_rails.textile32
-rw-r--r--railties/guides/source/debugging_rails_applications.textile2
-rw-r--r--railties/guides/source/getting_started.textile4
-rw-r--r--railties/guides/source/rails_on_rack.textile2
-rw-r--r--railties/guides/source/testing.textile81
16 files changed, 914 insertions, 198 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 5ecefe7c09..d020fdffc2 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -38,7 +38,7 @@ module ActionMailer #:nodoc:
# * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header.
# * <tt>bcc</tt> - Takes one or more email addresses. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc:</tt> header.
# * <tt>reply_to</tt> - Takes one or more email addresses. These addresses will be listed as the default recipients when replying to your email. Sets the <tt>Reply-To:</tt> header.
- # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent.
+ # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header will be set by the delivery agent.
# * <tt>content_type</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>.
# * <tt>headers</tt> - Specify additional headers to be set for the message, e.g. <tt>headers 'X-Mail-Count' => 107370</tt>.
#
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 590f9be3ac..8753253dc6 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -8,7 +8,7 @@ module ActionController #:nodoc:
# def create
# # save post
# flash[:notice] = "Successfully created post"
- # redirect_to posts_path(@post)
+ # redirect_to @post
# end
#
# def show
diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb
index d89b955317..e93034d224 100644
--- a/actionpack/lib/action_view/helpers/sanitize_helper.rb
+++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb
@@ -21,7 +21,7 @@ module ActionView
#
# Custom Use (only the mentioned tags and attributes are allowed, nothing else)
#
- # <%= sanitize @article.body, :tags => %w(table tr td), :attributes => %w(id class style)
+ # <%= sanitize @article.body, :tags => %w(table tr td), :attributes => %w(id class style) %>
#
# Add table tags to the default allowed tags
#
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 7a3001174f..b31ab0b837 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -113,7 +113,7 @@ module ActiveModel
full_messages
end
- # Translates an error message in it's default scope (<tt>activemodel.errrors.messages</tt>).
+ # Translates an error message in it's default scope (<tt>activemodel.errors.messages</tt>).
# Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there,
# it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the
# default message (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model name,
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index e5b8589fb3..e1f221bd3e 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -37,6 +37,13 @@ module ActiveResource
# self.element_name = "person"
# end
#
+ # If your Active Resource object is required to use an HTTP proxy you can set the +proxy+ value which holds a URI.
+ #
+ # class PersonResource < ActiveResource::Base
+ # self.site = "http://api.people.com:3000/"
+ # self.proxy = "http://user:password@proxy.people.com:8080"
+ # end
+ #
#
# == Lifecycle methods
#
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index 9d45c2739b..0eb93a0ded 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -1,6 +1,15 @@
class Array
# Wraps the object in an Array unless it's an Array. Converts the
# object to an Array using #to_ary if it implements that.
+ #
+ # It differs with Array() in that it does not call +to_a+ on
+ # the argument:
+ #
+ # Array(:foo => :bar) # => [[:foo, :bar]]
+ # Array.wrap(:foo => :bar) # => [{:foo => :bar}]
+ #
+ # Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8
+ # Array.wrap("foo\nbar") # => ["foo\nbar"]
def self.wrap(object)
case object
when nil
diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile
index bf6e3c8181..226f1b134b 100644
--- a/railties/guides/source/active_record_basics.textile
+++ b/railties/guides/source/active_record_basics.textile
@@ -1,50 +1,37 @@
h2. Active Record Basics
-This guide will give you a strong grasp of the Active Record pattern and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make you a stronger and better developer.
+This guide is an introduction to Active Record. After reading this guide we hope that you'll learn:
-After reading this guide we hope that you'll be able to:
-
-* Understand the way Active Record fits into the MVC model.
-* Create basic Active Record models and map them with your database tables.
-* Use your models to execute CRUD (Create, Read, Update and Delete) database operations.
-* Follow the naming conventions used by Rails to make developing database applications easier and obvious.
-* Take advantage of the way Active Record maps it's attributes with the database tables' columns to implement your application's logic.
-* Use Active Record with legacy databases that do not follow the Rails naming conventions.
+* What Object Relational Mapping and Active Record are and how they are used in Rails
+* How Active Record fits into the Model-View-Controller paradigm
+* How to use Active Record models to manipulate data stored in a relational database
+* Active Record schema naming conventions
+* The concepts of database migrations, validations and callbacks
endprologue.
-h3. What's Active Record?
-
-Rails' ActiveRecord is an implementation of Martin Fowler's "Active Record Design Pattern":http://martinfowler.com/eaaCatalog/activeRecord.html. This pattern is based on the idea of creating relations between the database and the application in the following way:
+h3. What is Active Record?
-* Each database table is mapped to a class.
-* Each table column is mapped to an attribute of this class.
-* Each instance of this class is mapped to a single row in the database table.
+Active Record is the M in "MVC":getting_started.html#the-mvc-architecture - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
-The definition of the Active Record pattern in Martin Fowler's words:
+h4. The Active Record Pattern
-??An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.??
+Active Record was described by Martin Fowler in his book _Patterns of Enterprise Application Architecture_. In Active Record, objects carry both persistent data and behavior which operates on that data. Active Record takes the opinion that ensuring data access logic is part of the object will educate users of that object on how to write to and read from the database.
-h3. Object Relational Mapping
+h4. Object Relational Mapping
-The relation between databases and object-oriented software is called ORM, which is short for "Object Relational Mapping". The purpose of an ORM framework is to minimize the mismatch existent between relational databases and object-oriented software. In applications with a domain model, we have objects that represent both the state of the system and the behavior of the real world elements that were modeled through these objects. Since we need to store the system's state somehow, we can use relational databases, which are proven to be an excellent approach to data management. Usually this may become a very hard thing to do, since we need to create an object-oriented model of everything that lives in the database, from simple columns to complicated relations between different tables. Doing this kind of thing by hand is a tedious and error prone job. This is where an ORM framework comes in.
+Object-Relational Mapping, commonly referred to as its abbreviation ORM, is a technique that connects the rich objects of an application to tables in a relational database management system. Using ORM, the properties and relationships of the objects in an application can be easily stored and retrieved from a database without writing SQL statements directly and with less overall database access code.
-h3. ActiveRecord as an ORM Framework
+h4. Active Record as an ORM Framework
-ActiveRecord gives us several mechanisms, being the most important ones the ability to:
+Active Record gives us several mechanisms, the most important being the ability to:
-* Represent models.
-* Represent associations between these models.
-* Represent inheritance hierarchies through related models.
-* Validate models before they get recorded to the database.
+* Represent models and their data
+* Represent associations between these models
+* Represent inheritance hierarchies through related models
+* Validate models before they get persisted to the database
* Perform database operations in an object-oriented fashion.
-It's easy to see that the Rails Active Record implementation goes way beyond the basic description of the Active Record Pattern.
-
-h3. Active Record Inside the MVC Model
-
-Active Record plays the role of model inside the MVC structure followed by Rails applications. Since model objects should encapsulate both state and logic of your applications, it's ActiveRecord responsibility to deliver you the easiest possible way to recover this data from the database.
-
h3. Convention over Configuration in ActiveRecord
When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason.
@@ -125,11 +112,93 @@ class Product < ActiveRecord::Base
end
</ruby>
+h3. Reading and Writing Data
+
+CRUD is an acronym for the four verbs we use to operate on data: Create, Read, Update, Delete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables.
+
+h4. Create
+
+Active Record objects can be created from a hash, a block or have its attributes manually set after creation. The _new_ method will return a new object while _create_ will return the object and save it to the database.
+
+For example, given a model +User+ with attributes of +name+ and +occupation+, the _create_ method call will create and save a new record into the database:
+
+<ruby>
+ user = User.create(:name => "David", :occupation => "Code Artist")
+</ruby>
+
+Using the _new_ method, an object can be created without being saved:
+
+<ruby>
+ user = User.new
+ user.name = "David"
+ user.occupation = "Code Artist"
+</ruby>
+
+A call to _user.save_ will commit the record to the database.
+
+Finally, passing a block to either create or new will return a new User object:
+
+<ruby>
+ user = User.new do |u|
+ u.name = "David"
+ u.occupation = "Code Artist"
+ end
+</ruby>
+
+h4. Read
+
+ActiveRecord provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by ActiveRecord.
+
+<ruby>
+ # return all records
+ users = User.all
+</ruby>
+
+<ruby>
+ # return first record
+ user = User.first
+</ruby>
+
+<ruby>
+ # return the first user named David
+ david = User.find_by_name('David')
+</ruby>
+
+<ruby>
+ # find all users named David who are Code Artists and sort by created_at in reverse chronological order
+ users = User.all(:conditions => { :name => 'David', :occupation => 'Code Artist'}, :order => 'created_at DESC')
+</ruby>
+
+You can learn more about querying an Active Record model in the "Active Record Query Interface":"active_record_querying.html" guide.
+
+h4. Update
+
+Once an Active Record object has been retrieved, its attributes can be modified and it can be saved to the database.
+
+<ruby>
+ user = User.find_by_name('David')
+ user.name = 'Dave'
+ user.save
+</ruby>
+
+h4. Delete
+
+Likewise, once retrieved an Active Record object can be destroyed which removes it from the database.
+
+<ruby>
+ user = User.find_by_name('David')
+ user.destroy
+</ruby>
+
+
h3. Validations
-ActiveRecord gives the ability to validate the state of your models before they get recorded into the database. There are several methods that you can use to hook into the life-cycle of your models and validate that an attribute value is not empty or follow a specific format and so on. You can learn more about validations in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#validations-overview.
+Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#validations-overview.
h3. Callbacks
-ActiveRecord callbacks allow you to attach code to certain events in the life-cycle of your models. This way you can add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#callbacks-overview.
+Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#callbacks-overview.
+
+h3. Migrations
+Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the "Active Record Migrations guide":migrations.html \ No newline at end of file
diff --git a/railties/guides/source/active_support_overview.textile b/railties/guides/source/active_support_overview.textile
index aea77c8d4e..ca1480b626 100644
--- a/railties/guides/source/active_support_overview.textile
+++ b/railties/guides/source/active_support_overview.textile
@@ -435,7 +435,67 @@ end
h3. Extensions to +Module+
-...
+h4. Aliasing
+
+h5. +alias_method_chain+
+
+Using plain Ruby you can wrap methods with other methods, that's called _alias chaining_.
+
+For example, let's say you'd like params to be strings in functional tests, as they are in real requests, but still want the convenience of assigning integers and other kind of values. To accomplish that you could wrap +ActionController::TestCase#process+ this way in +test/test_helper.rb+:
+
+<ruby>
+ActionController::TestCase.class_eval do
+ # save a reference to the original process method
+ alias_method :original_process, :process
+
+ # now redefine process and delegate to original_process
+ def process(action, params=nil, session=nil, flash=nil, http_method='GET')
+ params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
+ original_process(action, params, session, flash, http_method)
+ end
+end
+</ruby>
+
+That's the method +get+, +post+, etc., delegate the work to.
+
+That technique has a risk, it could be the case that +:original_process+ was taken. To try to avoid collisions people choose some label that characterizes what the chaining is about:
+
+<ruby>
+ActionController::TestCase.class_eval do
+ def process_with_stringified_params(...)
+ params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
+ process_without_stringified_params(action, params, session, flash, http_method)
+ end
+ alias_method :process_without_stringified_params, :process
+ alias_method :process, :process_with_stringified_params
+end
+</ruby>
+
+The method +alias_method_chain+ provides a shortcut for that pattern:
+
+<ruby>
+ActionController::TestCase.class_eval do
+ def process_with_stringified_params(...)
+ params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
+ process_without_stringified_params(action, params, session, flash, http_method)
+ end
+ alias_method_chain :process, :stringified_params
+end
+</ruby>
+
+Rails uses +alias_method_chain+ all over the code base. For example validations are added to +ActiveRecord::Base#save+ by wrapping the method that way in a separate module specialised in validations.
+
+h5. +alias_attribute+
+
+Model attributes have a reader, a writer, and a predicate. You can aliase a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (my mnemonic is they go in the same order as if you did an assignment):
+
+<ruby>
+class User < ActiveRecord::Base
+ # let me refer to the email column as "login",
+ # much meaningful for authentication code
+ alias_attribute :login, :email
+end
+</ruby>
h3. Extensions to +Class+
@@ -596,25 +656,86 @@ C # => NameError: uninitialized constant C
See also +Object#remove_subclasses_of+ in "Extensions to All Objects FIX THIS LINK":FIXME.
-h3. Extensions to +NilClass+
+h3. Extensions to +Symbol+
-...
+h4. +to_proc+
-h3. Extensions to +TrueClass+
+The method +to_proc+ turns a symbol into a Proc object so that for example
-...
+<ruby>
+emails = users.map {|u| u.email}
+</ruby>
-h3. Extensions to +FalseClass+
+can be written as
-...
+<ruby>
+emails = users.map(&:email)
+</ruby>
-h3. Extensions to +Symbol+
+TIP: If the method that receives the Proc yields more than one value to it the rest are considered to be arguments of the method call.
-...
+Symbols from Ruby 1.8.7 on respond to +to_proc+, and Active Support defines it for previous versions.
h3. Extensions to +String+
-...
+h4. +bytesize+
+
+Ruby 1.9 introduces +String#bytesize+ to obtain the length of a string in bytes. Ruby 1.8.7 defines this method as an alias for +String#size+ for forward compatibility, and Active Support does so for previous versions.
+
+h4. +squish+
+
+The method +String#squish+ strips leading and trailing whitespace, and substitutes runs of whitespace with a single space each:
+
+<ruby>
+" \n foo\n\r \t bar \n".squish # => "foo bar"
+</ruby>
+
+There's also the destructive version +String#squish!+.
+
+h4. Key-based Interpolation
+
+In Ruby 1.9 the <tt>%</tt> string operator supports key-based interpolation, both formatted and unformatted:
+
+<ruby>
+"Total is %<total>.02f" % {:total => 43.1} # => Total is 43.10
+"I say %{foo}" % {:foo => "wadus"} # => "I say wadus"
+"I say %{woo}" % {:foo => "wadus"} # => KeyError
+</ruby>
+
+Active Support adds that functionality to <tt>%</tt> in previous versions of Ruby.
+
+h4. +start_with?+ and +end_width?+
+
+Ruby 1.8.7 and up define the predicates +String#start_with?+ and +String#end_with?+:
+
+<ruby>
+"foo".start_with?("f") # => true
+"foo".start_with?("g") # => false
+"foo".start_with?("") # => true
+
+"foo".end_with?("o") # => true
+"foo".end_with?("p") # => false
+"foo".end_with?("") # => true
+</ruby>
+
+If strings do not respond to those methods Active Support emulates them, and also defines their 3rd person aliases:
+
+<ruby>
+"foo".starts_with?("f") # => true
+"foo".ends_with?("o") # => true
+</ruby>
+
+in case you feel more comfortable spelling them that way.
+
+WARNING. Active Support invokes +to_s+ on the argument, but Ruby does not. Since Active Support defines these methods only if strings do not respond to them, this corner of their behaviour depends on the interpreter that runs a given Rails application. You change the interpreter, and +start_with?(1)+ may change its return value. In consequence, it's more portable not to rely on that and pass always strings.
+
+h4. +each_char+
+
+Ruby 1.8.7 and up define the iterator +String#each_char+ that understands UTF8 and yields strings with a single character each, so they have length 1 but may be multibyte. Active Support defines that method for previous versions of Ruby:
+
+<ruby>
+"\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E".each_char {|c| print c} # => 日本語
+</ruby>
h3. Extensions to +Numeric+
@@ -622,7 +743,40 @@ h3. Extensions to +Numeric+
h3. Extensions to +Integer+
-...
+h4. +multiple_of?+
+
+The method +multiple_of?+ tests whether an integer is multiple of the argument:
+
+<ruby>
+2.multiple_of?(1) # => true
+1.multiple_of?(2) # => false
+</ruby>
+
+WARNING: Due the way it is implemented the argument must be nonzero, otherwise +ZeroDivisionError+ is raised.
+
+h4. +even?+ and +odd?+
+
+Integers in Ruby 1.8.7 and above respond to +even?+ and +odd?+, Active Support defines them for older versions:
+
+<ruby>
+-1.even? # => false
+-1.odd? # => true
+ 0.even? # => true
+ 0.odd? # => false
+ 2.even? # => true
+ 2.odd? # => false
+</ruby>
+
+h4. +ordinalize+
+
+The method +ordinalize+ returns the ordinal string corresponding to the receiver integer:
+
+<ruby>
+1.ordinalize # => "1st"
+2.ordinalize # => "2nd"
+53.ordinalize # => "53rd"
+2009.ordinalize # => "2009th"
+</ruby>
h3. Extensions to +Float+
@@ -663,6 +817,60 @@ You can pick a random element with +rand+:
shape_type = [Circle, Square, Triangle].rand
</ruby>
+h4. Conversions
+
+h5. +to_sentence+
+
+The method +to_sentence+ turns an array into a string containing a sentence that enumerates its items:
+
+<ruby>
+%w().to_sentence # => ""
+%w(Earth).to_sentence # => "Earth"
+%w(Earth Wind).to_sentence # => "Earth and Wind"
+%w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"
+</ruby>
+
+This method accepts three options:
+
+* <tt>:two_words_connector</tt>: What is used for arrays of length 2. Default is " and ".
+* <tt>:words_connector</tt>: What is used to join the elements of arrays with 3 or more elements, except for the last two. Default is ", ".
+* <tt>:last_word_connector</tt>: What is used to join the last items of an array with 3 or more elements. Default is ", and ".
+
+The defaults for these options can be localised, their keys are:
+
+|_. Option |_. I18n key |
+| <tt>:two_words_connector</tt> | <tt>support.array.two_words_connector</tt> |
+| <tt>:words_connector</tt> | <tt>support.array.words_connector</tt> |
+| <tt>:last_word_connector</tt> | <tt>support.array.last_word_connector</tt> |
+
+Options <tt>:connector</tt> and <tt>:skip_last_comma</tt> are deprecated.
+
+h5. +to_formatted_s+
+
+The method +to_formatted_s+ acts like +to_s+ by default.
+
+If the array contains items that respond to +id+, however, it may be passed the symbol <tt>:db</tt> as argument. That's typically used with collections of ARs, though technically any object in Ruby 1.8 responds to +id+ indeed. Returned strings are:
+
+<ruby>
+[].to_formatted_s(:db) # => "null"
+[user].to_formatted_s(:db) # => "8456"
+invoice.lines.to_formatted_s(:db) # => "23,567,556,12"
+</ruby>
+
+Integers in the example above are supposed to come from the respective calls to +id+.
+
+h4. Wrapping
+
+The class method +Array.wrap+ behaves like the function +Array()+ except that it does not try to call +to_a+ on its argument. That changes the behaviour for enumerables:
+
+<ruby>
+Array.wrap(:foo => :bar) # => [{:foo => :bar}]
+Array(:foo => :bar) # => [[:foo, :bar]]
+
+Array.wrap("foo\nbar") # => ["foo\nbar"]
+Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8
+</ruby>
+
h4. Grouping
h5. +in_groups_of(number, fill_with = nil)+
@@ -789,7 +997,25 @@ h3. Extensions to +Pathname+
h3. Extensions to +File+
-...
+h4. +atomic_write+
+
+With the class method +File.atomic_write+ you can write to a file in a way that will prevent any reader from seeing half-written content.
+
+The name of the file is passed as an argument, and the method yields a file handle opened for writing. Once the block is done +atomic_write+ closes the file handle and completes its job.
+
+For example, Action Pack uses this method to write asset cache files like +all.css+:
+
+<ruby>
+File.atomic_write(joined_asset_path) do |cache|
+ cache.write(join_asset_file_contents(asset_paths))
+end
+</ruby>
+
+To accomplish this +atomic_write+ creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed. If the target file exists +atomic_write+ overwrites it and keeps owners and permissions.
+
+WARNING. Note you can't append with +atomic_write+.
+
+The auxiliary file is written in a standard directory for temporary files, but you can pass a directory of your choice as second argument.
h3. Extensions to +Exception+
@@ -797,11 +1023,54 @@ h3. Extensions to +Exception+
h3. Extensions to +NameError+
-...
+Active Support adds +missing_name?+ to +NameError+, which tests whether the exception was raised because of the name passed as argument.
+
+The name may be given as a symbol or string. A symbol is tested against the bare constant name, a string is against the fully-qualified constant name.
+
+TIP: A symbol can represent a fully-qualified constant name as in +:"ActiveRecord::Base"+, so the behaviour for symbols is defined for convenience, not because it has to be that way technically.
+For example, when an action of +PostsController+ is called Rails tries optimistically to use +PostsHelper+. It is OK that the helper module does not exist, so if an exception for that constant name is raised it should be silenced. But it could be the case that +posts_helper.rb+ raises a +NameError+ due to an actual unknown constant. That should be reraised. The method +missing_name?+ provides a way to distinguish both cases:
+
+<ruby>
+def default_helper_module!
+ module_name = name.sub(/Controller$/, '')
+ module_path = module_name.underscore
+ helper module_path
+rescue MissingSourceFile => e
+ raise e unless e.is_missing? "#{module_path}_helper"
+rescue NameError => e
+ raise e unless e.missing_name? "#{module_name}Helper"
+end
+</ruby>
+
h3. Extensions to +LoadError+
+Rails hijacks +LoadError.new+ to return a +MissingSourceFile+ exception:
+
+<shell>
+$ ruby -e 'require "nonexistent"'
+...: no such file to load -- nonexistent (LoadError)
+...
+$ script/runner 'require "nonexistent"'
+...: no such file to load -- nonexistent (MissingSourceFile)
...
+</shell>
+
+The class +MissingSourceFile+ is a subclass of +LoadError+, so any code that rescues +LoadError+ as usual still works as expected. Point is these exception objects respond to +is_missing?+, which given a path name tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
+
+For example, when an action of +PostsController+ is called Rails tries to load +posts_helper.rb+, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist, but it in turn requires another library that is missing. In that case Rails must reraise the exception. The method +is_missing?+ provides a way to distinguish both cases:
+
+<ruby>
+def default_helper_module!
+ module_name = name.sub(/Controller$/, '')
+ module_path = module_name.underscore
+ helper module_path
+rescue MissingSourceFile => e
+ raise e unless e.is_missing? "#{module_path}_helper"
+rescue NameError => e
+ raise e unless e.missing_name? "#{module_name}Helper"
+end
+</ruby>
h3. Extensions to +CGI+
diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile
index 03d521ea1f..9d0ee29ff2 100644
--- a/railties/guides/source/activerecord_validations_callbacks.textile
+++ b/railties/guides/source/activerecord_validations_callbacks.textile
@@ -403,6 +403,47 @@ WARNING. Note that some databases are configured to perform case-insensitive sea
The default error message for +validates_uniqueness_of+ is "_has already been taken_".
+h4. +validates_with+
+
+This helper passes the record to a separate class for validation.
+
+<ruby>
+class Person < ActiveRecord::Base
+ validates_with GoodnessValidator
+end
+
+class GoodnessValidator < ActiveRecord::Validator
+ def validate
+ if record.first_name == "Evil"
+ record.errors[:base] << "This person is evil"
+ end
+ end
+end
+</ruby>
+
+The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class.
+
+The validator class has two attributes by default:
+
+* +record+ - the record to be validated
+* +options+ - the extra options that were passed to +validates_with+
+
+Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+:
+
+<ruby>
+class Person < ActiveRecord::Base
+ validates_with GoodnessValidator, :fields => [:first_name, :last_name]
+end
+
+class GoodnessValidator < ActiveRecord::Validator
+ def validate
+ if options[:fields].any?{|field| record.send(field) == "Evil" }
+ record.errors[:base] << "This person is evil"
+ end
+ end
+end
+</ruby>
+
h4. +validates_each+
This helper validates attributes against a block. It doesn't have a predefined validation function. You should create one using a block, and every attribute passed to +validates_each+ will be tested against it. In the following example, we don't want names and surnames to begin with lower case.
diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile
index 74e8dec5cf..8a38cf2dc2 100644
--- a/railties/guides/source/ajax_on_rails.textile
+++ b/railties/guides/source/ajax_on_rails.textile
@@ -3,9 +3,8 @@ h2. AJAX on Rails
This guide covers the built-in Ajax/Javascript functionality of Rails (and more); it will enable you to create rich and dynamic AJAX applications with ease! We will cover the following topics:
* Quick introduction to AJAX and related technologies
-* Handling Javascript the Rails way: Rails helpers, RJS, Prototype and script.aculo.us
+* Handling Javascript the Rails way: Rails helpers, RJS, Prototype and script.aculo.us
* Testing Javascript functionality
-* Becoming an Ajax Master on Rails: Plugins, Best Practices, Tips and Tricks
endprologue.
@@ -30,65 +29,314 @@ How do 'standard' and AJAX requests differ, why does this matter for understandi
-h3. Built-in Rails Helpers
+h3. Built-in Rails Helpers
-Mostly a reference to standard JS helpers like link_to_remote, remote_form_for etc + some explanation
+Rails' Javascript framework of choice is "Prototype":http://www.prototypejs.org. Prototype is a generic-purpose Javascript framework that aims to ease the development of dynamic web applications by offering DOM manipulation, AJAX and other Javascript functionality ranging from utility functions to object oriented constructs. It is not specifically written for any language, so Rails provides a set of helpers to enable seamless integration of Prototype with your Rails views.
+To get access to these helpers, all you have to do is to include the prototype framework in your pages - typically in your master layout, application.html.erb - like so:
+<ruby>
+javascript_include_tag 'prototype'
+</ruby>
+You are ready to add some AJAX love to your Rails app!
-h3. Responding to AJAX the Rails way: RJS
+h4. The Quintessential AJAX Rails Helper: link_to_remote
-In the last section we sent some AJAX requests to the server; now we need to respond, and the standard Rails way to this is using RJS; RJS intro, function reference
+Let's start with the the probably most often used helper: +link_to_remote+, which has an interesting feature from the documentation point of view: the options supplied to +link_to_remote+ are shared by all other AJAX helpers, so learning the mechanics and options of +link_to_remote+ is a great help when using other helpers.
+The signature of +link_to_remote+ function is the same as that of the standard +link_to+ helper:
+<ruby>
+def link_to_remote(name, options = {}, html_options = nil)
+</ruby>
-h3. I Want my Yellow Thingy: Prototype and Script.aculo.us
+And here is a simple example of link_to_remote in action:
-Walk through prototype and script.aculo.us, most important functionality, method reference etc.
+<ruby>
+link_to_remote "Add to cart",
+ :url => add_to_cart_url(product.id),
+ :update => "cart"
+</ruby>
+* The very first parameter, a string, is the text of the link which appears on the page.
+* The second parameter, the +options+ hash is the most interesting part as it has the AJAX specific stuff:
+** *:url* This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty +options+ hash to +link_to_remote+ - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the +url_for+ format too.
+** *:update* There are basically two ways of injecting the server response into the page: One is involving RJS and we will discuss it in the next chapter, and the other is specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
-h3. Testing Javascript
+<ruby>
+link_to_remote "Add to cart",
+ :url => add_to_cart_url(product),
+ :update => { :success => "cart", :failure => "error" }
+</ruby>
-Javascript testing reminds me the definition of the world 'classic' by Mark Twain: "A classic is something that everybody wants to have read and nobody wants to read." It's similar with Javascript testing: everyone would like to have it, yet it's not done by too much developers as it is tedious, complicated, there is a proliferation of tools and no consensus/accepted best practices, but we will nevertheless take a stab at it:
+If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element.
-* (Fire)Watir
-* Selenium
-* Celerity/Culerity
-* Cucumber+Webrat
-* Mention stuff like screw.unit/jsSpec
+** *position* By default (i.e. when not specifying this option, like in the examples before) the repsonse is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
+*** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element.
+*** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element.
+*** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all.
+*** +:bottom+ The counterpart of +:top+: the response is inserted after the target element's original content.
+
+A typical example of using +:bottom+ is inserting a new &lt;li&gt; element into an existing list:
+
+<ruby>
+link_to_remote "Add new item",
+ :url => items_url,
+ :update => 'item_list',
+ :position => :bottom
+</ruby>
+
+** *:method* Most typically you want to use a POST request when adding a remote link to your view so this is the default behavior. However, sometimes you'll want to update (PUT) or delete/destroy (DELETE) something and you can specify this with the +:method+ option. Let's see an example for a typical AJAX link for deleting an item from a list:
+
+<ruby>
+link_to_remote "Delete the item",
+ :url => item_url(item),
+ :method => :delete
+</ruby>
+
+Note that if we wouldn't override the default behavior (POST), the above snippet would route to the create action rather than destroy.
+
+** *JavaScript filters* You can customize the remote call further by wrapping it with some JavaScript code. Let's say in the previous example, when deleting a link, you'd like to ask for a confirmation by showing a simple modal text box to the user. This is a typical example what you can accomplish with these options - let's see them one by one:
+*** +:confirm+ =&gt; +msg+ Pops up a JavaScript confirmation dialog, displaying +msg+. If the user chooses 'OK', the request is launched, otherwise canceled.
+*** +:condition+ =&gt; +code+ Evaluates +code+ (which should evaluate to a boolean) and proceeds if it's true, cancels the request otherwise.
+*** +:before+ =&gt; +code+ Evaluates the +code+ just before launching the request. The output of the code has no influence on the execution. Typically used show a progress indicator (see this in action in the next example).
+*** +:after+ =&gt; +code+ Evaluates the +code+ after launching the request. Note that this is different from the +:success+ or +:complete+ callback (covered in the next section) since those are triggered after the request is completed, while the code snippet passed to +:after+ is evaluated after the remote call is made. A common example is to disable elements on the page or otherwise prevent further action while the request is completed.
+*** +:submit+ =&gt; +dom_id+ This option does not make sense for +link_to_remote+, but we'll cover it for the sake of completeness. By default, the parent element of the form elements the user is going to submit is the current form - use this option if you want to change the default behavior. By specifying this option you can change the parent element to the element specified by the DOM id +dom_id+.
+*** +:with+ &gt; +code+ The JavaScript code snippet in +code+ is evaluated and added to the request URL as a parameter (or set of parameters). Therefore, +code+ should return a valid URL query string (like "item_type=8" or "item_type=8&sort=true"). Usually you want to obtain some value(s) from the page - let's see an example:
+
+<ruby>
+link_to_remote "Update record",
+ :url => record_url(record),
+ :method => :put,
+ :with => "'status=' + 'encodeURIComponent($('status').value) + '&completed=' + $('completed')"
+</ruby>
+
+This generates a remote link which adds 2 parameters to the standard URL generated by Rails, taken from the page (contained in the elements matched by the 'status' and 'completed' DOM id).
+
+** *Callbacks* Since an AJAX call is typically asynchronous, as it's name suggests (this is not a rule, and you can fire a synchronous request - see the last option, +:type+) your only way of communicating with a request once it is fired is via specifying callbacks. There are six options at your disposal (in fact 508, counting all possible response types, but these six are the most frequent and therefore specified by a constant):
+*** +:loading:+ =&gt; +code+ The request is in the process of receiving the data, but the transfer is not completed yet.
+*** +:loaded:+ =&gt; +code+ The transfer is completed, but the data is not processed and returned yet
+*** +:interactive:+ =&gt; +code+ One step after +:loaded+: The data is fully received and being processed
+*** +:success:+ =&gt; +code+ The data is fully received, parsed and the server responded with "200 OK"
+*** +:failure:+ =&gt; +code+ The data is fully received, parsed and the server responded with *anything* but "200 OK" (typically 404 or 500, but in general with any status code ranging from 100 to 509)
+*** +:complete:+ =&gt; +code+ The combination of the previous two: The request has finished receiving and parsing the data, and returned a status code (which can be anything).
+*** Any other status code ranging from 100 to 509: Additionally you might want to check for other HTTP status codes, such as 404. In this case simply use the status code as a number:
+<ruby>
+link_to_remote "Add new item",
+ :url => items_url,
+ :update => "item_list",
+ 404 => "alert('Item not found!')"
+</ruby>
+Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action:
+<ruby>
+link_to_remote "Add new item",
+ :url => items_url,
+ :update => "item_list",
+ :before => "$('progress').show()",
+ :complete => "$('progress').hide()",
+ :success => "display_item_added(request)",
+ :failure => "display_error(request)",
+</ruby>
+** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+.
+* Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though:
+** If you specify the +href+ parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser
+** +link_to_remote+ gains it's AJAX behavior by specifying the remote call in the onclick handler of the link. If you supply +html_options[:onclick]+ you override the default behavior, so use this with care!
+
+We are finished with +link_to_remote+. I know this is quite a lot to digest for one helper function, but remember, these options are common for all the rest of the Rails view helpers, so we will take a look at the differences / additional parameters in the next sections.
+
+h4. AJAX Forms
+
+There are three different ways of adding AJAX forms to your view using Rails Prototype helpers. They are slightly different, but striving for the same goal: instead of submitting the form using the standard HTTP request/response cycle, it is submitted asynchronously, thus not reloading the page. These methods are the following:
+
+* +remote_form_for+ (and it's alias +form_remote_for+) is tied to Rails most tightly of the three since it takes a resource, model or array of resources (in case of a nested resource) as a parameter.
+* +form_remote_tag+ AJAXifies the form by serializing and sending it's data in the background
+* +submit_to_remote+ and +button_to_remote+ is more rarely used than the previous two. Rather than creating an AJAX form, you add a button/input
+
+Let's se them in action one by one!
+
+h5. +remote_form_for+
+
+h5. +form_remote_tag+
+
+h5. +submit_to_remote+
+
+h4. Observing Elements
+
+h5. +observe_field+
+
+h5. +observe_form+
+
+h4. Calling a Function Periodically
+
+h5. +periodically_call_remote+
+
+
+h4. Miscellaneous Functionality
+
+h5. +remote_function+
+
+h5. +update_page+
+
+
+h3. JavaScript the Rails way: RJS
+
+In the last section we sent some AJAX requests to the server, and inserted the HTML response into the page (with the +:update+ option). However, sometimes a more complicated interaction with the page is needed, which you can either achieve with JavaScript... or with RJS! You are sending JavaScript instructions to the server in both cases, but while in the former case you have to write vanilla JavaScript, in the second you can code Rails, and sit back while Rails generates the JavaScript for you - so basically RJS is a Ruby DSL to write JavaScript in your Rails code.
+
+h4. Javascript without RJS
+
+First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood.
+
+<ruby>
+def javascript_test
+ render :text => "alert('Hello, world!')",
+ :content_type => "text/javascript"
+end
+</ruby>
+
+(Note: if you want to test the above method, create a +link_to_remote+ with a single parameter - +:url+, pointing to the +javascript_test+ action)
+
+What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior).
+
+h4. Inline RJS
+
+As we said, the purpose of RJS is to write Ruby which is then auto-magically turned into JavaScript by Rails. The above example didn't look too Ruby-esque so let's see how to do it the Rails way:
+
+<ruby>
+def javascript_test
+ render :update do |page|
+ page.alert "Hello from inline RJS"
+ end
+end
+</ruby>
+
+The above code snippet does exactly the same as the one in the previous section - going about it much more elegantly though. You don't need to worry about headers,write ugly JavaScript code into a string etc. When the first parameter to +render+ is +:update+, Rails expects a block with a single parameter (+page+ in our case, which is the traditional naming convention) which is an instance of the JavaScriptGenerator:"http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html" object. As it's name suggests, JavaScriptGenerator is responsible for generating JavaScript from your Ruby code. You can execute multiple method calls on the +page+ instance - it's all turned into JavaScript code and sent to the server with the appropriate Content Type, "text/javascript".
+
+h4. RJS Templates
-Note to self: check out the RailsConf JS testing video
+If you don't want to clutter your controllers with view code (especially when your inline RJS is more than a few lines), you can move your RJS code to a template file. RJS templates should go to the +/app/views/+ directory, just as +.html.erb+ or any other view files of the appropriate controller, conventionally named +js.rjs+.
-h3. Useful Plugins
+To rewrite the above example, you can leave the body of the action empty, and create a RJS template named +javascript_test.js.rjs+, containing the following line:
-This was in the ticket description, but at the moment I don't really have clue what to add here, so please tell me
+<ruby>
+page.alert "Hello from inline RJS"
+</ruby>
+h4. RJS Reference
+In this section we'll go through the methods RJS offers.
-h3. Tips and Tricks
+h5. JavaScriptGenerator Methods
-* Unobtrusive Javascript (Prototype events, maybe the jQuery way (esp. jQeury.live()))
+h6. DOM Element Manipulation
-* Minimize communication with the server - there does not have to be a communication at all!
-** If you absolutely don't have to, don't use Rails observers
-** Cache stuff on the client side, e.g. with auto-complete
+It is possible to manipulate multiple elements at once through the +page+ JavaScriptGenerator instance. Let's see this in action:
-* Using AJAX to load stuff asynchronously
-** To avoid page blocking
-** Tricking page caching
-*** inserting user-specific info into a cached page
-*** anti-CSFR bit
+<ruby>
+page.show :div_one, :div_two
+page.hide :div_one
+page.remove :div_one, :div_two, :div_three
+page.toggle :other_div
+</ruby>
-* Jumping to the top? Try event.stopPropagation
+The above methods (+show+, +hide+, +remove+, +toggle+) have the same semantics as the Prototype methods of the same name. You can pass an arbitrary number (but at least one) of DOM ids to these calls.
-* Performance
-** pack your javascript (minify, asset packager)
-** require your JS at the end of the file
-** other perf tricks and optimization
-* Don't overuse AJAX
-** Usability first, cool effects second
-** situations where AJAX is discouraged
+h6. Inserting and Replacing Content
+
+You can insert content into an element on the page with the +insert_html+ method:
+
+<ruby>
+page.insert_html :top, :result, '42'
+</ruby>
+
+The first parameter is the position of the new content relative to the element specified by the second parameter, a DOM id.
+
+Position can be one of these four values:
+
+*** +:before+ Inserts the response text just before the target element.
+*** +:after+ The response is inserted after the target element.
+*** +:top+ Inserts the text into the target element, before it's original content.
+*** +:bottom+ The counterpart of +:top+: the response is inserted after the target element's original content.
+
+The third parameter can either be a string, or a hash of options to be passed to ActionView::Base#render - for example:
+
+<ruby>
+page.insert_html :top, :result, :partial => "the_answer"
+</ruby>
+
+You can replace the contents (innerHTML) of an element with the +replace_html+ method. The only difference is that since it's clear where should the new content go, there is no need for a position parameter - so +replace_html+ takes only two arguments,
+the DOM id of the element you wish to modify and a string or a hash of options to be passed to ActionView::Base#render.
+
+h6. Delay
+
+You can delay the execution of a block of code with +delay+:
+
+<ruby>
+page.delay(10) { page.alert('Hey! Just waited 10 seconds') }
+</ruby>
+
++delay+ takes one parameter (time to wait in seconds) and a block which will be executed after the specified time has passed - whatever else follows a +page.delay+ line is executed immediately, the delay affects only the code in the block.
+
+h6. Reloading and Redirecting
+
+You can reload the page with the +reload+ method:
+
+<ruby>
+page.reload
+</ruby>
+
+When using AJAX, you can't rely on the standard +redirect_to+ controller method - you have to use the +page+'s instance method, also called +redirect_to+:
+
+<ruby>
+page.redirect_to some_url
+</ruby>
+
+h6. Generating Arbitrary JavaScript
+
+Sometimes even the full power of RJS is not enough to accomplish everything, but you still don't want to drop to pure JavaScript. A nice golden mean is offered by the combination of +<<+, +assign+ and +call+ methods:
+
+<ruby>
+ page << "alert('1+1 equals 3')"
+</ruby>
+
+So +<<+ is used to execute an arbitrary JavaScript statement, passed as string to the method. The above code is equivalent to:
+
+<ruby>
+ page.assign :result, 3
+ page.call :alert, '1+1 equals ' + result
+</ruby>
+
++assign+ simply assigns a value to a variable. +call+ is similar to +<<+ with a slightly different syntax: the first parameter is the name of the function to call, followed by the list of parameters passed to the function.
+
+h6. Class Proxies
+
+h5. Element Proxies
+
+h5. Collection Proxies
+
+h5. RJS Helpers
+
+
+
+h3. I Want my Yellow Thingy: Quick overview of Script.aculo.us
+
+h4. Introduction
+
+h4. Visual Effects
+
+h4. Drag and Drop
+
+
+
+h3. Testing Javascript
+
+Javascript testing reminds me the definition of the world 'classic' by Mark Twain: "A classic is something that everybody wants to have read and nobody wants to read." It's similar with Javascript testing: everyone would like to have it, yet it's not done by too much developers as it is tedious, complicated, there is a proliferation of tools and no consensus/accepted best practices, but we will nevertheless take a stab at it:
+
+* (Fire)Watir
+* Selenium
+* Celerity/Culerity
+* Cucumber+Webrat
+* Mention stuff like screw.unit/jsSpec
-* Last but not least: Javascript is your friend :)
+Note to self: check out the RailsConf JS testing video \ No newline at end of file
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 2711337d43..0e6f981168 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -7,7 +7,6 @@ This guide covers the configuration and initialization features available to Rai
endprologue.
-
h3. Locations for Initialization Code
Rails offers (at least) five good spots to place initialization code:
@@ -38,31 +37,87 @@ config.active_record.colorize_logging = false
Rails will use that particular setting to configure Active Record.
+h4. Rails General Configuration
+
+* +config.routes_configuration_file+ overrides the default path for the routes configuration file. This defaults to +config/routes.rb+.
+
+* +config.cache_classes+ controls whether or not application classes should be reloaded on each request.
+
+* +config.cache_store+ configures which cache store to use for Rails caching. Options include +:memory_store+, +:file_store+, +:mem_cache_store+ or the name of your own custom class.
+
+* +config.controller_paths+ accepts an array of paths that will be searched for controllers. Defaults to +app/controllers+.
+
+* +config.database_configuration_file+ overrides the default path for the database configuration file. Default to +config/database.yml+.
+
+* +config.dependency_loading+ enables or disables dependency loading during the request cycle. Setting dependency_loading to _true_ will allow new classes to be loaded during a request and setting it to _false_ will disable this behavior.
+
+* +config.eager_load_paths+ accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. All elements of this array must also be in +load_paths+.
+
+* +config.frameworks+ accepts an array of rails framework components that should be loaded. (Defaults to +:active_record+, +:action_controller+, +:action_view+, +:action_mailer+, and +:active_resource+).
+
+* +config.load_once_paths+ accepts an array of paths from which Rails will automatically load from only once. All elements of this array must also be in +load_paths+.
+
+* +config.load_paths+ accepts an array of additional paths to prepend to the load path. By default, all app, lib, vendor and mock paths are included in this list.
+
+* +config.log_level+ defines the verbosity of the Rails logger. In production mode, this defaults to +:info+. In development mode, it defaults to +:debug+.
+
+* +config.log_path+ overrides the path to the log file to use. Defaults to +log/#{environment}.log+ (e.g. log/development.log or log/production.log).
+
+* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
+
+* +config.metals+ accepts an array used as the metals to load. If this is set to nil, all metals will be loaded in alphabetical order. If this is set to [], no metals will be loaded. Otherwise metals will be loaded in the order specified
+
+* +config.plugin_loader+ overrides the class that handles loading each plugin. Defaults to +Rails::Plugin::Loader+.
+
+* +config.plugin_locators+ overrides the class that handle finding the desired plugins that you‘d like to load for your application. By default it is the +Rails::Plugin::FileSystemLocator+.
+
+* +config.plugin_paths+ overrides the path to the root of the plugins directory. Defaults to +vendor/plugins+.
+
+* +config.plugins+ accepts the list of plugins to load. If this is set to nil, all plugins will be loaded. If this is set to [], no plugins will be loaded. Otherwise, plugins will be loaded in the order specified.
+
+* +config.preload_frameworks+ enables or disables preloading all frameworks at startup.
+
+* +config.reload_plugins+ enables or disables plugin reloading.
+
+* +config.root_path+ configures the root path of the application.
+
+* +config.time_zone+ sets the default time zone for the application and enables time zone awareness for Active Record.
+
+* +config.view_path+ sets the path of the root of an application's views. Defaults to +app/views+.
+
+* +config.whiny_nils+ enables or disabled warnings when an methods of nil are invoked. Defaults to _false_.
+
+h4. Configuring i18n
+
+* +config.i18n.default_locale+ sets the default locale of an application used for i18n. Defaults to +:en+.
+
+* +config.i18n.load_path+ sets the path Rails uses to look for locale files. Defaults to +config/locales/*.{yml,rb}+
+
h4. Configuring Active Record
-<tt>ActiveRecord::Base</tt> includes a variety of configuration options:
+<tt>config.active_record</tt> includes a variety of configuration options:
-* +logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8.x Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling +logger+ on either an ActiveRecord model class or an ActiveRecord model instance. Set to nil to disable logging.
+* +config.active_record.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8.x Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling +logger+ on either an Active Record model class or an Active Record model instance. Set to nil to disable logging.
-* +primary_key_prefix_type+ lets you adjust the naming for primary key columns. By default, Rails assumes that primary key columns are named +id+ (and this configuration option doesn't need to be set.) There are two other choices:
+* +config.active_record.primary_key_prefix_type+ lets you adjust the naming for primary key columns. By default, Rails assumes that primary key columns are named +id+ (and this configuration option doesn't need to be set.) There are two other choices:
** +:table_name+ would make the primary key for the Customer class +customerid+
** +:table_name_with_underscore+ would make the primary key for the Customer class +customer_id+
-* +table_name_prefix+ lets you set a global string to be prepended to table names. If you set this to +northwest_+, then the Customer class will look for +northwest_customers+ as its table. The default is an empty string.
+* +config.active_record.table_name_prefix+ lets you set a global string to be prepended to table names. If you set this to +northwest_+, then the Customer class will look for +northwest_customers+ as its table. The default is an empty string.
-* +table_name_suffix+ lets you set a global string to be appended to table names. If you set this to +_northwest+, then the Customer class will look for +customers_northwest+ as its table. The default is an empty string.
+* +config.active_record.table_name_suffix+ lets you set a global string to be appended to table names. If you set this to +_northwest+, then the Customer class will look for +customers_northwest+ as its table. The default is an empty string.
-* +pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to +true+ (the default), then the Customer class will use the +customers+ table. If set to +false+, then the Customers class will use the +customer+ table.
+* +config.active_record.pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to +true+ (the default), then the Customer class will use the +customers+ table. If set to +false+, then the Customers class will use the +customer+ table.
-* +colorize_logging+ (true by default) specifies whether or not to use ANSI color codes when logging information from ActiveRecord.
+* +config.active_record.colorize_logging+ (true by default) specifies whether or not to use ANSI color codes when logging information from ActiveRecord.
-* +default_timezone+ determines whether to use +Time.local+ (if set to +:local+) or +Time.utc+ (if set to +:utc+) when pulling dates and times from the database. The default is +:local+.
+* +config.active_record.default_timezone+ determines whether to use +Time.local+ (if set to +:local+) or +Time.utc+ (if set to +:utc+) when pulling dates and times from the database. The default is +:local+.
-* +schema_format+ controls the format for dumping the database schema to a file. The options are +:ruby+ (the default) for a database-independent version that depends on migrations, or +:sql+ for a set of (potentially database-dependent) SQL statements.
+* +config.active_record.schema_format+ controls the format for dumping the database schema to a file. The options are +:ruby+ (the default) for a database-independent version that depends on migrations, or +:sql+ for a set of (potentially database-dependent) SQL statements.
-* +timestamped_migrations+ controls whether migrations are numbered with serial integers or with timestamps. The default is +true+, to use timestamps, which are preferred if there are multiple developers working on the same application.
+* +config.active_record.timestamped_migrations+ controls whether migrations are numbered with serial integers or with timestamps. The default is +true+, to use timestamps, which are preferred if there are multiple developers working on the same application.
-* +lock_optimistically+ controls whether ActiveRecord will use optimistic locking. By default this is +true+.
+* +config.active_record.lock_optimistically+ controls whether ActiveRecord will use optimistic locking. By default this is +true+.
The MySQL adapter adds one additional configuration option:
@@ -70,79 +125,81 @@ The MySQL adapter adds one additional configuration option:
The schema dumper adds one additional configuration option:
-* +ActiveRecord::SchemaDumper.ignore_tables+ accepts an array of tables that should _not_ be included in any generated schema file. This setting is ignored unless +ActiveRecord::Base.schema_format == :ruby+.
+* +ActiveRecord::SchemaDumper.ignore_tables+ accepts an array of tables that should _not_ be included in any generated schema file. This setting is ignored unless +config.active_record.schema_format == :ruby+.
h4. Configuring Action Controller
-<tt>ActionController::Base</tt> includes a number of configuration settings:
+<tt>config.action_controller</tt> includes a number of configuration settings:
-* +asset_host+ provides a string that is prepended to all of the URL-generating helpers in +AssetHelper+. This is designed to allow moving all javascript, CSS, and image files to a separate asset host.
+* +config.action_controller.asset_host+ provides a string that is prepended to all of the URL-generating helpers in +AssetHelper+. This is designed to allow moving all javascript, CSS, and image files to a separate asset host.
-* +consider_all_requests_local+ is generally set to +true+ during development and +false+ during production; if it is set to +true+, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to +false+ and implement +local_request?+ to specify which requests should provide debugging information on errors.
+* +config.action_controller.consider_all_requests_local+ is generally set to +true+ during development and +false+ during production; if it is set to +true+, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to +false+ and implement +local_request?+ to specify which requests should provide debugging information on errors.
-* +allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Instead, you should simply call +config.threadsafe!+ inside your +production.rb+ file, which makes all the necessary adjustments.
+* +config.action_controller.allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Instead, you should simply call +config.threadsafe!+ inside your +production.rb+ file, which makes all the necessary adjustments.
WARNING: Threadsafe operation in incompatible with the normal workings of development mode Rails. In particular, automatic dependency loading and class reloading are automatically disabled when you call +config.threadsafe!+.
-* +param_parsers+ provides an array of handlers that can extract information from incoming HTTP requests and add it to the +params+ hash. By default, parsers for multipart forms, URL-encoded forms, XML, and JSON are active.
+* +config.action_controller.param_parsers+ provides an array of handlers that can extract information from incoming HTTP requests and add it to the +params+ hash. By default, parsers for multipart forms, URL-encoded forms, XML, and JSON are active.
+
+* +config.action_controller.default_charset+ specifies the default character set for all renders. The default is "utf-8".
-* +default_charset+ specifies the default character set for all renders. The default is "utf-8".
+* +config.action_controller.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
-* +logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
+* +config.action_controller.resource_action_separator+ gives the token to be used between resources and actions when building or interpreting RESTful URLs. By default, this is "/".
-* +resource_action_separator+ gives the token to be used between resources and actions when building or interpreting RESTful URLs. By default, this is "/".
+* +config.action_controller.resource_path_names+ is a hash of default names for several RESTful actions. By default, the new action is named +new+ and the edit action is named +edit+.
-* +resource_path_names+ is a hash of default names for several RESTful actions. By default, the new action is named +new+ and the edit action is named +edit+.
+* +config.action_controller.request_forgery_protection_token+ sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ sets it to +:authenticity_token+ by default.
-* +request_forgery_protection_token+ sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ sets it to +:authenticity_token+ by default.
+* +config.action_controller.optimise_named_routes+ turns on some optimizations in generating the routing table. It is set to +true+ by default.
-* +optimise_named_routes+ turns on some optimizations in generating the routing table. It is set to +true+ by default.
+* +config.action_controller.use_accept_header+ sets the rules for determining the response format. If this is set to +true+ (the default) then +respond_to+ and +Request#format+ will take the Accept header into account. If it is set to false then the request format will be determined solely by examining +params[:format]+. If there is no +format+ parameter, then the response format will be either HTML or Javascript depending on whether the request is an AJAX request.
-* +use_accept_header+ sets the rules for determining the response format. If this is set to +true+ (the default) then +respond_to+ and +Request#format+ will take the Accept header into account. If it is set to false then the request format will be determined solely by examining +params[:format]+. If there is no +format+ parameter, then the response format will be either HTML or Javascript depending on whether the request is an AJAX request.
+* +config.action_controller.allow_forgery_protection+ enables or disables CSRF protection. By default this is +false+ in test mode and +true+ in all other modes.
-* +allow_forgery_protection+ enables or disables CSRF protection. By default this is +false+ in test mode and +true+ in all other modes.
+* +config.action_controller.relative_url_root+ can be used to tell Rails that you are deploying to a subdirectory. The default is +ENV['RAILS_RELATIVE_URL_ROOT']+.
-* +relative_url_root+ can be used to tell Rails that you are deploying to a subdirectory. The default is +ENV['RAILS_RELATIVE_URL_ROOT']+.
+* +config.action_controller.session_store+ sets the name of the store for session data. The default is +:cookie_store+; other valid options include +:active_record_store+, +:mem_cache_store+ or the name of your own custom class.
The caching code adds two additional settings:
-* +ActionController::Caching::Pages.page_cache_directory+ sets the directory where Rails will create cached pages for your web server. The default is +Rails.public_path+ (which is usually set to +RAILS_ROOT + "/public"+).
+* +ActionController::Base.page_cache_directory+ sets the directory where Rails will create cached pages for your web server. The default is +Rails.public_path+ (which is usually set to +RAILS_ROOT + "/public"+).
-* +ActionController::Caching::Pages.page_cache_extension+ sets the extension to be used when generating pages for the cache (this is ignored if the incoming request already has an extension). The default is +.html+.
+* +ActionController::Base.page_cache_extension+ sets the extension to be used when generating pages for the cache (this is ignored if the incoming request already has an extension). The default is +.html+.
-The dispatcher includes one setting:
+The Active Record session store can also be configured:
-* +ActionController::Dispatcher.error_file_path+ gives the path where Rails will look for error files such as +404.html+. The default is +Rails.public_path+.
+* +ActiveRecord::SessionStore::Session.table_name+ sets the name of the table uses to store sessions. Defaults to +sessions+.
-The Active Record session store can also be configured:
+* +ActiveRecord::SessionStore::Session.primary_key+ sets the name of the ID column uses in the sessions table. Defaults to +session_id+.
-* +CGI::Session::ActiveRecordStore::Session.data_column_name+ sets the name of the column to use to store session data. By default it is 'data'
+* +ActiveRecord::SessionStore::Session.data_column_name+ sets the name of the column which stores marshaled session data. Defaults to +data+.
h4. Configuring Action View
There are only a few configuration options for Action View, starting with four on +ActionView::Base+:
-* +debug_rjs+ specifies whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it). The default is +false+.
+* +config.action_view.debug_rjs+ specifies whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it). The default is +false+.
-* +warn_cache_misses+ tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is +false+.
+* +config.action_view.warn_cache_misses+ tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is +false+.
-* +field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>" }</tt>
+* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>" }</tt>
-* +default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
+* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
-The ERB template handler supplies one additional option:
+* +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
-* +ActionView::TemplateHandlers::ERB.erb_trim_mode+ gives the trim mode to be used by ERB. It defaults to +'-'+. See the "ERB documentation":http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/ for more information.
+* +config.action_view.erb_trim_mode+ gives the trim mode to be used by ERB. It defaults to +'-'+. See the "ERB documentation":http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/ for more information.
h4. Configuring Action Mailer
-There are a number of settings available on +ActionMailer::Base+:
+There are a number of settings available on +config.action_mailer+:
-* +template_root+ gives the root folder for Action Mailer templates.
+* +config.action_mailer.template_root+ gives the root folder for Action Mailer templates.
-* +logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
+* +config.action_mailer.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
-* +smtp_settings+ allows detailed configuration for the +:smtp+ delivery method. It accepts a hash of options, which can include any of these options:
+* +config.action_mailer.smtp_settings+ allows detailed configuration for the +:smtp+ delivery method. It accepts a hash of options, which can include any of these options:
** +:address+ - Allows you to use a remote mail server. Just change it from its default "localhost" setting.
** +:port+ - On the off chance that your mail server doesn't run on port 25, you can change it.
** +:domain+ - If you need to specify a HELO domain, you can do it here.
@@ -150,48 +207,46 @@ There are a number of settings available on +ActionMailer::Base+:
** +:password+ - If your mail server requires authentication, set the password in this setting.
** +:authentication+ - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of +:plain+, +:login+, +:cram_md5+.
-* +sendmail_settings+ allows detailed configuration for the +sendmail+ delivery method. It accepts a hash of options, which can include any of these options:
+* +config.action_mailer.sendmail_settings+ allows detailed configuration for the +sendmail+ delivery method. It accepts a hash of options, which can include any of these options:
** +:location+ - The location of the sendmail executable. Defaults to +/usr/sbin/sendmail+.
** +:arguments+ - The command line arguments. Defaults to +-i -t+.
-* +raise_delivery_errors+ specifies whether to raise an error if email delivery cannot be completed. It defaults to +true+.
+* +config.action_mailer.raise_delivery_errors+ specifies whether to raise an error if email delivery cannot be completed. It defaults to +true+.
-* +delivery_method+ defines the delivery method. The allowed values are +:smtp+ (default), +:sendmail+, and +:test+.
+* +config.action_mailer.delivery_method+ defines the delivery method. The allowed values are +:smtp+ (default), +:sendmail+, and +:test+.
-* +perform_deliveries+ specifies whether mail will actually be delivered. By default this is +true+; it can be convenient to set it to +false+ for testing.
+* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered. By default this is +true+; it can be convenient to set it to +false+ for testing.
-* +default_charset+ tells Action Mailer which character set to use for the body and for encoding the subject. It defaults to +utf-8+.
+* +config.action_mailer.default_charset+ tells Action Mailer which character set to use for the body and for encoding the subject. It defaults to +utf-8+.
-* +default_content_type+ specifies the default content type used for the main part of the message. It defaults to "text/plain"
+* +config.action_mailer.default_content_type+ specifies the default content type used for the main part of the message. It defaults to "text/plain"
-* +default_mime_version+ is the default MIME version for the message. It defaults to +1.0+.
+* +config.action_mailer.default_mime_version+ is the default MIME version for the message. It defaults to +1.0+.
-* +default_implicit_parts_order+ - When a message is built implicitly (i.e. multiple parts are assembled from templates
+* +config.action_mailer.default_implicit_parts_order+ - When a message is built implicitly (i.e. multiple parts are assembled from templates
which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to +["text/html", "text/enriched", "text/plain"]+. Items that appear first in the array have higher priority in the mail client
and appear last in the mime encoded message.
h4. Configuring Active Resource
-There is a single configuration setting available on +ActiveResource::Base+:
+There is a single configuration setting available on +config.active_resource+:
-<tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Active Resource. Set to nil to disable logging.
+* +config.active_resource.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Active Resource. Set to nil to disable logging.
h4. Configuring Active Support
There are a few configuration options available in Active Support:
+* +config.active_support.escape_html_entities_in_json+ enables or disables the escaping of HTML entities in JSON serialization. Defaults to _true_.
+
+* +config.active_support.use_standard_json_time_format+ enables or disables serializing dates to ISO 8601 format. Defaults to _false_.
+
* +ActiveSupport::BufferedLogger.silencer+ is set to +false+ to disable the ability to silence logging in a block. The default is +true+.
* +ActiveSupport::Cache::Store.logger+ specifies the logger to use within cache store operations.
* +ActiveSupport::Logger.silencer+ is set to +false+ to disable the ability to silence logging in a block. The default is +true+.
-h4. Configuring Active Model
-
-Active Model currently has a single configuration setting:
-
-* +ActiveModel::Errors.default_error_messages+ is an array containing all of the validation error messages.
-
h3. Using Initializers
After it loads the framework plus any gems and plugins in your application, Rails turns to loading initializers. An initializer is any file of ruby code stored under +config/initializers+ in your application. You can use initializers to hold configuration settings that should be made after all of the frameworks and plugins are loaded.
@@ -230,5 +285,6 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/28
+* August 13, 2009: Updated with config syntax and added general configuration options by "John Pignata"
* January 3, 2009: First reasonably complete draft by "Mike Gunderloy":credits.html#mgunderloy
* November 5, 2008: Rough outline by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/contributing_to_rails.textile b/railties/guides/source/contributing_to_rails.textile
index a5912643c0..b20b7d3994 100644
--- a/railties/guides/source/contributing_to_rails.textile
+++ b/railties/guides/source/contributing_to_rails.textile
@@ -14,7 +14,7 @@ endprologue.
h3. Reporting a Rails Issue
-Rails uses a "Lighthouse project":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/ to track issues (primarily bugs and contributions of new code). If you've found a bug in Rails, this is the place to start.
+Rails uses a "Lighthouse project":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/ to track issues (primarily bugs and contributions of new code). If you've found a bug in Rails, this is the place to start. You'll need to create a (free) Lighthouse account in order to comment on issues or to upload tests or patches.
NOTE: Bugs in the most recent released version of Rails are likely to get the most attention. Also, the Rails core team is always interested in feedback from those who can take the time to test _edge Rails_ (the code for the version of Rails that is currently under development). Later in this Guide you'll find out how to get edge Rails for testing.
@@ -32,6 +32,10 @@ h4. Special Treatment for Security Issues
If you've found a security vulnerability in Rails, please do *not* report it via a Lighthouse ticket. Lighthouse tickets are public as soon as they are entered. Instead, you should use the dedicated email address "security@rubyonrails.org":mailto:security@rubyonrails.org to report any vulnerabilities. This alias is monitored and the core team will work with you to quickly and completely address any such vulnerabilities.
+WARNING: Just to emphasize the point, _please do not report security vulnerabilities on public Lighthouse tickets_. This will only expose your fellow Rails developers to needless risks.
+
+You should receive an acknowledgement and detailed response to any reported security issue within 48 hours. If you don't think you're getting adequate response from the security alias, refer to the "Rails security policy page":http://rubyonrails.org/security for direct emails for the current Rails security coordinators.
+
h4. What About Feature Requests?
Please don't put "feature request" tickets into Lighthouse. If there's a new feature that you want to see added to Rails, you'll need to write the code yourself - or convince someone else to partner with you to write the code. Later in this guide you'll find detailed instructions for proposing a patch to Rails. If you enter a wishlist item in Lighthouse with no code, you can expect it to be marked "invalid" as soon as it's reviewed.
@@ -47,6 +51,7 @@ Rails uses git for source code control. You won’t be able to do anything witho
* "Everyday Git":http://www.kernel.org/pub/software/scm/git/docs/everyday.html will teach you just enough about git to get by.
* The "PeepCode screencast":https://peepcode.com/products/git on git ($9) is easier to follow.
* "GitHub":http://github.com/guides/home offers links to a variety of git resources.
+* "Pro Git":http://progit.org/book/ is an entire book about git with a Creative Commons license.
h4. Get the Rails Source Code
@@ -57,9 +62,25 @@ git clone git://github.com/rails/rails.git
cd rails
</shell>
+h4. Pick a Branch
+
+Currently, there is active work being done on both the 2-3-stable branch of Rails and on the master branch (which will become Rails 3.0). If you want to work with the master branch, you're all set. To work with 2.3, you'll need to set up and switch to your own local tracking branch:
+
+<shell>
+git branch --track 2-3-stable origin/2-3-stable
+git checkout 2-3-stable
+</shell>
+
+TIP: You may want to "put your git branch name in your shell prompt":http://github.com/guides/put-your-git-branch-name-in-your-shell-prompt to make it easier to remember which version of the code you're working with.
+
h4. Set up and Run the Tests
-All of the Rails tests must pass with any code you submit, otherwise you have no chance of getting code accepted. This means you need to be able to run the tests. For the tests that touch the database, this means creating the databases. If you're using MySQL:
+All of the Rails tests must pass with any code you submit, otherwise you have no chance of getting code accepted. This means you need to be able to run the tests. Rails needs the +mocha+ gem for running some tests, so install it with:
+<shell>
+gem install mocha
+</shell>
+
+For the tests that touch the database, this means creating the databases. If you're using MySQL:
<shell>
mysql> create database activerecord_unittest;
@@ -79,7 +100,7 @@ rake test_sqlite3
rake test_sqlite3 TEST=test/cases/validations_test.rb
</shell>
-You can change +sqlite3+ with +jdbcmysql+, +jdbcsqlite3+, +jdbcpostgresql+, +mysql+ or +postgresql+. Check out the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/ci_build.rb+ to see the test suite that the Rails continuous integration server runs.
+You can replace +sqlite3+ with +jdbcmysql+, +jdbcsqlite3+, +jdbcpostgresql+, +mysql+ or +postgresql+. Check out the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/ci_build.rb+ to see the test suite that the Rails continuous integration server runs.
@@ -132,7 +153,7 @@ h3. Contributing to the Rails Documentation
Another area where you can help out if you're not yet ready to take the plunge to writing Rails core code is with Rails documentation. You can help with the Rails Guides or the Rails API documentation.
-TIP: "docrails":http://github.com/lifo/docrails/tree/master is the documentation branch for Rails with an *open commit policy*. You can simply PM "lifo":http://github.com/lifo on Github and ask for the commit rights. Documentation changes made as part of the "docrails":http://github.com/lifo/docrails/tree/master project, are merged back to the Rails master code from time to time. Check out the "original announcement":http://weblog.rubyonrails.org/2008/5/2/help-improve-rails-documentation-on-git-branch for more details.
+TIP: "docrails":http://github.com/lifo/docrails/tree/master is the documentation branch for Rails with an *open commit policy*. You can simply PM "lifo":http://github.com/lifo on Github and ask for the commit rights. Documentation changes made as part of the "docrails":http://github.com/lifo/docrails/tree/master project are merged back to the Rails master code from time to time. Check out the "original announcement":http://weblog.rubyonrails.org/2008/5/2/help-improve-rails-documentation-on-git-branch for more details.
h4. The Rails Guides
@@ -188,6 +209,8 @@ h4. Sanity Check
You should not be the only person who looks at the code before you submit it. You know at least one other Rails developer, right? Show them what you’re doing and ask for feedback. Doing this in private before you push a patch out publicly is the “smoke test” for a patch: if you can’t convince one other developer of the beauty of your code, you’re unlikely to convince the core team either.
+You might also want to check out the "RailsBridge BugMash":http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash as a way to get involved in a group effort to improve Rails. This can help you get started and help check your code when you're writing your first patches.
+
h4. Commit Your Changes
When you're happy with the code on your computer, you need to commit the changes to git:
@@ -243,6 +266,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/64
+* August 1, 2009: Updates/amplifications by "Mike Gunderloy":credits.html#mgunderloy
* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index 9c0f22724e..94411a560e 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -330,7 +330,7 @@ h4. The Context
When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.
-ruby-debug creates a content when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.
+ruby-debug creates a context when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.
At any time you can call the +backtrace+ command (or its alias +where+) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then +backtrace+ will supply the answer.
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index 5c05648f12..eef221266e 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -51,7 +51,7 @@ A model represents the information (data) of the application and the rules to ma
h5. Views
-Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that performs tasks related solely to the presentation of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.
+Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that perform tasks related solely to the presentation of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.
h5. Controllers
@@ -1052,7 +1052,7 @@ This creates a new +Comment+ object _and_ sets up the +post_id+ field to have th
h4. Building Views
-Because you skipped scaffolding, you'll need to build views for comments "by hand." Invoking +script/generate controller+ will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views.
+Because you skipped scaffolding, you'll need to build views for comments "by hand". Invoking +script/generate controller+ will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views.
The +views/comments/index.html.erb+ view:
diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile
index 545aaa18e0..8d9df9e6ef 100644
--- a/railties/guides/source/rails_on_rack.textile
+++ b/railties/guides/source/rails_on_rack.textile
@@ -71,7 +71,7 @@ run ActionController::Dispatcher.new
And start the server:
<shell>
-[lifo@null application]$ rackup
+[lifo@null application]$ rackup config.ru
</shell>
To find out more about different +rackup+ options:
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index 8318146ed3..c7b475899f 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -162,7 +162,7 @@ require 'test_helper'
class PostTest < ActiveSupport::TestCase
# Replace this with your real tests.
- def test_truth
+ test "the truth" do
assert true
end
end
@@ -186,7 +186,17 @@ The +PostTest+ class defines a _test case_ because it inherits from +ActiveSuppo
def test_truth
</ruby>
-Any method defined within a test case that begins with +test+ (case sensitive) is simply called a test. So, +test_password+, +test_valid_password+ and +testValidPassword+ all are legal test names and are run automatically when the test case is run.
+Any method defined within a +Test::Unit+ test case that begins with +test+ (case sensitive) is simply called a test. So, +test_password+, +test_valid_password+ and +testValidPassword+ all are legal test names and are run automatically when the test case is run.
+
+Rails adds a +test+ method that takes a test name and a block. It generates a normal +Test::Unit+ test with method names prefixed with +test_+.
+
+<ruby>
+test "the truth" do
+ # ...
+end
+</ruby>
+
+This makes test names more readable by replacing underscores with regular language.
<ruby>
assert true
@@ -262,7 +272,7 @@ The +.+ (dot) above indicates a passing test. When a test fails you see an +F+;
To see how a test failure is reported, you can add a failing test to the +post_test.rb+ test case.
<ruby>
-def test_should_not_save_post_without_title
+test "should not save post without title" do
post = Post.new
assert !post.save
end
@@ -272,16 +282,13 @@ Let us run this newly added test.
<pre>
$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
-Loaded suite unit/post_test
+Loaded suite -e
Started
F
-Finished in 0.197094 seconds.
+Finished in 0.102072 seconds.
1) Failure:
-test_should_not_save_post_without_title(PostTest)
- [unit/post_test.rb:11:in `test_should_not_save_post_without_title'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
+test_should_not_save_post_without_title(PostTest) [/test/unit/post_test.rb:6]:
<false> is not true.
1 tests, 1 assertions, 1 failures, 0 errors
@@ -290,7 +297,7 @@ test_should_not_save_post_without_title(PostTest)
In the output, +F+ denotes a failure. You can see the corresponding trace shown under +1)+ along with the name of the failing test. The next few lines contain the stack trace followed by a message which mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable every assertion provides an optional message parameter, as shown here:
<ruby>
-def test_should_not_save_post_without_title
+test "should not save post without title" do
post = Post.new
assert !post.save, "Saved the post without a title"
end
@@ -299,21 +306,10 @@ end
Running this test shows the friendlier assertion message:
<pre>
-$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
-Loaded suite unit/post_test
-Started
-F
-Finished in 0.198093 seconds.
-
1) Failure:
-test_should_not_save_post_without_title(PostTest)
- [unit/post_test.rb:11:in `test_should_not_save_post_without_title'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
+test_should_not_save_post_without_title(PostTest) [/test/unit/post_test.rb:6]:
Saved the post without a title.
<false> is not true.
-
-1 tests, 1 assertions, 1 failures, 0 errors
</pre>
Now to get this test to pass we can add a model level validation for the _title_ field.
@@ -343,7 +339,7 @@ TIP: Many Rails developers practice _Test-Driven Development_ (TDD). This is an
To see how an error gets reported, here's a test containing an error:
<ruby>
-def test_should_report_error
+test "should report error" do
# some_undefined_variable is not defined elsewhere in the test case
some_undefined_variable
assert true
@@ -354,18 +350,15 @@ Now you can see even more output in the console from running the tests:
<pre>
$ ruby unit/post_test.rb -n test_should_report_error
-Loaded suite unit/post_test
+Loaded suite -e
Started
E
-Finished in 0.195757 seconds.
+Finished in 0.082603 seconds.
1) Error:
test_should_report_error(PostTest):
-NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x2cc9de8>
- /opt/local/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/test_process.rb:467:in `method_missing'
- unit/post_test.rb:16:in `test_should_report_error'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
- /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run'
+NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x249d354>
+ /test/unit/post_test.rb:6:in `test_should_report_error'
1 tests, 0 assertions, 0 failures, 1 errors
</pre>
@@ -446,7 +439,7 @@ Now that we have used Rails scaffold generator for our +Post+ resource, it has a
Let me take you through one such test, +test_should_get_index+ from the file +posts_controller_test.rb+.
<ruby>
-def test_should_get_index
+test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:posts)
@@ -479,7 +472,7 @@ NOTE: If you try running +test_should_create_post+ test from +posts_controller_t
Let us modify +test_should_create_post+ test in +posts_controller_test.rb+ so that all our test pass:
<ruby>
-def test_should_create_post
+test "should create post" do
assert_difference('Post.count') do
post :create, :post => { :title => 'Some title'}
end
@@ -535,7 +528,7 @@ h4. A Fuller Functional Test Example
Here's another example that uses +flash+, +assert_redirected_to+, and +assert_difference+:
<ruby>
-def test_should_create_post
+test "should create post" do
assert_difference('Post.count') do
post :create, :post => { :title => 'Hi', :body => 'This is my first post.'}
end
@@ -625,7 +618,7 @@ class UserFlowsTest < ActionController::IntegrationTest
# fixtures :your, :models
# Replace this with your real tests.
- def test_truth
+ test "the truth" do
assert true
end
end
@@ -660,7 +653,7 @@ require 'test_helper'
class UserFlowsTest < ActionController::IntegrationTest
fixtures :users
- def test_login_and_browse_site
+ test "login and browse site" do
# login via https
https!
get "/login"
@@ -688,7 +681,7 @@ require 'test_helper'
class UserFlowsTest < ActionController::IntegrationTest
fixtures :users
- def test_login_and_browse_site
+ test "login and browse site" do
# User avs logs in
avs = login(:avs)
@@ -771,12 +764,12 @@ class PostsControllerTest < ActionController::TestCase
@post = nil
end
- def test_should_show_post
+ test "should show post" do
get :show, :id => @post.id
assert_response :success
end
- def test_should_destroy_post
+ test "should destroy post" do
assert_difference('Post.count', -1) do
delete :destroy, :id => @post.id
end
@@ -809,17 +802,17 @@ class PostsControllerTest < ActionController::TestCase
@post = nil
end
- def test_should_show_post
+ test "should show post" do
get :show, :id => @post.id
assert_response :success
end
- def test_should_update_post
+ test "should update post" do
put :update, :id => @post.id, :post => { }
assert_redirected_to post_path(assigns(:post))
end
- def test_should_destroy_post
+ test "should destroy post" do
assert_difference('Post.count', -1) do
delete :destroy, :id => @post.id
end
@@ -841,7 +834,7 @@ h3. Testing Routes
Like everything else in your Rails application, it is recommended that you test your routes. An example test for a route in the default +show+ action of +Posts+ controller above should look like:
<ruby>
-def test_should_route_to_post
+test "should route to post" do
assert_routing '/posts/1', { :controller => "posts", :action => "show", :id => "1" }
end
</ruby>
@@ -883,7 +876,7 @@ require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
tests UserMailer
- def test_invite
+ test "invite" do
@expected.from = 'me@example.com'
@expected.to = 'friend@example.com'
@expected.subject = "You have been invited by #{@expected.from}"
@@ -920,7 +913,7 @@ Functional testing for mailers involves more than just checking that the email b
require 'test_helper'
class UserControllerTest < ActionController::TestCase
- def test_invite_friend
+ test "invite friend" do
assert_difference 'ActionMailer::Base.deliveries.size', +1 do
post :invite_friend, :email => 'friend@example.com'
end