mirror of https://github.com/rails/rails
Merge documentation changes from docrails.
commit0fc3381aa5
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. commit70e4bcf5cb
Author: Chris Kampmeier <chris@kampers.net> Date: Fri May 16 12:09:46 2008 -0700 Fix a couple spelling errors in docs commit6ea5e4208f
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 commita01a0178be
Author: miloops <miloops@gmail.com> Date: Wed May 14 09:22:39 2008 +0000 Change migration generator USAGE to explain the timestamped migrations behaviour commit4e2bc02163
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. commitd6ecce66f4
Author: Michael Hartl <michael@michaelhartl.com> Date: Thu May 15 10:46:40 2008 -0700 Expanded and updated the link_to documentation commitb8c46c86f0
Author: Cody Fauser <cody@jadedpixel.com> Date: Wed May 14 09:10:02 2008 -0400 Improve and cleanup ActionMailer documentation commit9546ee2999
Author: Yehuda Katz <wycats@gmail.com> Date: Mon May 12 23:41:43 2008 -0700 Add documentation for Inflector.inflections commitcbd5db8f51
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 commit130a280dde
Author: Gaurav Sharma <gaurav@norbauer.com> Date: Mon May 12 18:00:19 2008 +0530 adding documentation for cached_attributes commit164c958648
Author: TomK32 <tomk32@tomk32.de> Date: Mon May 12 10:59:33 2008 +0200 proper heading for "Example:" commit35634feb47
Author: Matt Boehlig <thetamind@gmail.com> Date: Sun May 11 16:46:07 2008 -0500 Cleanup whitespace and change_table documentation commit80bba28a1a
Author: Xavier Noria <fxn@hashref.com> Date: Sun May 11 02:54:02 2008 +0200 documented the source annotation extractor commite6823bb165
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. commite6afd8b273
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 commit2fead68b31
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. commitf5b84182db
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. commit370f4f5172
Author: Sunny Ripert <negatif@gmail.com> Date: Wed May 7 14:00:59 2008 +0200 Applied list conventions in AR::Base commit5bd18429f0
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 commit2fa628e34b
Author: Xavier Noria <fxn@hashref.com> Date: Wed May 7 11:52:33 2008 +0200 revised details in Exceptions section of AR::Base docs commitd912bd5672
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 commitf81d771f06
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. commitae6b46f00b
Author: Cheah Chu Yeow <chuyeow@gmail.com> Date: Wed May 7 13:47:41 2008 +0800 Document AttributeAssignmentError and MultiparameterAssignmentErrors. commit8f463550b5
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. commit284a930a93
Author: Jonathan Dance <jd@wuputah.com> Date: Tue May 6 14:58:26 2008 -0400 improvements to the page caching docs commit9482da6213
Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 18:13:40 2008 +0200 validates_numericality_of() "integer" option really is "only_integer" commite9afd6790a
Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 12:11:59 2008 +0200 Harmonized hash notation in AR::Base commit67ebf14a91
Author: Sunny Ripert <negatif@gmail.com> Date: Mon May 5 12:06:19 2008 +0200 Turned options into rdoc-lists in AR::Base commit0ec7c0a41d
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: Pratik Naik <pratiknaik@gmail.com>
This commit is contained in:
parent
345f030c5b
commit
46f30f902f
|
@ -19,8 +19,7 @@ are all set up this way. An example of such a method:
|
||||||
recipients recipient
|
recipients recipient
|
||||||
subject "[Signed up] Welcome #{recipient}"
|
subject "[Signed up] Welcome #{recipient}"
|
||||||
from "system@loudthinking.com"
|
from "system@loudthinking.com"
|
||||||
|
body :recipient => recipient
|
||||||
body(:recipient => recipient)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
The body of the email is created by using an Action View template (regular
|
The body of the email is created by using an Action View template (regular
|
||||||
|
@ -78,21 +77,26 @@ Example:
|
||||||
end
|
end
|
||||||
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)'
|
./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
|
== Configuration
|
||||||
|
|
||||||
The Base class has the full list of configuration options. Here's an example:
|
The Base class has the full list of configuration options. Here's an example:
|
||||||
|
|
||||||
ActionMailer::Base.smtp_settings = {
|
ActionMailer::Base.smtp_settings = {
|
||||||
:address=>'smtp.yourserver.com', # default: localhost
|
:address => 'smtp.yourserver.com', # default: localhost
|
||||||
:port=>'25', # default: 25
|
:port => '25', # default: 25
|
||||||
:user_name=>'user',
|
:user_name => 'user',
|
||||||
:password=>'pass',
|
:password => 'pass',
|
||||||
:authentication=>:plain # :plain, :login or :cram_md5
|
:authentication => :plain # :plain, :login or :cram_md5
|
||||||
}
|
}
|
||||||
|
|
||||||
== Dependencies
|
== Dependencies
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ module ActionMailer #:nodoc:
|
||||||
# * <tt>subject</tt> - The subject of your email. Sets the <tt>Subject:</tt> header.
|
# * <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>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>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>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>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>.
|
# * <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
|
# class MyMailer < ActionMailer::Base
|
||||||
# def signup_notification(recipient)
|
# def signup_notification(recipient)
|
||||||
# recipients recipient.email_address_with_name
|
# recipients recipient.email_address_with_name
|
||||||
# subject "New account information"
|
# subject "New account information"
|
||||||
# body "account" => recipient
|
# from "system@example.com"
|
||||||
# from "system@example.com"
|
# body :account => recipient
|
||||||
# content_type "text/html" # Here's where the magic happens
|
# content_type "text/html"
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
|
@ -145,6 +145,7 @@ module ActionMailer #:nodoc:
|
||||||
# recipients recipient.email_address_with_name
|
# recipients recipient.email_address_with_name
|
||||||
# subject "New account information"
|
# subject "New account information"
|
||||||
# from "system@example.com"
|
# from "system@example.com"
|
||||||
|
# content_type "multipart/alternative"
|
||||||
#
|
#
|
||||||
# part :content_type => "text/html",
|
# part :content_type => "text/html",
|
||||||
# :body => render_message("signup-as-html", :account => recipient)
|
# :body => render_message("signup-as-html", :account => recipient)
|
||||||
|
@ -167,9 +168,14 @@ module ActionMailer #:nodoc:
|
||||||
# * signup_notification.text.x-yaml.erb
|
# * signup_notification.text.x-yaml.erb
|
||||||
#
|
#
|
||||||
# Each would be rendered and added as a separate part to the message,
|
# 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
|
# with the corresponding content type. The content type for the entire
|
||||||
# each template.
|
# 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
|
# = 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>: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>: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>: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.
|
# * <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>
|
# 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>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>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
|
||||||
# * <tt>:arguments</tt> - The command line arguments
|
# * <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.
|
# * <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
|
# * <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.
|
# 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
|
# * <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>.
|
# 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
|
# * <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>.
|
# 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 "1.0". You
|
# * <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 <tt>@mime_version</tt>.
|
# 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
|
# * <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
|
# 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
|
# 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
|
class Base
|
||||||
include AdvAttrAccessor, PartContainer
|
include AdvAttrAccessor, PartContainer
|
||||||
include ActionController::UrlWriter if Object.const_defined?(:ActionController)
|
include ActionController::UrlWriter if Object.const_defined?(:ActionController)
|
||||||
|
|
|
@ -92,7 +92,7 @@ module ActionController #:nodoc:
|
||||||
# with the remaining data.
|
# with the remaining data.
|
||||||
#
|
#
|
||||||
# Note that you can define your own XML parameter parser which would allow you to describe multiple entities
|
# 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.
|
# 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
|
# 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 ActionView
|
||||||
# There are also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,
|
# 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
|
# link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html
|
||||||
module FormHelper
|
module FormHelper
|
||||||
# Creates a form and a scope around a specific model object that is used as a base for questioning about
|
# Creates a form and a scope around a specific model object that is used as
|
||||||
# values for the fields.
|
# a base for questioning about values for the fields.
|
||||||
|
#
|
||||||
|
# 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 %>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# The generic way to call +form_for+ requires a few arguments:
|
||||||
#
|
#
|
||||||
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
||||||
# <%= f.error_messages %>
|
# <%= f.error_messages %>
|
||||||
# First name: <%= f.text_field :first_name %>
|
# First name: <%= f.text_field :first_name %><br />
|
||||||
# Last name : <%= f.text_field :last_name %>
|
# Last name : <%= f.text_field :last_name %><br />
|
||||||
# Biography : <%= f.text_area :biography %>
|
# Biography : <%= f.text_area :biography %><br />
|
||||||
# Admin? : <%= f.check_box :admin %>
|
# Admin? : <%= f.check_box :admin %><br />
|
||||||
# <% end %>
|
# <% 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>,
|
# Worth noting is that the +form_for+ tag is called in a ERb evaluation block,
|
||||||
# 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
|
# not an ERb output block. So that's <tt><% %></tt>, not <tt><%= %></tt>. Also
|
||||||
# the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,
|
# worth noting is that +form_for+ yields a form builder object, in this
|
||||||
# you get away with <tt>f.text_field :name</tt>. Notice that you can even do <tt><%= f.error_messages %></tt> to display the
|
# example as +f+, which emulates the API for the stand-alone FormHelper
|
||||||
# error messsages of the model object in question.
|
# 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
|
# Even further, the +form_for+ method allows you to more easily escape the
|
||||||
# approach would require <tt>text_field :person, :name, :object => person</tt>
|
# instance variable convention. So while the stand-alone approach would require
|
||||||
# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with
|
# <tt>text_field :person, :name, :object => person</tt> to work with local
|
||||||
# <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>.
|
# 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
|
# Also note that +form_for+ doesn't create an exclusive scope. It's still
|
||||||
# and methods from FormTagHelper. For example:
|
# possible to use both the stand-alone FormHelper methods and methods from
|
||||||
|
# FormTagHelper. For example:
|
||||||
#
|
#
|
||||||
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
||||||
# First name: <%= f.text_field :first_name %>
|
# First name: <%= f.text_field :first_name %>
|
||||||
|
@ -105,22 +129,26 @@ module ActionView
|
||||||
# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
|
# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
|
||||||
# <% end %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base,
|
# This also works for the methods in FormOptionHelper and DateHelper that are
|
||||||
# like FormOptionHelper#collection_select and DateHelper#datetime_select.
|
# 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| %>
|
# <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>
|
||||||
# ...
|
# ...
|
||||||
# <% end %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
# The above form will then have the <tt>id</tt> attribute with the value </tt>person_form</tt>, which you can then
|
# The above form will then have the +id+ attribute with the value "person_form",
|
||||||
# style with CSS or manipulate with JavaScript.
|
# which you can then style with CSS or manipulate with JavaScript.
|
||||||
#
|
#
|
||||||
# === Relying on record identification
|
# === Relying on record identification
|
||||||
#
|
#
|
||||||
# In addition to manually configuring the form_for call, you can also rely on record identification, which will use
|
# As we said above, in addition to manually configuring the +form_for+ call,
|
||||||
# the conventions and named routes of that approach. Examples:
|
# 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| %>
|
# <% form_for(@post) do |f| %>
|
||||||
# ...
|
# ...
|
||||||
|
@ -140,7 +168,7 @@ module ActionView
|
||||||
#
|
#
|
||||||
# This will expand to be the same as:
|
# 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 %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
|
@ -150,7 +178,7 @@ module ActionView
|
||||||
# ...
|
# ...
|
||||||
# <% end %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
# And for namespaced routes, like admin_post_url:
|
# And for namespaced routes, like +admin_post_url+:
|
||||||
#
|
#
|
||||||
# <% form_for([:admin, @post]) do |f| %>
|
# <% form_for([:admin, @post]) do |f| %>
|
||||||
# ...
|
# ...
|
||||||
|
|
|
@ -120,17 +120,72 @@ module ActionView
|
||||||
# exception.
|
# exception.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== 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&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?"
|
# 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>
|
# # => <a href="http://www.rubyonrails.org/" onclick="return confirm('Are you sure?');">Visit Other Site</a>
|
||||||
#
|
#
|
||||||
# link_to "Help", { :action => "help" }, :popup => true
|
# link_to "Help", { :action => "help" }, :popup => true
|
||||||
# # => <a href="/testing/help/" onclick="window.open(this.href);return false;">Help</a>
|
# # => <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']
|
# link_to "View Image", @image, :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>
|
# # => <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
|
# link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete
|
||||||
# # => <a href="/testing/delete/9/" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
|
# # => <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;
|
# 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');
|
# 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>
|
# m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
change_table :videos do |t|
|
change_table :videos do |t|
|
||||||
t.timestamps # adds created_at, updated_at
|
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.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
|
t.remove :name, :email # removes the name and email columns
|
||||||
end
|
end
|
||||||
|
|
|
@ -753,6 +753,8 @@ module ActiveRecord
|
||||||
# * <tt>:source</tt> - Specifies the source association name used by <tt>has_one :through</tt> queries. Only use it if the name cannot be
|
# * <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
|
# 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>: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.
|
# * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
|
||||||
#
|
#
|
||||||
# Option examples:
|
# Option examples:
|
||||||
|
|
|
@ -16,16 +16,20 @@ module ActiveRecord
|
||||||
|
|
||||||
# Declare and check for suffixed attribute methods.
|
# Declare and check for suffixed attribute methods.
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
# Declare a method available for all attributes with the given suffix.
|
# Declares a method available for all attributes with the given suffix.
|
||||||
# Uses method_missing and respond_to? to rewrite the method
|
# Uses +method_missing+ and <tt>respond_to?</tt> to rewrite the method
|
||||||
|
#
|
||||||
# #{attr}#{suffix}(*args, &block)
|
# #{attr}#{suffix}(*args, &block)
|
||||||
|
#
|
||||||
# to
|
# to
|
||||||
|
#
|
||||||
# attribute#{suffix}(#{attr}, *args, &block)
|
# attribute#{suffix}(#{attr}, *args, &block)
|
||||||
#
|
#
|
||||||
# An attribute#{suffix} instance method must exist and accept at least
|
# An <tt>attribute#{suffix}</tt> instance method must exist and accept at least
|
||||||
# the attr argument.
|
# the +attr+ argument.
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
|
#
|
||||||
# class Person < ActiveRecord::Base
|
# class Person < ActiveRecord::Base
|
||||||
# attribute_method_suffix '_changed?'
|
# attribute_method_suffix '_changed?'
|
||||||
#
|
#
|
||||||
|
@ -60,8 +64,8 @@ module ActiveRecord
|
||||||
!generated_methods.empty?
|
!generated_methods.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# generates all the attribute related methods for columns in the database
|
# Generates all the attribute related methods for columns in the database
|
||||||
# accessors, mutators and query methods
|
# accessors, mutators and query methods.
|
||||||
def define_attribute_methods
|
def define_attribute_methods
|
||||||
return if generated_methods?
|
return if generated_methods?
|
||||||
columns_hash.each do |name, column|
|
columns_hash.each do |name, column|
|
||||||
|
@ -89,8 +93,9 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check to see if the method is defined in the model or any of its subclasses that also derive from ActiveRecord.
|
# Checks whether the method is defined in the model or any of its subclasses
|
||||||
# Raise DangerousAttributeError if the method is defined by ActiveRecord though.
|
# that also derive from ActiveRecord. Raises DangerousAttributeError if the
|
||||||
|
# method is defined by Active Record though.
|
||||||
def instance_method_already_implemented?(method_name)
|
def instance_method_already_implemented?(method_name)
|
||||||
method_name = method_name.to_s
|
method_name = method_name.to_s
|
||||||
return true if method_name =~ /^id(=$|\?$|$)/
|
return true if method_name =~ /^id(=$|\?$|$)/
|
||||||
|
@ -104,17 +109,19 @@ module ActiveRecord
|
||||||
|
|
||||||
# +cache_attributes+ allows you to declare which converted attribute values should
|
# +cache_attributes+ allows you to declare which converted attribute values should
|
||||||
# be cached. Usually caching only pays off for attributes with expensive conversion
|
# 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)
|
def cache_attributes(*attribute_names)
|
||||||
attribute_names.each {|attr| cached_attributes << attr.to_s}
|
attribute_names.each {|attr| cached_attributes << attr.to_s}
|
||||||
end
|
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
|
def cached_attributes
|
||||||
@cached_attributes ||=
|
@cached_attributes ||=
|
||||||
columns.select{|c| attribute_types_cached_by_default.include?(c.type)}.map(&:name).to_set
|
columns.select{|c| attribute_types_cached_by_default.include?(c.type)}.map(&:name).to_set
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns +true+ if the provided attribute is being cached.
|
||||||
def cache_attribute?(attr_name)
|
def cache_attribute?(attr_name)
|
||||||
cached_attributes.include?(attr_name)
|
cached_attributes.include?(attr_name)
|
||||||
end
|
end
|
||||||
|
@ -210,14 +217,14 @@ module ActiveRecord
|
||||||
end # ClassMethods
|
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
|
# 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
|
# 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
|
# 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
|
# 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)
|
def method_missing(method_id, *args, &block)
|
||||||
method_name = method_id.to_s
|
method_name = method_id.to_s
|
||||||
|
|
||||||
|
@ -288,7 +295,7 @@ module ActiveRecord
|
||||||
|
|
||||||
|
|
||||||
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float
|
# 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)
|
def write_attribute(attr_name, value)
|
||||||
attr_name = attr_name.to_s
|
attr_name = attr_name.to_s
|
||||||
@attributes_cache.delete(attr_name)
|
@attributes_cache.delete(attr_name)
|
||||||
|
@ -319,8 +326,9 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# A Person object with a name attribute can ask person.respond_to?("name"), person.respond_to?("name="), and
|
# A Person object with a name attribute can ask <tt>person.respond_to?("name")</tt>,
|
||||||
# person.respond_to?("name?") which will all return true.
|
# <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?
|
alias :respond_to_without_attributes? :respond_to?
|
||||||
def respond_to?(method, include_priv = false)
|
def respond_to?(method, include_priv = false)
|
||||||
method_name = method.to_s
|
method_name = method.to_s
|
||||||
|
|
|
@ -18,11 +18,11 @@ module ActiveRecord
|
||||||
#
|
#
|
||||||
# +name+ is the column's name, as in <tt><b>supplier_id</b> int(11)</tt>.
|
# +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>.
|
# +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.
|
# +null+ determines if this column allows +NULL+ values.
|
||||||
def initialize(name, default, sql_type = nil, null = true)
|
def initialize(name, default, sql_type = nil, null = true)
|
||||||
@name, @sql_type, @null = name, sql_type, null
|
@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)
|
@type = simplified_type(sql_type)
|
||||||
@default = extract_default(default)
|
@default = extract_default(default)
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ module ActiveRecord
|
||||||
def new_time(year, mon, mday, hour, min, sec, microsec)
|
def new_time(year, mon, mday, hour, min, sec, microsec)
|
||||||
# Treat 0000-00-00 00:00:00 as nil.
|
# Treat 0000-00-00 00:00:00 as nil.
|
||||||
return nil if year.nil? || year == 0
|
return nil if year.nil? || year == 0
|
||||||
|
|
||||||
Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
|
Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -250,11 +250,11 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
|
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
|
||||||
|
|
||||||
def sql_type
|
def sql_type
|
||||||
base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
|
base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_sql
|
def to_sql
|
||||||
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
|
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
|
||||||
add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key
|
add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key
|
||||||
|
@ -309,39 +309,39 @@ module ActiveRecord
|
||||||
# * <tt>:default</tt> -
|
# * <tt>:default</tt> -
|
||||||
# The column's default value. Use nil for NULL.
|
# The column's default value. Use nil for NULL.
|
||||||
# * <tt>:null</tt> -
|
# * <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>.
|
# have been named <tt>:null_allowed</tt>.
|
||||||
# * <tt>:precision</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> -
|
# * <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
|
# Please be aware of different RDBMS implementations behavior with
|
||||||
# <tt>:decimal</tt> columns:
|
# <tt>:decimal</tt> columns:
|
||||||
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
|
# * 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>, and makes no comments about the requirements of
|
||||||
# <tt>:precision</tt>.
|
# <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).
|
# Default is (10,0).
|
||||||
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
||||||
# <tt>:scale</tt> [0..infinity]. No default.
|
# <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.
|
# Internal storage as strings. No default.
|
||||||
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
||||||
# but the maximum supported <tt>:precision</tt> is 16. No default.
|
# 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).
|
# 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.
|
# 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
|
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
||||||
# storage rules, decimal being better.
|
# 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
|
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
||||||
# NUMERIC is 19, and DECIMAL is 38.
|
# 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).
|
# 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).
|
# Default (38,0).
|
||||||
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
||||||
#
|
#
|
||||||
|
@ -394,7 +394,7 @@ module ActiveRecord
|
||||||
# t.timestamps
|
# t.timestamps
|
||||||
# end
|
# 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#timestamps that'll add created_at and updated_at as datetimes.
|
||||||
#
|
#
|
||||||
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
||||||
|
@ -434,13 +434,13 @@ module ActiveRecord
|
||||||
def #{column_type}(*args)
|
def #{column_type}(*args)
|
||||||
options = args.extract_options!
|
options = args.extract_options!
|
||||||
column_names = args
|
column_names = args
|
||||||
|
|
||||||
column_names.each { |name| column(name, '#{column_type}', options) }
|
column_names.each { |name| column(name, '#{column_type}', options) }
|
||||||
end
|
end
|
||||||
EOV
|
EOV
|
||||||
end
|
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.
|
# <tt>:updated_at</tt> to the table.
|
||||||
def timestamps
|
def timestamps
|
||||||
column(:created_at, :datetime)
|
column(:created_at, :datetime)
|
||||||
|
@ -458,7 +458,7 @@ module ActiveRecord
|
||||||
alias :belongs_to :references
|
alias :belongs_to :references
|
||||||
|
|
||||||
# Returns a String whose contents are the column definitions
|
# 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.
|
# to generate the final SQL to create the table.
|
||||||
def to_sql
|
def to_sql
|
||||||
@columns * ', '
|
@columns * ', '
|
||||||
|
@ -510,15 +510,15 @@ module ActiveRecord
|
||||||
|
|
||||||
# Adds a new column to the named table.
|
# Adds a new column to the named table.
|
||||||
# See TableDefinition#column for details of the options you can use.
|
# See TableDefinition#column for details of the options you can use.
|
||||||
# ===== Examples
|
# ===== Example
|
||||||
# ====== Creating a simple columns
|
# ====== Creating a simple column
|
||||||
# t.column(:name, :string)
|
# t.column(:name, :string)
|
||||||
def column(column_name, type, options = {})
|
def column(column_name, type, options = {})
|
||||||
@base.add_column(@table_name, column_name, type, options)
|
@base.add_column(@table_name, column_name, type, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
||||||
# an Array of Symbols. See SchemaStatements#add_index
|
# an Array of Symbols. See SchemaStatements#add_index
|
||||||
#
|
#
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
# ====== Creating a simple index
|
# ====== Creating a simple index
|
||||||
|
@ -531,8 +531,8 @@ module ActiveRecord
|
||||||
@base.add_index(@table_name, column_name, options)
|
@base.add_index(@table_name, column_name, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#timestamps
|
# Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#add_timestamps
|
||||||
# ===== Examples
|
# ===== Example
|
||||||
# t.timestamps
|
# t.timestamps
|
||||||
def timestamps
|
def timestamps
|
||||||
@base.add_timestamps(@table_name)
|
@base.add_timestamps(@table_name)
|
||||||
|
@ -547,7 +547,7 @@ module ActiveRecord
|
||||||
@base.change_column(@table_name, column_name, type, options)
|
@base.change_column(@table_name, column_name, type, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets a new default value for a column. See
|
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
# t.change_default(:qualification, 'new')
|
# t.change_default(:qualification, 'new')
|
||||||
# t.change_default(:authorized, 1)
|
# t.change_default(:authorized, 1)
|
||||||
|
@ -559,27 +559,27 @@ module ActiveRecord
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
# t.remove(:qualification)
|
# t.remove(:qualification)
|
||||||
# t.remove(:qualification, :experience)
|
# t.remove(:qualification, :experience)
|
||||||
# t.removes(:qualification, :experience)
|
|
||||||
def remove(*column_names)
|
def remove(*column_names)
|
||||||
@base.remove_column(@table_name, column_names)
|
@base.remove_column(@table_name, column_names)
|
||||||
end
|
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
|
# 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
|
# 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]
|
# 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
|
# t.remove_index :name => :by_branch_party
|
||||||
def remove_index(options = {})
|
def remove_index(options = {})
|
||||||
@base.remove_index(@table_name, options)
|
@base.remove_index(@table_name, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the timestamp columns (created_at and updated_at) from the table.
|
# Removes the timestamp columns (created_at and updated_at) from the table.
|
||||||
# ===== Examples
|
# ===== Example
|
||||||
# t.remove_timestamps
|
# t.remove_timestamps
|
||||||
def remove_timestamps
|
def remove_timestamps
|
||||||
@base.remove_timestamps(@table_name)
|
@base.remove_timestamps(@table_name)
|
||||||
|
@ -592,12 +592,11 @@ module ActiveRecord
|
||||||
@base.rename_column(@table_name, column_name, new_column_name)
|
@base.rename_column(@table_name, column_name, new_column_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds a reference. Optionally adds a +type+ column. <tt>reference</tt>,
|
# Adds a reference. Optionally adds a +type+ column.
|
||||||
# <tt>references</tt> and <tt>belongs_to</tt> are all acceptable
|
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
|
||||||
# ===== Example
|
# ===== Examples
|
||||||
# t.references(:goat)
|
# t.references(:goat)
|
||||||
# t.references(:goat, :polymorphic => true)
|
# t.references(:goat, :polymorphic => true)
|
||||||
# t.references(:goat)
|
|
||||||
# t.belongs_to(:goat)
|
# t.belongs_to(:goat)
|
||||||
def references(*args)
|
def references(*args)
|
||||||
options = args.extract_options!
|
options = args.extract_options!
|
||||||
|
@ -609,12 +608,11 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
alias :belongs_to :references
|
alias :belongs_to :references
|
||||||
|
|
||||||
# Adds a reference. Optionally removes a +type+ column. <tt>remove_reference</tt>,
|
# Removes a reference. Optionally removes a +type+ column.
|
||||||
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are all acceptable
|
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
||||||
# ===== Example
|
# ===== Examples
|
||||||
# t.remove_reference(:goat)
|
|
||||||
# t.remove_reference(:goat, :polymorphic => true)
|
|
||||||
# t.remove_references(:goat)
|
# t.remove_references(:goat)
|
||||||
|
# t.remove_references(:goat, :polymorphic => true)
|
||||||
# t.remove_belongs_to(:goat)
|
# t.remove_belongs_to(:goat)
|
||||||
def remove_references(*args)
|
def remove_references(*args)
|
||||||
options = args.extract_options!
|
options = args.extract_options!
|
||||||
|
@ -627,7 +625,7 @@ module ActiveRecord
|
||||||
alias :remove_belongs_to :remove_references
|
alias :remove_belongs_to :remove_references
|
||||||
|
|
||||||
# Adds a column or columns of a specified type
|
# Adds a column or columns of a specified type
|
||||||
# ===== Example
|
# ===== Examples
|
||||||
# t.string(:goat)
|
# t.string(:goat)
|
||||||
# t.string(:goat, :sheep)
|
# t.string(:goat, :sheep)
|
||||||
%w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
|
%w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module ActiveRecord
|
||||||
255
|
255
|
||||||
end
|
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)
|
def table_alias_for(table_name)
|
||||||
table_name[0..table_alias_length-1].gsub(/\./, '_')
|
table_name[0..table_alias_length-1].gsub(/\./, '_')
|
||||||
end
|
end
|
||||||
|
@ -152,7 +152,7 @@ module ActiveRecord
|
||||||
# t.remove :company
|
# t.remove :company
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# ====== Remove a column
|
# ====== Remove several columns
|
||||||
# change_table(:suppliers) do |t|
|
# change_table(:suppliers) do |t|
|
||||||
# t.remove :company_id
|
# t.remove :company_id
|
||||||
# t.remove :width, :height
|
# t.remove :width, :height
|
||||||
|
@ -168,7 +168,7 @@ module ActiveRecord
|
||||||
def change_table(table_name)
|
def change_table(table_name)
|
||||||
yield Table.new(table_name, self)
|
yield Table.new(table_name, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Renames a table.
|
# Renames a table.
|
||||||
# ===== Example
|
# ===== Example
|
||||||
# rename_table('octopuses', 'octopi')
|
# rename_table('octopuses', 'octopi')
|
||||||
|
@ -199,7 +199,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias :remove_columns :remove_column
|
alias :remove_columns :remove_column
|
||||||
|
|
||||||
# Changes the column's definition according to the new options.
|
# Changes the column's definition according to the new options.
|
||||||
# See TableDefinition#column for details of the options you can use.
|
# See TableDefinition#column for details of the options you can use.
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
|
@ -389,7 +389,7 @@ module ActiveRecord
|
||||||
def distinct(columns, order_by)
|
def distinct(columns, order_by)
|
||||||
"DISTINCT #{columns}"
|
"DISTINCT #{columns}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# ORDER BY clause for the passed order option.
|
# ORDER BY clause for the passed order option.
|
||||||
# PostgreSQL overrides this due to its stricter standards compliance.
|
# PostgreSQL overrides this due to its stricter standards compliance.
|
||||||
def add_order_by_for_association_limiting!(sql, options)
|
def add_order_by_for_association_limiting!(sql, options)
|
||||||
|
@ -401,17 +401,17 @@ module ActiveRecord
|
||||||
# add_timestamps(:suppliers)
|
# add_timestamps(:suppliers)
|
||||||
def add_timestamps(table_name)
|
def add_timestamps(table_name)
|
||||||
add_column table_name, :created_at, :datetime
|
add_column table_name, :created_at, :datetime
|
||||||
add_column table_name, :updated_at, :datetime
|
add_column table_name, :updated_at, :datetime
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
# remove_timestamps(:suppliers)
|
# remove_timestamps(:suppliers)
|
||||||
def remove_timestamps(table_name)
|
def remove_timestamps(table_name)
|
||||||
remove_column table_name, :updated_at
|
remove_column table_name, :updated_at
|
||||||
remove_column table_name, :created_at
|
remove_column table_name, :created_at
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def options_include_default?(options)
|
def options_include_default?(options)
|
||||||
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
class Module
|
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)
|
def attr_internal_reader(*attrs)
|
||||||
attrs.each do |attr|
|
attrs.each do |attr|
|
||||||
module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end"
|
module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end"
|
||||||
end
|
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)
|
def attr_internal_writer(*attrs)
|
||||||
attrs.each do |attr|
|
attrs.each do |attr|
|
||||||
module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end"
|
module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end"
|
||||||
end
|
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.
|
# variable.
|
||||||
def attr_internal_accessor(*attrs)
|
def attr_internal_accessor(*attrs)
|
||||||
attr_internal_reader(*attrs)
|
attr_internal_reader(*attrs)
|
||||||
|
|
|
@ -15,10 +15,9 @@ module ActiveSupport #:nodoc:
|
||||||
end
|
end
|
||||||
# Gives a human readable format of the range.
|
# Gives a human readable format of the range.
|
||||||
#
|
#
|
||||||
# Example:
|
# ==== Example:
|
||||||
#
|
#
|
||||||
# >> [1..100].to_formatted_s
|
# [1..100].to_formatted_s # => "1..100"
|
||||||
# => "1..100"
|
|
||||||
def to_formatted_s(format = :default)
|
def to_formatted_s(format = :default)
|
||||||
RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s
|
RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s
|
||||||
end
|
end
|
||||||
|
|
|
@ -92,6 +92,13 @@ module Inflector
|
||||||
|
|
||||||
extend self
|
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
|
def inflections
|
||||||
if block_given?
|
if block_given?
|
||||||
yield Inflections.instance
|
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
|
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
|
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
|
class WeblogController < ActionController::Base
|
||||||
def index
|
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>
|
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
|
== Description of Contents
|
||||||
|
|
||||||
|
@ -200,13 +209,13 @@ app/models
|
||||||
|
|
||||||
app/views
|
app/views
|
||||||
Holds the template files for the view that should be named like
|
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.
|
syntax.
|
||||||
|
|
||||||
app/views/layouts
|
app/views/layouts
|
||||||
Holds the template files for layouts to be used with views. This models the common
|
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
|
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.
|
call <% yield %> to render the view using this layout.
|
||||||
|
|
||||||
app/helpers
|
app/helpers
|
||||||
|
@ -243,4 +252,5 @@ test
|
||||||
|
|
||||||
vendor
|
vendor
|
||||||
External libraries that the application depends on. Also includes the plugins subdirectory.
|
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.
|
This directory is in the load path.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# 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.
|
# 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.
|
# 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
|
Stubs out a new database migration. Pass the migration name, either
|
||||||
CamelCased or under_scored, and an optional list of attribute pairs as arguments.
|
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
|
You can name your migration in either of these formats to generate add/remove
|
||||||
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
|
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
|
||||||
|
@ -10,12 +10,12 @@ Description:
|
||||||
Example:
|
Example:
|
||||||
`./script/generate migration AddSslFlag`
|
`./script/generate migration AddSslFlag`
|
||||||
|
|
||||||
With 4 existing migrations, this creates the AddSslFlag migration in
|
If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
|
||||||
db/migrate/005_add_ssl_flag.rb
|
db/migrate/20080514090912_add_ssl_flag.rb
|
||||||
|
|
||||||
`./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
|
`./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:
|
this in the Up migration:
|
||||||
|
|
||||||
add_column :posts, :title, :string
|
add_column :posts, :title, :string
|
||||||
|
|
|
@ -1,5 +1,26 @@
|
||||||
|
# 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 SourceAnnotationExtractor
|
||||||
class Annotation < Struct.new(:line, :tag, :text)
|
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={})
|
def to_s(options={})
|
||||||
s = "[%3d] " % line
|
s = "[%3d] " % line
|
||||||
s << "[#{tag}] " if options[:tag]
|
s << "[#{tag}] " if options[:tag]
|
||||||
|
@ -7,6 +28,12 @@ class SourceAnnotationExtractor
|
||||||
end
|
end
|
||||||
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={})
|
def self.enumerate(tag, options={})
|
||||||
extractor = new(tag)
|
extractor = new(tag)
|
||||||
extractor.display(extractor.find, options)
|
extractor.display(extractor.find, options)
|
||||||
|
@ -18,10 +45,18 @@ class SourceAnnotationExtractor
|
||||||
@tag = tag
|
@tag = tag
|
||||||
end
|
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))
|
def find(dirs=%w(app lib test))
|
||||||
dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
|
dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
|
||||||
end
|
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)
|
def find_in(dir)
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
|
@ -40,6 +75,9 @@ class SourceAnnotationExtractor
|
||||||
results
|
results
|
||||||
end
|
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)
|
def extract_annotations_from(file, pattern)
|
||||||
lineno = 0
|
lineno = 0
|
||||||
result = File.readlines(file).inject([]) do |list, line|
|
result = File.readlines(file).inject([]) do |list, line|
|
||||||
|
@ -50,6 +88,8 @@ class SourceAnnotationExtractor
|
||||||
result.empty? ? {} : { file => result }
|
result.empty? ? {} : { file => result }
|
||||||
end
|
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={})
|
def display(results, options={})
|
||||||
results.keys.sort.each do |file|
|
results.keys.sort.each do |file|
|
||||||
puts "#{file}:"
|
puts "#{file}:"
|
||||||
|
|
Loading…
Reference in New Issue