提交 46f30f90 编写于 作者: P Pratik Naik

Merge documentation changes from docrails.

commit 0fc3381a
Author: Xavier Noria <fxn@hashref.com>
Date:   Fri May 16 23:44:51 2008 +0200

    Conventions. Formatting. Revising docs all over the rails.

    This revision encourages the modern resource-oriented form_for usage. In addition corrects some markup and other details.

commit 70e4bcf5
Author: Chris Kampmeier <chris@kampers.net>
Date:   Fri May 16 12:09:46 2008 -0700

    Fix a couple spelling errors in docs

commit 6ea5e420
Author: Chris O'Sullivan <thechrisoshow@gmail.com>
Date:   Fri May 16 16:09:11 2008 +0100

    Added docs about source_type for has_one association

commit a01a0178
Author: miloops <miloops@gmail.com>
Date:   Wed May 14 09:22:39 2008 +0000

    Change migration generator USAGE to explain the timestamped migrations behaviour

commit 4e2bc021
Author: Xavier Noria <fxn@hashref.com>
Date:   Fri May 16 00:43:03 2008 +0200

    minor revision in url_for docs

    Made explicit that RESTful and controller/action styles are not interchangeable, and revised some markup.

commit d6ecce66
Author: Michael Hartl <michael@michaelhartl.com>
Date:   Thu May 15 10:46:40 2008 -0700

    Expanded and updated the link_to documentation

commit b8c46c86
Author: Cody Fauser <cody@jadedpixel.com>
Date:   Wed May 14 09:10:02 2008 -0400

    Improve and cleanup ActionMailer documentation

commit 9546ee29
Author: Yehuda Katz <wycats@gmail.com>
Date:   Mon May 12 23:41:43 2008 -0700

    Add documentation for Inflector.inflections

commit cbd5db8f
Author: Manik Juneja <mjuneja@manik-junejas-computer.local>
Date:   Mon May 12 23:43:31 2008 +0530

    minor changes in railties/README. Added dbconsole introduction

commit 130a280d
Author: Gaurav Sharma <gaurav@norbauer.com>
Date:   Mon May 12 18:00:19 2008 +0530

    adding documentation for cached_attributes

commit 164c9586
Author: TomK32 <tomk32@tomk32.de>
Date:   Mon May 12 10:59:33 2008 +0200

    proper heading for "Example:"

commit 35634feb
Author: Matt Boehlig <thetamind@gmail.com>
Date:   Sun May 11 16:46:07 2008 -0500

    Cleanup whitespace and change_table documentation

commit 80bba28a
Author: Xavier Noria <fxn@hashref.com>
Date:   Sun May 11 02:54:02 2008 +0200

    documented the source annotation extractor

commit e6823bb1
Author: Mike Mondragon <mikemondragon@gmail.com>
Date:   Fri May 9 13:49:56 2008 -0700

    Added additional information about processing email with ActionMailer and the strategy one might want to employ to do so.

commit e6afd8b2
Author: Xavier Noria <fxn@hashref.com>
Date:   Thu May 8 23:49:36 2008 +0200

    corrected and completed docs of increment/decrement/toggle in AR::Base

commit 2fead68b
Author: Austin Putman <austin@emmanuel.local>
Date:   Wed May 7 19:35:46 2008 -0700

    Documented class methods on ActionController::Routing.  These are dangerous, and mostly used for testing.

commit f5b84182
Author: Teflon Ted <github@rudiment.net>
Date:   Wed May 7 16:08:49 2008 -0400

    Added explanation about errant inflections not being patched in the future in order to avoid breaking legacy applications.

commit 370f4f51
Author: Sunny Ripert <negatif@gmail.com>
Date:   Wed May 7 14:00:59 2008 +0200

    Applied list conventions in AR::Base

commit 5bd18429
Author: Sunny Ripert <negatif@gmail.com>
Date:   Wed May 7 13:53:35 2008 +0200

    Renamed Options list to Attributes list whenever they weren't option hashes in AR::Base

commit 2fa628e3
Author: Xavier Noria <fxn@hashref.com>
Date:   Wed May 7 11:52:33 2008 +0200

    revised details in Exceptions section of AR::Base docs

commit d912bd56
Author: Yaroslav Markin <yaroslav@markin.net>
Date:   Wed May 7 13:50:28 2008 +0400

    Add a filter_parameter_logging usage hint to generated ApplicationController.
    This may help to remind the developer to filter sensitive information from application logs.
    Closes #11578

commit f81d771f
Author: Jack Danger Canty <git@6brand.com>
Date:   Tue May 6 23:35:05 2008 -0700

    doc: ActiveRecord::Reflection::AssociationReflection#through_reflection

    Added documentation demonstrating the use of #through_reflection for
    finding intervening reflection objects for HasManyThrough
    and HasOneThrough.

commit ae6b46f0
Author: Cheah Chu Yeow <chuyeow@gmail.com>
Date:   Wed May 7 13:47:41 2008 +0800

    Document AttributeAssignmentError and MultiparameterAssignmentErrors.

commit 8f463550
Author: John Barnette <jbarnette@gmail.com>
Date:   Tue May 6 22:46:44 2008 -0700

    Killing/fixing a bunch of outdated language in the AR README.

commit 284a930a
Author: Jonathan Dance <jd@wuputah.com>
Date:   Tue May 6 14:58:26 2008 -0400

    improvements to the page caching docs

commit 9482da62
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 18:13:40 2008 +0200

    validates_numericality_of() "integer" option really is "only_integer"

commit e9afd679
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 12:11:59 2008 +0200

    Harmonized hash notation in AR::Base

commit 67ebf14a
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 12:06:19 2008 +0200

    Turned options into rdoc-lists in AR::Base

commit 0ec7c0a4
Author: Marshall Huss <mwhuss@Macbook.local>
Date:   Sun May 4 23:21:33 2008 -0400

    Added information of how to set element_name in the case the user has a name confliction with an existing model
Signed-off-by: NPratik Naik <pratiknaik@gmail.com>
上级 345f030c
......@@ -19,8 +19,7 @@ are all set up this way. An example of such a method:
recipients recipient
subject "[Signed up] Welcome #{recipient}"
from "system@loudthinking.com"
body(:recipient => recipient)
body :recipient => recipient
end
The body of the email is created by using an Action View template (regular
......@@ -78,21 +77,26 @@ Example:
end
end
This Mailman can be the target for Postfix. In Rails, you would use the runner like this:
This Mailman can be the target for Postfix or other MTAs. In Rails, you would use the runner in the
trivial case like this:
./script/runner 'Mailman.receive(STDIN.read)'
However, invoking Rails in the runner for each mail to be received is very resource intensive. A single
instance of Rails should be run within a daemon if it is going to be utilized to process more than just
a limited number of email.
== Configuration
The Base class has the full list of configuration options. Here's an example:
ActionMailer::Base.smtp_settings = {
:address=>'smtp.yourserver.com', # default: localhost
:port=>'25', # default: 25
:user_name=>'user',
:password=>'pass',
:authentication=>:plain # :plain, :login or :cram_md5
}
ActionMailer::Base.smtp_settings = {
:address => 'smtp.yourserver.com', # default: localhost
:port => '25', # default: 25
:user_name => 'user',
:password => 'pass',
:authentication => :plain # :plain, :login or :cram_md5
}
== Dependencies
......
......@@ -35,7 +35,7 @@ module ActionMailer #:nodoc:
# * <tt>subject</tt> - The subject of your email. Sets the <tt>Subject:</tt> header.
# * <tt>from</tt> - Who the email you are sending is from. Sets the <tt>From:</tt> header.
# * <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 address. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc</tt> header.
# * <tt>bcc</tt> - Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc:</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>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>.
......@@ -127,11 +127,11 @@ module ActionMailer #:nodoc:
#
# class MyMailer < ActionMailer::Base
# def signup_notification(recipient)
# recipients recipient.email_address_with_name
# subject "New account information"
# body "account" => recipient
# from "system@example.com"
# content_type "text/html" # Here's where the magic happens
# recipients recipient.email_address_with_name
# subject "New account information"
# from "system@example.com"
# body :account => recipient
# content_type "text/html"
# end
# end
#
......@@ -145,6 +145,7 @@ module ActionMailer #:nodoc:
# recipients recipient.email_address_with_name
# subject "New account information"
# from "system@example.com"
# content_type "multipart/alternative"
#
# part :content_type => "text/html",
# :body => render_message("signup-as-html", :account => recipient)
......@@ -167,9 +168,14 @@ module ActionMailer #:nodoc:
# * signup_notification.text.x-yaml.erb
#
# Each would be rendered and added as a separate part to the message,
# with the corresponding content type. The same body hash is passed to
# each template.
# with the corresponding content type. The content type for the entire
# message is automatically set to <tt>multipart/alternative</tt>, which indicates
# that the email contains multiple different representations of the same email
# body. The same body hash is passed to each template.
#
# Implicit template rendering is not performed if any attachments or parts have been added to the email.
# This means that you'll have to manually add each part to the email and set the content type of the email
# to <tt>multipart/alternative</tt>.
#
# = Attachments
#
......@@ -209,12 +215,12 @@ module ActionMailer #:nodoc:
# * <tt>:domain</tt> - If you need to specify a HELO domain, you can do it here.
# * <tt>:user_name</tt> - If your mail server requires authentication, set the username in this setting.
# * <tt>:password</tt> - If your mail server requires authentication, set the password in this setting.
# * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the authentication type here.
# This is a symbol and one of <tt>:plain</tt>, <tt>:login</tt>, <tt>:cram_md5</tt>
# * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the authentication type here.
# This is a symbol and one of <tt>:plain</tt>, <tt>:login</tt>, <tt>:cram_md5</tt>.
#
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method
# * <tt>:location</tt> - The location of the sendmail executable, defaults to "/usr/sbin/sendmail"
# * <tt>:arguments</tt> - The command line arguments
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
# * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
# * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i -t</tt>.
#
# * <tt>raise_delivery_errors</tt> - Whether or not errors should be raised if the email fails to be delivered.
#
......@@ -226,17 +232,17 @@ module ActionMailer #:nodoc:
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with <tt>delivery_method :test</tt>. Most useful
# for unit and functional testing.
#
# * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also
# pick a different charset from inside a method with <tt>@charset</tt>.
# * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also
# pick a different charset from inside a method with +charset+.
# * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You
# can also pick a different content type from inside a method with <tt>@content_type</tt>.
# * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to "1.0". You
# can also pick a different value from inside a method with <tt>@mime_version</tt>.
# can also pick a different content type from inside a method with +content_type+.
# * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to <tt>1.0</tt>. You
# can also pick a different value from inside a method with +mime_version+.
# * <tt>default_implicit_parts_order</tt> - 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
# <tt>["text/html", "text/enriched", "text/plain"]</tt>. Items that appear first in the array have higher priority in the mail client
# and appear last in the mime encoded message. You can also pick a different order from inside a method with
# <tt>@implicit_parts_order</tt>.
# +implicit_parts_order+.
class Base
include AdvAttrAccessor, PartContainer
include ActionController::UrlWriter if Object.const_defined?(:ActionController)
......
......@@ -92,7 +92,7 @@ module InstanceMethods
# with the remaining data.
#
# Note that you can define your own XML parameter parser which would allow you to describe multiple entities
# in a single request (i.e., by wrapping them all in a single root note), but if you just go with the flow
# in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
# and accept Rails' defaults, life will be much easier.
#
# If you need to use a MIME type which isn't supported by default, you can register your own handlers in
......
......@@ -73,30 +73,54 @@ module Helpers
# There are also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,
# link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html
module FormHelper
# Creates a form and a scope around a specific model object that is used as a base for questioning about
# values for the fields.
# Creates a form and a scope around a specific model object that is used as
# a base for questioning about values for the fields.
#
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
# <%= f.error_messages %>
# First name: <%= f.text_field :first_name %>
# Last name : <%= f.text_field :last_name %>
# Biography : <%= f.text_area :biography %>
# Admin? : <%= f.check_box :admin %>
# Rails provides succint resource-oriented form generation with +form_for+
# like this:
#
# <% form_for @offer do |f| %>
# <%= f.label :version, 'Version' %>:
# <%= f.text_field :version %><br />
# <%= f.label :author, 'Author' %>:
# <%= f.text_field :author %><br />
# <% end %>
#
# Worth noting is that the form_for tag is called in a ERb evaluation block, not an ERb output block. So that's <tt><% %></tt>,
# not <tt><%= %></tt>. Also worth noting is that form_for yields a <tt>form_builder</tt> object, in this example as <tt>f</tt>, which emulates
# the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,
# you get away with <tt>f.text_field :name</tt>. Notice that you can even do <tt><%= f.error_messages %></tt> to display the
# error messsages of the model object in question.
# There, +form_for+ is able to generate the rest of RESTful parameters
# based on introspection on the record, but to understand what it does we
# need to dig first into the alternative generic usage it is based upon.
#
# === Generic form_for
#
# Even further, the form_for method allows you to more easily escape the instance variable convention. So while the stand-alone
# approach would require <tt>text_field :person, :name, :object => person</tt>
# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with
# <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>.
# The generic way to call +form_for+ requires a few arguments:
#
# Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods
# and methods from FormTagHelper. For example:
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
# <%= f.error_messages %>
# First name: <%= f.text_field :first_name %><br />
# Last name : <%= f.text_field :last_name %><br />
# Biography : <%= f.text_area :biography %><br />
# Admin? : <%= f.check_box :admin %><br />
# <% end %>
#
# Worth noting is that the +form_for+ tag is called in a ERb evaluation block,
# not an ERb output block. So that's <tt><% %></tt>, not <tt><%= %></tt>. Also
# worth noting is that +form_for+ yields a form builder object, in this
# example as +f+, which emulates the API for the stand-alone FormHelper
# methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,
# you get away with <tt>f.text_field :name</tt>. Notice that you can even do
# <tt><%= f.error_messages %></tt> to display the error messsages of the model
# object in question.
#
# Even further, the +form_for+ method allows you to more easily escape the
# instance variable convention. So while the stand-alone approach would require
# <tt>text_field :person, :name, :object => person</tt> to work with local
# variables instead of instance ones, the +form_for+ calls remain the same.
# You simply declare once with <tt>:person, person</tt> and all subsequent
# field calls save <tt>:person</tt> and <tt>:object => person</tt>.
#
# Also note that +form_for+ doesn't create an exclusive scope. It's still
# possible to use both the stand-alone FormHelper methods and methods from
# FormTagHelper. For example:
#
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
# First name: <%= f.text_field :first_name %>
......@@ -105,22 +129,26 @@ module FormHelper
# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
# <% end %>
#
# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base,
# like FormOptionHelper#collection_select and DateHelper#datetime_select.
# This also works for the methods in FormOptionHelper and DateHelper that are
# designed to work with an object as base, like FormOptionHelper#collection_select
# and DateHelper#datetime_select.
#
# HTML attributes for the form tag can be given as <tt>:html => {...}</tt>. For example:
# HTML attributes for the form tag can be given as <tt>:html => {...}</tt>.
# For example:
#
# <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>
# ...
# <% end %>
#
# The above form will then have the <tt>id</tt> attribute with the value </tt>person_form</tt>, which you can then
# style with CSS or manipulate with JavaScript.
# The above form will then have the +id+ attribute with the value "person_form",
# which you can then style with CSS or manipulate with JavaScript.
#
# === Relying on record identification
#
# In addition to manually configuring the form_for call, you can also rely on record identification, which will use
# the conventions and named routes of that approach. Examples:
# As we said above, in addition to manually configuring the +form_for+ call,
# you can rely on record identification, which will use the conventions and
# named routes of that approach. This is the preferred way to use +form_for+
# nowadays:
#
# <% form_for(@post) do |f| %>
# ...
......@@ -140,7 +168,7 @@ module FormHelper
#
# This will expand to be the same as:
#
# <% form_for :post, @post, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
# <% form_for :post, Post.new, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
# ...
# <% end %>
#
......@@ -150,7 +178,7 @@ module FormHelper
# ...
# <% end %>
#
# And for namespaced routes, like admin_post_url:
# And for namespaced routes, like +admin_post_url+:
#
# <% form_for([:admin, @post]) do |f| %>
# ...
......
......@@ -120,17 +120,72 @@ def url_for(options = {})
# exception.
#
# ==== Examples
# Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
# and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base
# your application on resources and use
#
# link_to "Profile", profile_path(@profile)
# # => <a href="/profiles/1">Profile</a>
#
# or the even pithier
#
# link_to "Profile", @profile
# # => <a href="/profiles/1">Profile</a>
#
# in place of the older more verbose, non-resource-oriented
#
# link_to "Profile", :controller => "profiles", :action => "show", :id => @profile
# # => <a href="/profiles/show/1">Profile</a>
#
# Similarly,
#
# link_to "Profiles", profiles_path
# # => <a href="/profiles">Profiles</a>
#
# is better than
#
# link_to "Profiles", :controller => "profiles"
# # => <a href="/profiles">Profiles</a>
#
# Classes and ids for CSS are easy to produce:
#
# link_to "Articles", articles_path, :id => "news", :class => "article"
# # => <a href="/articles" class="article" id="news">Articles</a>
#
# Be careful when using the older argument style, as an extra literal hash is needed:
#
# link_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"
# # => <a href="/articles" class="article" id="news">Articles</a>
#
# Leaving the hash off gives the wrong link:
#
# link_to "WRONG!", :controller => "articles", :id => "news", :class => "article"
# # => <a href="/articles/index/news?class=article">WRONG!</a>
#
# +link_to+ can also produce links with anchors or query strings:
#
# link_to "Comment wall", profile_path(@profile, :anchor => "wall")
# # => <a href="/profiles/1#wall">Comment wall</a>
#
# link_to "Ruby on Rails search", :controller => "searches", :query => "ruby on rails"
# # => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>
#
# link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux")
# # => <a href="/searches?foo=bar&amp;baz=quux">Nonsense search</a>
#
# The three options specfic to +link_to+ (<tt>:confirm</tt>, <tt>:popup</tt>, and <tt>:method</tt>) are used as follows:
#
# link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?"
# # => <a href="http://www.rubyonrails.org/" onclick="return confirm('Are you sure?');">Visit Other Site</a>
#
# link_to "Help", { :action => "help" }, :popup => true
# # => <a href="/testing/help/" onclick="window.open(this.href);return false;">Help</a>
#
# link_to "View Image", { :action => "view" }, :popup => ['new_window_name', 'height=300,width=600']
# # => <a href="/testing/view/" onclick="window.open(this.href,'new_window_name','height=300,width=600');return false;">View Image</a>
# link_to "View Image", @image, :popup => ['new_window_name', 'height=300,width=600']
# # => <a href="/images/9" onclick="window.open(this.href,'new_window_name','height=300,width=600');return false;">View Image</a>
#
# link_to "Delete Image", { :action => "delete", :id => @image.id }, :confirm => "Are you sure?", :method => :delete
# # => <a href="/testing/delete/9/" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
# link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete
# # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
# f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;
# var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method');
# m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a>
......
......@@ -12,7 +12,7 @@
change_table :videos do |t|
t.timestamps # adds created_at, updated_at
t.belongs_to :goat # add goat_id integer
t.belongs_to :goat # adds goat_id integer
t.string :name, :email, :limit => 20 # adds name and email both with a 20 char limit
t.remove :name, :email # removes the name and email columns
end
......
......@@ -753,6 +753,8 @@ def has_many(association_id, options = {}, &extension)
# * <tt>:source</tt> - Specifies the source association name used by <tt>has_one :through</tt> queries. Only use it if the name cannot be
# inferred from the association. <tt>has_one :favorite, :through => :favorites</tt> will look for a
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
# * <tt>:source_type</tt> - Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
# association is a polymorphic +belongs_to+.
# * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
#
# Option examples:
......
......@@ -16,16 +16,20 @@ def self.included(base)
# Declare and check for suffixed attribute methods.
module ClassMethods
# Declare a method available for all attributes with the given suffix.
# Uses method_missing and respond_to? to rewrite the method
# Declares a method available for all attributes with the given suffix.
# Uses +method_missing+ and <tt>respond_to?</tt> to rewrite the method
#
# #{attr}#{suffix}(*args, &block)
#
# to
#
# attribute#{suffix}(#{attr}, *args, &block)
#
# An attribute#{suffix} instance method must exist and accept at least
# the attr argument.
# An <tt>attribute#{suffix}</tt> instance method must exist and accept at least
# the +attr+ argument.
#
# For example:
#
# class Person < ActiveRecord::Base
# attribute_method_suffix '_changed?'
#
......@@ -60,8 +64,8 @@ def generated_methods?
!generated_methods.empty?
end
# generates all the attribute related methods for columns in the database
# accessors, mutators and query methods
# Generates all the attribute related methods for columns in the database
# accessors, mutators and query methods.
def define_attribute_methods
return if generated_methods?
columns_hash.each do |name, column|
......@@ -89,8 +93,9 @@ def define_attribute_methods
end
end
# Check to see if the method is defined in the model or any of its subclasses that also derive from ActiveRecord.
# Raise DangerousAttributeError if the method is defined by ActiveRecord though.
# Checks whether the method is defined in the model or any of its subclasses
# that also derive from ActiveRecord. Raises DangerousAttributeError if the
# method is defined by Active Record though.
def instance_method_already_implemented?(method_name)
method_name = method_name.to_s
return true if method_name =~ /^id(=$|\?$|$)/
......@@ -104,17 +109,19 @@ def instance_method_already_implemented?(method_name)
# +cache_attributes+ allows you to declare which converted attribute values should
# be cached. Usually caching only pays off for attributes with expensive conversion
# methods, like date columns (e.g. created_at, updated_at).
# methods, like time related columns (e.g. +created_at+, +updated_at+).
def cache_attributes(*attribute_names)
attribute_names.each {|attr| cached_attributes << attr.to_s}
end
# returns the attributes where
# Returns the attributes which are cached. By default time related columns
# with datatype <tt>:datetime, :timestamp, :time, :date</tt> are cached.
def cached_attributes
@cached_attributes ||=
columns.select{|c| attribute_types_cached_by_default.include?(c.type)}.map(&:name).to_set
end
# Returns +true+ if the provided attribute is being cached.
def cache_attribute?(attr_name)
cached_attributes.include?(attr_name)
end
......@@ -210,14 +217,14 @@ def evaluate_attribute_method(attr_name, method_definition, method_name=attr_nam
end # ClassMethods
# Allows access to the object attributes, which are held in the @attributes hash, as though they
# Allows access to the object attributes, which are held in the <tt>@attributes</tt> hash, as though they
# were first-class methods. So a Person class with a name attribute can use Person#name and
# Person#name= and never directly use the attributes hash -- except for multiple assigns with
# ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that
# the completed attribute is not nil or 0.
# the completed attribute is not +nil+ or 0.
#
# It's also possible to instantiate related objects, so a Client class belonging to the clients
# table with a master_id foreign key can instantiate master through Client#master.
# table with a +master_id+ foreign key can instantiate master through Client#master.
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
......@@ -288,7 +295,7 @@ def unserialize_attribute(attr_name)
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float
# columns are turned into nil.
# columns are turned into +nil+.
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
@attributes_cache.delete(attr_name)
......@@ -319,8 +326,9 @@ def query_attribute(attr_name)
end
end
# A Person object with a name attribute can ask person.respond_to?("name"), person.respond_to?("name="), and
# person.respond_to?("name?") which will all return true.
# A Person object with a name attribute can ask <tt>person.respond_to?("name")</tt>,
# <tt>person.respond_to?("name=")</tt>, and <tt>person.respond_to?("name?")</tt>
# which will all return +true+.
alias :respond_to_without_attributes? :respond_to?
def respond_to?(method, include_priv = false)
method_name = method.to_s
......
......@@ -18,11 +18,11 @@ module Format
#
# +name+ is the column's name, as in <tt><b>supplier_id</b> int(11)</tt>.
# +default+ is the type-casted default value, such as <tt>sales_stage varchar(20) default <b>'new'</b></tt>.
# +sql_type+ is only used to extract the column's length, if necessary. For example, <tt>company_name varchar(<b>60</b>)</tt>.
# +sql_type+ is only used to extract the column's length, if necessary. For example, <tt>company_name varchar(<b>60</b>)</tt>.
# +null+ determines if this column allows +NULL+ values.
def initialize(name, default, sql_type = nil, null = true)
@name, @sql_type, @null = name, sql_type, null
@limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type)
@limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type)
@type = simplified_type(sql_type)
@default = extract_default(default)
......@@ -172,7 +172,7 @@ def new_date(year, mon, mday)
def new_time(year, mon, mday, hour, min, sec, microsec)
# Treat 0000-00-00 00:00:00 as nil.
return nil if year.nil? || year == 0
Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
end
......@@ -250,11 +250,11 @@ class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
end
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
def sql_type
base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
end
def to_sql
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key
......@@ -309,39 +309,39 @@ def [](name)
# * <tt>:default</tt> -
# The column's default value. Use nil for NULL.
# * <tt>:null</tt> -
# Allows or disallows +NULL+ values in the column. This option could
# Allows or disallows +NULL+ values in the column. This option could
# have been named <tt>:null_allowed</tt>.
# * <tt>:precision</tt> -
# Specifies the precision for a <tt>:decimal</tt> column.
# Specifies the precision for a <tt>:decimal</tt> column.
# * <tt>:scale</tt> -
# Specifies the scale for a <tt>:decimal</tt> column.
# Specifies the scale for a <tt>:decimal</tt> column.
#
# Please be aware of different RDBMS implementations behavior with
# <tt>:decimal</tt> columns:
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
# <tt>:precision</tt>, and makes no comments about the requirements of
# <tt>:precision</tt>.
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
# Default is (10,0).
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
# <tt>:scale</tt> [0..infinity]. No default.
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
# Internal storage as strings. No default.
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
# but the maximum supported <tt>:precision</tt> is 16. No default.
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
# Default is (38,0).
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
# Default unknown.
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
# Default (9,0). Internal types NUMERIC and DECIMAL have different
# storage rules, decimal being better.
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
# NUMERIC is 19, and DECIMAL is 38.
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# Default (38,0).
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
# Default (38,0).
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
#
......@@ -394,7 +394,7 @@ def [](name)
# t.timestamps
# end
#
# There's a short-hand method for each of the type values declared at the top. And then there's
# There's a short-hand method for each of the type values declared at the top. And then there's
# TableDefinition#timestamps that'll add created_at and updated_at as datetimes.
#
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
......@@ -434,13 +434,13 @@ def column(name, type, options = {})
def #{column_type}(*args)
options = args.extract_options!
column_names = args
column_names.each { |name| column(name, '#{column_type}', options) }
end
EOV
end
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
# <tt>:updated_at</tt> to the table.
def timestamps
column(:created_at, :datetime)
......@@ -458,7 +458,7 @@ def references(*args)
alias :belongs_to :references
# Returns a String whose contents are the column definitions
# concatenated together. This string can then be prepended and appended to
# concatenated together. This string can then be prepended and appended to
# to generate the final SQL to create the table.
def to_sql
@columns * ', '
......@@ -510,15 +510,15 @@ def initialize(table_name, base)
# Adds a new column to the named table.
# See TableDefinition#column for details of the options you can use.
# ===== Examples
# ====== Creating a simple columns
# ===== Example
# ====== Creating a simple column
# t.column(:name, :string)
def column(column_name, type, options = {})
@base.add_column(@table_name, column_name, type, options)
end
# Adds a new index to the table. +column_name+ can be a single Symbol, or
# an Array of Symbols. See SchemaStatements#add_index
# Adds a new index to the table. +column_name+ can be a single Symbol, or
# an Array of Symbols. See SchemaStatements#add_index
#
# ===== Examples
# ====== Creating a simple index
......@@ -531,8 +531,8 @@ def index(column_name, options = {})
@base.add_index(@table_name, column_name, options)
end
# Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#timestamps
# ===== Examples
# Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#add_timestamps
# ===== Example
# t.timestamps
def timestamps
@base.add_timestamps(@table_name)
......@@ -547,7 +547,7 @@ def change(column_name, type, options = {})
@base.change_column(@table_name, column_name, type, options)
end
# Sets a new default value for a column. See
# Sets a new default value for a column. See SchemaStatements#change_column_default
# ===== Examples
# t.change_default(:qualification, 'new')
# t.change_default(:authorized, 1)
......@@ -559,27 +559,27 @@ def change_default(column_name, default)
# ===== Examples
# t.remove(:qualification)
# t.remove(:qualification, :experience)
# t.removes(:qualification, :experience)
def remove(*column_names)
@base.remove_column(@table_name, column_names)
end
# Remove the given index from the table.
# Removes the given index from the table.
#
# Remove the suppliers_name_index in the suppliers table.
# ===== Examples
# ====== Remove the suppliers_name_index in the suppliers table
# t.remove_index :name
# Remove the index named accounts_branch_id_index in the accounts table.
# ====== Remove the index named accounts_branch_id_index in the accounts table
# t.remove_index :column => :branch_id
# Remove the index named accounts_branch_id_party_id_index in the accounts table.
# ====== Remove the index named accounts_branch_id_party_id_index in the accounts table
# t.remove_index :column => [:branch_id, :party_id]
# Remove the index named by_branch_party in the accounts table.
# ====== Remove the index named by_branch_party in the accounts table
# t.remove_index :name => :by_branch_party
def remove_index(options = {})
@base.remove_index(@table_name, options)
end
# Removes the timestamp columns (created_at and updated_at) from the table.
# ===== Examples
# ===== Example
# t.remove_timestamps
def remove_timestamps
@base.remove_timestamps(@table_name)
......@@ -592,12 +592,11 @@ def rename(column_name, new_column_name)
@base.rename_column(@table_name, column_name, new_column_name)
end
# Adds a reference. Optionally adds a +type+ column. <tt>reference</tt>,
# <tt>references</tt> and <tt>belongs_to</tt> are all acceptable
# ===== Example
# Adds a reference. Optionally adds a +type+ column.
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
# ===== Examples
# t.references(:goat)
# t.references(:goat, :polymorphic => true)
# t.references(:goat)
# t.belongs_to(:goat)
def references(*args)
options = args.extract_options!
......@@ -609,12 +608,11 @@ def references(*args)
end
alias :belongs_to :references
# Adds a reference. Optionally removes a +type+ column. <tt>remove_reference</tt>,
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are all acceptable
# ===== Example
# t.remove_reference(:goat)
# t.remove_reference(:goat, :polymorphic => true)
# Removes a reference. Optionally removes a +type+ column.
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
# ===== Examples
# t.remove_references(:goat)
# t.remove_references(:goat, :polymorphic => true)
# t.remove_belongs_to(:goat)
def remove_references(*args)
options = args.extract_options!
......@@ -627,7 +625,7 @@ def remove_references(*args)
alias :remove_belongs_to :remove_references
# Adds a column or columns of a specified type
# ===== Example
# ===== Examples
# t.string(:goat)
# t.string(:goat, :sheep)
%w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
......
......@@ -13,7 +13,7 @@ def table_alias_length
255
end
# Truncates a table alias according to the limits of the current adapter.
# Truncates a table alias according to the limits of the current adapter.
def table_alias_for(table_name)
table_name[0..table_alias_length-1].gsub(/\./, '_')
end
......@@ -152,7 +152,7 @@ def create_table(table_name, options = {})
# t.remove :company
# end
#
# ====== Remove a column
# ====== Remove several columns
# change_table(:suppliers) do |t|
# t.remove :company_id
# t.remove :width, :height
......@@ -168,7 +168,7 @@ def create_table(table_name, options = {})
def change_table(table_name)
yield Table.new(table_name, self)
end
# Renames a table.
# ===== Example
# rename_table('octopuses', 'octopi')
......@@ -199,7 +199,7 @@ def remove_column(table_name, *column_names)
end
end
alias :remove_columns :remove_column
# Changes the column's definition according to the new options.
# See TableDefinition#column for details of the options you can use.
# ===== Examples
......@@ -389,7 +389,7 @@ def add_column_options!(sql, options) #:nodoc:
def distinct(columns, order_by)
"DISTINCT #{columns}"
end
# ORDER BY clause for the passed order option.
# PostgreSQL overrides this due to its stricter standards compliance.
def add_order_by_for_association_limiting!(sql, options)
......@@ -401,17 +401,17 @@ def add_order_by_for_association_limiting!(sql, options)
# add_timestamps(:suppliers)
def add_timestamps(table_name)
add_column table_name, :created_at, :datetime
add_column table_name, :updated_at, :datetime
add_column table_name, :updated_at, :datetime
end
# Removes the timestamp columns (created_at and updated_at) from the table definition.
# ===== Examples
# remove_timestamps(:suppliers)
def remove_timestamps(table_name)
remove_column table_name, :updated_at
remove_column table_name, :created_at
remove_column table_name, :updated_at
remove_column table_name, :created_at
end
protected
def options_include_default?(options)
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
......
class Module
# Declare an attribute reader backed by an internally-named instance variable.
# Declares an attribute reader backed by an internally-named instance variable.
def attr_internal_reader(*attrs)
attrs.each do |attr|
module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end"
end
end
# Declare an attribute writer backed by an internally-named instance variable.
# Declares an attribute writer backed by an internally-named instance variable.
def attr_internal_writer(*attrs)
attrs.each do |attr|
module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end"
end
end
# Declare an attribute reader and writer backed by an internally-named instance
# Declares an attribute reader and writer backed by an internally-named instance
# variable.
def attr_internal_accessor(*attrs)
attr_internal_reader(*attrs)
......
......@@ -15,10 +15,9 @@ def self.included(base) #:nodoc:
end
# Gives a human readable format of the range.
#
# Example:
# ==== Example:
#
# >> [1..100].to_formatted_s
# => "1..100"
# [1..100].to_formatted_s # => "1..100"
def to_formatted_s(format = :default)
RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s
end
......
......@@ -92,6 +92,13 @@ def clear(scope = :all)
extend self
# Yields a singleton instance of Inflector::Inflections so you can specify additional
# inflector rules.
#
# Example:
# Inflector.inflections do |inflect|
# inflect.uncountable "rails"
# end
def inflections
if block_given?
yield Inflections.instance
......
......@@ -145,7 +145,9 @@ and also on programming in general.
Debugger support is available through the debugger command when you start your Mongrel or
Webrick server with --debugger. This means that you can break out of execution at any point
in the code, investigate and change the model, AND then resume execution! Example:
in the code, investigate and change the model, AND then resume execution!
You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'
Example:
class WeblogController < ActionController::Base
def index
......@@ -183,6 +185,13 @@ Passing an argument will specify a different environment, like <tt>script/consol
To reload your controllers and models after launching the console run <tt>reload!</tt>
== dbconsole
You can go to the command line of your database directly through <tt>script/dbconsole</tt>.
You would be connected to the database with the credentials defined in database.yml.
Starting the script without arguments will connect you to the development database. Passing an
argument will connect you to a different database, like <tt>script/dbconsole production</tt>.
Currently works for mysql, postgresql and sqlite.
== Description of Contents
......@@ -200,13 +209,13 @@ app/models
app/views
Holds the template files for the view that should be named like
weblogs/index.erb for the WeblogsController#index action. All views use eRuby
weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby
syntax.
app/views/layouts
Holds the template files for layouts to be used with views. This models the common
header/footer method of wrapping views. In your views, define a layout using the
<tt>layout :default</tt> and create a file named default.erb. Inside default.erb,
<tt>layout :default</tt> and create a file named default.html.erb. Inside default.html.erb,
call <% yield %> to render the view using this layout.
app/helpers
......@@ -243,4 +252,5 @@ test
vendor
External libraries that the application depends on. Also includes the plugins subdirectory.
If the app has frozen rails, those gems also go here, under vendor/rails/.
This directory is in the load path.
# These settins change the behavior of Rails 2 apps and will be defaults
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
# Only save the attributes that have changed since the record was loaded.
......
......@@ -2,7 +2,7 @@ Description:
Stubs out a new database migration. Pass the migration name, either
CamelCased or under_scored, and an optional list of attribute pairs as arguments.
A migration class is generated in db/migrate prefixed by the latest migration number.
A migration class is generated in db/migrate prefixed by a timestamp of the current date and time.
You can name your migration in either of these formats to generate add/remove
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
......@@ -10,12 +10,12 @@ Description:
Example:
`./script/generate migration AddSslFlag`
With 4 existing migrations, this creates the AddSslFlag migration in
db/migrate/005_add_ssl_flag.rb
If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
db/migrate/20080514090912_add_ssl_flag.rb
`./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
This will create the AddTitleBodyToPost in db/migrate/005_add_title_body_to_post.rb with
This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with
this in the Up migration:
add_column :posts, :title, :string
......
# Implements the logic behind the rake tasks for annotations like
#
# rake notes
# rake notes:optimize
#
# and friends. See <tt>rake -T notes</tt> and <tt>railties/lib/tasks/annotations.rake</tt>.
#
# Annotation objects are triplets <tt>:line</tt>, <tt>:tag</tt>, <tt>:text</tt> that
# represent the line where the annotation lives, its tag, and its text. Note
# the filename is not stored.
#
# Annotations are looked for in comments and modulus whitespace they have to
# start with the tag optionally followed by a colon. Everything up to the end
# of the line (or closing ERb comment tag) is considered to be their text.
class SourceAnnotationExtractor
class Annotation < Struct.new(:line, :tag, :text)
# Returns a representation of the annotation that looks like this:
#
# [126] [TODO] This algorithm is simple and clearly correct, make it faster.
#
# If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above.
# Otherwise the string contains just line and text.
def to_s(options={})
s = "[%3d] " % line
s << "[#{tag}] " if options[:tag]
......@@ -7,6 +28,12 @@ def to_s(options={})
end
end
# Prints all annotations with tag +tag+ under the root directories +app+, +lib+,
# and +test+ (recursively). Only filenames with extension +.builder+, +.rb+,
# +.rxml+, +.rjs+, +.rhtml+, or +.erb+ are taken into account. The +options+
# hash is passed to each annotation's +to_s+.
#
# This class method is the single entry point for the rake tasks.
def self.enumerate(tag, options={})
extractor = new(tag)
extractor.display(extractor.find, options)
......@@ -18,10 +45,18 @@ def initialize(tag)
@tag = tag
end
# Returns a hash that maps filenames under +dirs+ (recursively) to arrays
# with their annotations. Only files with annotations are included, and only
# those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+
# are taken into account.
def find(dirs=%w(app lib test))
dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
end
# Returns a hash that maps filenames under +dir+ (recursively) to arrays
# with their annotations. Only files with annotations are included, and only
# those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+
# are taken into account.
def find_in(dir)
results = {}
......@@ -40,6 +75,9 @@ def find_in(dir)
results
end
# If +file+ is the filename of a file that contains annotations this method returns
# a hash with a single entry that maps +file+ to an array of its annotations.
# Otherwise it returns an empty hash.
def extract_annotations_from(file, pattern)
lineno = 0
result = File.readlines(file).inject([]) do |list, line|
......@@ -50,6 +88,8 @@ def extract_annotations_from(file, pattern)
result.empty? ? {} : { file => result }
end
# Prints the mapping from filenames to annotations in +results+ ordered by filename.
# The +options+ hash is passed to each annotation's +to_s+.
def display(results, options={})
results.keys.sort.each do |file|
puts "#{file}:"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册