Rails 2.1
Update to Rails 2.1 final.
This commit is contained in:
parent
fd554cce90
commit
516d6dfac0
257 changed files with 4058 additions and 1933 deletions
2
vendor/rails/actionmailer/CHANGELOG
vendored
2
vendor/rails/actionmailer/CHANGELOG
vendored
|
@ -1,4 +1,4 @@
|
||||||
*2.1.0 RC1 (May 11th, 2008)*
|
*2.1.0 (May 31st, 2008)*
|
||||||
|
|
||||||
* Fixed that a return-path header would be ignored #7572 [joost]
|
* Fixed that a return-path header would be ignored #7572 [joost]
|
||||||
|
|
||||||
|
|
24
vendor/rails/actionmailer/README
vendored
24
vendor/rails/actionmailer/README
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
2
vendor/rails/actionmailer/Rakefile
vendored
2
vendor/rails/actionmailer/Rakefile
vendored
|
@ -55,7 +55,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.rubyforge_project = "actionmailer"
|
s.rubyforge_project = "actionmailer"
|
||||||
s.homepage = "http://www.rubyonrails.org"
|
s.homepage = "http://www.rubyonrails.org"
|
||||||
|
|
||||||
s.add_dependency('actionpack', '= 2.0.991' + PKG_BUILD)
|
s.add_dependency('actionpack', '= 2.1.0' + PKG_BUILD)
|
||||||
|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
|
@ -5,12 +5,12 @@ require 'action_mailer/utils'
|
||||||
require 'tmail/net'
|
require 'tmail/net'
|
||||||
|
|
||||||
module ActionMailer #:nodoc:
|
module ActionMailer #:nodoc:
|
||||||
# ActionMailer allows you to send email from your application using a mailer model and views.
|
# Action Mailer allows you to send email from your application using a mailer model and views.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# = Mailer Models
|
# = Mailer Models
|
||||||
#
|
#
|
||||||
# To use ActionMailer, you need to create a mailer model.
|
# To use Action Mailer, you need to create a mailer model.
|
||||||
#
|
#
|
||||||
# $ script/generate mailer Notifier
|
# $ script/generate mailer Notifier
|
||||||
#
|
#
|
||||||
|
@ -35,7 +35,8 @@ 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 addresses. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc:</tt> header.
|
||||||
|
# * <tt>reply_to</tt> - Takes one or more email addresses. These addresses will be listed as the default recipients when replying to your email. Sets the <tt>Reply-To:</tt> header.
|
||||||
# * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent.
|
# * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header 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>.
|
||||||
|
@ -54,7 +55,7 @@ module ActionMailer #:nodoc:
|
||||||
#
|
#
|
||||||
# = Mailer views
|
# = Mailer views
|
||||||
#
|
#
|
||||||
# Like ActionController, each mailer class has a corresponding view directory
|
# Like Action Controller, each mailer class has a corresponding view directory
|
||||||
# in which each method of the class looks for a template with its name.
|
# in which each method of the class looks for a template with its name.
|
||||||
# To define a template to be used with a mailing, create an <tt>.erb</tt> file with the same name as the method
|
# To define a template to be used with a mailing, create an <tt>.erb</tt> file with the same name as the method
|
||||||
# in your mailer model. For example, in the mailer defined above, the template at
|
# in your mailer model. For example, in the mailer defined above, the template at
|
||||||
|
@ -129,9 +130,9 @@ module ActionMailer #:nodoc:
|
||||||
# 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"
|
||||||
# content_type "text/html" # Here's where the magic happens
|
# body :account => recipient
|
||||||
|
# content_type "text/html"
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
|
@ -145,6 +146,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)
|
||||||
|
@ -156,7 +158,7 @@ module ActionMailer #:nodoc:
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Multipart messages can also be used implicitly because ActionMailer will automatically
|
# Multipart messages can also be used implicitly because Action Mailer will automatically
|
||||||
# detect and use multipart templates, where each template is named after the name of the action, followed
|
# detect and use multipart templates, where each template is named after the name of the action, followed
|
||||||
# by the content type. Each such detected template will be added as separate part to the message.
|
# by the content type. Each such detected template will be added as separate part to the message.
|
||||||
#
|
#
|
||||||
|
@ -167,9 +169,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
|
||||||
#
|
#
|
||||||
|
@ -210,11 +217,11 @@ module ActionMailer #:nodoc:
|
||||||
# * <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.
|
||||||
#
|
#
|
||||||
|
@ -227,16 +234,16 @@ module ActionMailer #:nodoc:
|
||||||
# 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)
|
||||||
|
@ -311,6 +318,10 @@ module ActionMailer #:nodoc:
|
||||||
# Specify the from address for the message.
|
# Specify the from address for the message.
|
||||||
adv_attr_accessor :from
|
adv_attr_accessor :from
|
||||||
|
|
||||||
|
# Specify the address (if different than the "from" address) to direct
|
||||||
|
# replies to this message.
|
||||||
|
adv_attr_accessor :reply_to
|
||||||
|
|
||||||
# Specify additional headers to be added to the message.
|
# Specify additional headers to be added to the message.
|
||||||
adv_attr_accessor :headers
|
adv_attr_accessor :headers
|
||||||
|
|
||||||
|
@ -377,8 +388,8 @@ module ActionMailer #:nodoc:
|
||||||
|
|
||||||
# Receives a raw email, parses it into an email object, decodes it,
|
# Receives a raw email, parses it into an email object, decodes it,
|
||||||
# instantiates a new mailer, and passes the email object to the mailer
|
# instantiates a new mailer, and passes the email object to the mailer
|
||||||
# object's #receive method. If you want your mailer to be able to
|
# object's +receive+ method. If you want your mailer to be able to
|
||||||
# process incoming messages, you'll need to implement a #receive
|
# process incoming messages, you'll need to implement a +receive+
|
||||||
# method that accepts the email object as a parameter:
|
# method that accepts the email object as a parameter:
|
||||||
#
|
#
|
||||||
# class MyMailer < ActionMailer::Base
|
# class MyMailer < ActionMailer::Base
|
||||||
|
@ -484,7 +495,7 @@ module ActionMailer #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delivers a TMail::Mail object. By default, it delivers the cached mail
|
# Delivers a TMail::Mail object. By default, it delivers the cached mail
|
||||||
# object (from the #create! method). If no cached mail object exists, and
|
# object (from the <tt>create!</tt> method). If no cached mail object exists, and
|
||||||
# no alternate has been given as the parameter, this will fail.
|
# no alternate has been given as the parameter, this will fail.
|
||||||
def deliver!(mail = @mail)
|
def deliver!(mail = @mail)
|
||||||
raise "no mail object available for delivery!" unless mail
|
raise "no mail object available for delivery!" unless mail
|
||||||
|
@ -511,7 +522,7 @@ module ActionMailer #:nodoc:
|
||||||
@content_type ||= @@default_content_type.dup
|
@content_type ||= @@default_content_type.dup
|
||||||
@implicit_parts_order ||= @@default_implicit_parts_order.dup
|
@implicit_parts_order ||= @@default_implicit_parts_order.dup
|
||||||
@template ||= method_name
|
@template ||= method_name
|
||||||
@mailer_name ||= Inflector.underscore(self.class.name)
|
@mailer_name ||= self.class.name.underscore
|
||||||
@parts ||= []
|
@parts ||= []
|
||||||
@headers ||= {}
|
@headers ||= {}
|
||||||
@body ||= {}
|
@body ||= {}
|
||||||
|
@ -574,9 +585,10 @@ module ActionMailer #:nodoc:
|
||||||
m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)
|
m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)
|
||||||
m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil?
|
m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil?
|
||||||
m.cc = quote_address_if_necessary(cc, charset) unless cc.nil?
|
m.cc = quote_address_if_necessary(cc, charset) unless cc.nil?
|
||||||
|
m.reply_to = quote_address_if_necessary(reply_to, charset) unless reply_to.nil?
|
||||||
m.mime_version = mime_version unless mime_version.nil?
|
m.mime_version = mime_version unless mime_version.nil?
|
||||||
m.date = sent_on.to_time rescue sent_on if sent_on
|
m.date = sent_on.to_time rescue sent_on if sent_on
|
||||||
|
|
||||||
headers.each { |k, v| m[k] = v }
|
headers.each { |k, v| m[k] = v }
|
||||||
|
|
||||||
real_content_type, ctype_attrs = parse_content_type
|
real_content_type, ctype_attrs = parse_content_type
|
||||||
|
|
|
@ -34,7 +34,7 @@ module ActionMailer
|
||||||
# helper FooHelper
|
# helper FooHelper
|
||||||
# includes FooHelper in the template class.
|
# includes FooHelper in the template class.
|
||||||
# helper { def foo() "#{bar} is the very best" end }
|
# helper { def foo() "#{bar} is the very best" end }
|
||||||
# evaluates the block in the template class, adding method #foo.
|
# evaluates the block in the template class, adding method +foo+.
|
||||||
# helper(:three, BlindHelper) { def mice() 'mice' end }
|
# helper(:three, BlindHelper) { def mice() 'mice' end }
|
||||||
# does all three.
|
# does all three.
|
||||||
def helper(*args, &block)
|
def helper(*args, &block)
|
||||||
|
|
|
@ -5,7 +5,7 @@ require 'action_mailer/utils'
|
||||||
module ActionMailer
|
module ActionMailer
|
||||||
# Represents a subpart of an email message. It shares many similar
|
# Represents a subpart of an email message. It shares many similar
|
||||||
# attributes of ActionMailer::Base. Although you can create parts manually
|
# attributes of ActionMailer::Base. Although you can create parts manually
|
||||||
# and add them to the #parts list of the mailer, it is easier
|
# and add them to the +parts+ list of the mailer, it is easier
|
||||||
# to use the helper methods in ActionMailer::PartContainer.
|
# to use the helper methods in ActionMailer::PartContainer.
|
||||||
class Part
|
class Part
|
||||||
include ActionMailer::AdvAttrAccessor
|
include ActionMailer::AdvAttrAccessor
|
||||||
|
@ -13,7 +13,7 @@ module ActionMailer
|
||||||
|
|
||||||
# Represents the body of the part, as a string. This should not be a
|
# Represents the body of the part, as a string. This should not be a
|
||||||
# Hash (like ActionMailer::Base), but if you want a template to be rendered
|
# Hash (like ActionMailer::Base), but if you want a template to be rendered
|
||||||
# into the body of a subpart you can do it with the mailer's #render method
|
# into the body of a subpart you can do it with the mailer's +render+ method
|
||||||
# and assign the result here.
|
# and assign the result here.
|
||||||
adv_attr_accessor :body
|
adv_attr_accessor :body
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ module ActionMailer
|
||||||
# regular email address, or it can be a phrase followed by an address in
|
# regular email address, or it can be a phrase followed by an address in
|
||||||
# brackets. The phrase is the only part that will be quoted, and only if
|
# brackets. The phrase is the only part that will be quoted, and only if
|
||||||
# it needs to be. This allows extended characters to be used in the
|
# it needs to be. This allows extended characters to be used in the
|
||||||
# "to", "from", "cc", and "bcc" headers.
|
# "to", "from", "cc", "bcc" and "reply-to" headers.
|
||||||
def quote_address_if_necessary(address, charset)
|
def quote_address_if_necessary(address, charset)
|
||||||
if Array === address
|
if Array === address
|
||||||
address.map { |a| quote_address_if_necessary(a, charset) }
|
address.map { |a| quote_address_if_necessary(a, charset) }
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
|
||||||
begin
|
begin
|
||||||
gem 'tmail', '~> 1.2.2'
|
gem 'tmail', '~> 1.2.3'
|
||||||
rescue Gem::LoadError
|
rescue Gem::LoadError
|
||||||
$:.unshift "#{File.dirname(__FILE__)}/vendor/tmail-1.2.2"
|
$:.unshift "#{File.dirname(__FILE__)}/vendor/tmail-1.2.3"
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
|
@ -339,23 +339,37 @@ module TMail
|
||||||
def scanadd( str, force = false )
|
def scanadd( str, force = false )
|
||||||
types = ''
|
types = ''
|
||||||
strs = []
|
strs = []
|
||||||
|
if str.respond_to?(:encoding)
|
||||||
|
enc = str.encoding
|
||||||
|
str.force_encoding(Encoding::ASCII_8BIT)
|
||||||
|
end
|
||||||
until str.empty?
|
until str.empty?
|
||||||
if m = /\A[^\e\t\r\n ]+/.match(str)
|
if m = /\A[^\e\t\r\n ]+/.match(str)
|
||||||
types << (force ? 'j' : 'a')
|
types << (force ? 'j' : 'a')
|
||||||
|
if str.respond_to?(:encoding)
|
||||||
|
strs.push m[0].force_encoding(enc)
|
||||||
|
else
|
||||||
strs.push m[0]
|
strs.push m[0]
|
||||||
|
end
|
||||||
elsif m = /\A[\t\r\n ]+/.match(str)
|
elsif m = /\A[\t\r\n ]+/.match(str)
|
||||||
types << 's'
|
types << 's'
|
||||||
|
if str.respond_to?(:encoding)
|
||||||
|
strs.push m[0].force_encoding(enc)
|
||||||
|
else
|
||||||
strs.push m[0]
|
strs.push m[0]
|
||||||
|
end
|
||||||
|
|
||||||
elsif m = /\A\e../.match(str)
|
elsif m = /\A\e../.match(str)
|
||||||
esc = m[0]
|
esc = m[0]
|
||||||
str = m.post_match
|
str = m.post_match
|
||||||
if esc != "\e(B" and m = /\A[^\e]+/.match(str)
|
if esc != "\e(B" and m = /\A[^\e]+/.match(str)
|
||||||
types << 'j'
|
types << 'j'
|
||||||
|
if str.respond_to?(:encoding)
|
||||||
|
strs.push m[0].force_encoding(enc)
|
||||||
|
else
|
||||||
strs.push m[0]
|
strs.push m[0]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
raise 'TMail FATAL: encoder scan fail'
|
raise 'TMail FATAL: encoder scan fail'
|
||||||
|
@ -453,8 +467,14 @@ module TMail
|
||||||
size = max_bytes(chunksize, str.size) - 6
|
size = max_bytes(chunksize, str.size) - 6
|
||||||
size = (size % 2 == 0) ? (size) : (size - 1)
|
size = (size % 2 == 0) ? (size) : (size - 1)
|
||||||
return nil if size <= 0
|
return nil if size <= 0
|
||||||
|
if str.respond_to?(:encoding)
|
||||||
|
enc = str.encoding
|
||||||
|
str.force_encoding(Encoding::ASCII_8BIT)
|
||||||
|
"\e$B#{str.slice!(0, size)}\e(B".force_encoding(enc)
|
||||||
|
else
|
||||||
"\e$B#{str.slice!(0, size)}\e(B"
|
"\e$B#{str.slice!(0, size)}\e(B"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def extract_A( chunksize, str )
|
def extract_A( chunksize, str )
|
||||||
size = max_bytes(chunksize, str.size)
|
size = max_bytes(chunksize, str.size)
|
|
@ -592,11 +592,16 @@ module TMail
|
||||||
|
|
||||||
# Destructively sets the message ID of the mail object instance to the passed in string
|
# Destructively sets the message ID of the mail object instance to the passed in string
|
||||||
#
|
#
|
||||||
|
# Invalid message IDs are ignored (silently, unless configured otherwise) and result in
|
||||||
|
# a nil message ID. Left and right angle brackets are required.
|
||||||
|
#
|
||||||
# Example:
|
# Example:
|
||||||
#
|
#
|
||||||
# mail = TMail::Mail.new
|
# mail = TMail::Mail.new
|
||||||
|
# mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
||||||
|
# mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
||||||
# mail.message_id = "this_is_my_badly_formatted_message_id"
|
# mail.message_id = "this_is_my_badly_formatted_message_id"
|
||||||
# mail.message_id #=> "this_is_my_badly_formatted_message_id"
|
# mail.message_id #=> nil
|
||||||
def message_id=( str )
|
def message_id=( str )
|
||||||
set_string_attr 'Message-Id', str
|
set_string_attr 'Message-Id', str
|
||||||
end
|
end
|
|
@ -32,7 +32,7 @@ module TMail
|
||||||
module VERSION
|
module VERSION
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 2
|
MINOR = 2
|
||||||
TINY = 2
|
TINY = 3
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
|
@ -1,8 +1,8 @@
|
||||||
module ActionMailer
|
module ActionMailer
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 0
|
MINOR = 1
|
||||||
TINY = 991
|
TINY = 0
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,6 +40,15 @@ class TestMailer < ActionMailer::Base
|
||||||
body "Nothing to see here."
|
body "Nothing to see here."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def different_reply_to(recipient)
|
||||||
|
recipients recipient
|
||||||
|
subject "testing reply_to"
|
||||||
|
from "system@loudthinking.com"
|
||||||
|
sent_on Time.local(2008, 5, 23)
|
||||||
|
reply_to "atraver@gmail.com"
|
||||||
|
body "Nothing to see here."
|
||||||
|
end
|
||||||
|
|
||||||
def iso_charset(recipient)
|
def iso_charset(recipient)
|
||||||
@recipients = recipient
|
@recipients = recipient
|
||||||
@subject = "testing isø charsets"
|
@subject = "testing isø charsets"
|
||||||
|
@ -445,6 +454,31 @@ class ActionMailerTest < Test::Unit::TestCase
|
||||||
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_reply_to
|
||||||
|
expected = new_mail
|
||||||
|
|
||||||
|
expected.to = @recipient
|
||||||
|
expected.subject = "testing reply_to"
|
||||||
|
expected.body = "Nothing to see here."
|
||||||
|
expected.from = "system@loudthinking.com"
|
||||||
|
expected.reply_to = "atraver@gmail.com"
|
||||||
|
expected.date = Time.local 2008, 5, 23
|
||||||
|
|
||||||
|
created = nil
|
||||||
|
assert_nothing_raised do
|
||||||
|
created = TestMailer.create_different_reply_to @recipient
|
||||||
|
end
|
||||||
|
assert_not_nil created
|
||||||
|
assert_equal expected.encoded, created.encoded
|
||||||
|
|
||||||
|
assert_nothing_raised do
|
||||||
|
TestMailer.deliver_different_reply_to @recipient
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_not_nil ActionMailer::Base.deliveries.first
|
||||||
|
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
|
||||||
|
end
|
||||||
|
|
||||||
def test_iso_charset
|
def test_iso_charset
|
||||||
expected = new_mail( "iso-8859-1" )
|
expected = new_mail( "iso-8859-1" )
|
||||||
expected.to = @recipient
|
expected.to = @recipient
|
||||||
|
|
5
vendor/rails/actionpack/CHANGELOG
vendored
5
vendor/rails/actionpack/CHANGELOG
vendored
|
@ -1,9 +1,12 @@
|
||||||
*2.1.0 RC1 (May 11th, 2008)*
|
*2.1.0 (May 31st, 2008)*
|
||||||
|
|
||||||
|
* InstanceTag#default_time_from_options overflows to DateTime [Geoff Buesing]
|
||||||
|
|
||||||
* Fixed that forgery protection can be used without session tracking (Peter Jones) [#139]
|
* Fixed that forgery protection can be used without session tracking (Peter Jones) [#139]
|
||||||
|
|
||||||
* Added session(:on) to turn session management back on in a controller subclass if the superclass turned it off (Peter Jones) [#136]
|
* Added session(:on) to turn session management back on in a controller subclass if the superclass turned it off (Peter Jones) [#136]
|
||||||
|
|
||||||
|
* Change the request forgery protection to go by Content-Type instead of request.format so that you can't bypass it by POSTing to "#{request.uri}.xml" [rick]
|
||||||
* InstanceTag#default_time_from_options with hash args uses Time.current as default; respects hash settings when time falls in system local spring DST gap [Geoff Buesing]
|
* InstanceTag#default_time_from_options with hash args uses Time.current as default; respects hash settings when time falls in system local spring DST gap [Geoff Buesing]
|
||||||
|
|
||||||
* select_date defaults to Time.zone.today when config.time_zone is set [Geoff Buesing]
|
* select_date defaults to Time.zone.today when config.time_zone is set [Geoff Buesing]
|
||||||
|
|
2
vendor/rails/actionpack/Rakefile
vendored
2
vendor/rails/actionpack/Rakefile
vendored
|
@ -76,7 +76,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
||||||
s.add_dependency('activesupport', '= 2.0.991' + PKG_BUILD)
|
s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD)
|
||||||
|
|
||||||
s.require_path = 'lib'
|
s.require_path = 'lib'
|
||||||
s.autorequire = 'action_controller'
|
s.autorequire = 'action_controller'
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
module Assertions
|
module Assertions
|
||||||
module ModelAssertions
|
module ModelAssertions
|
||||||
# Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not.
|
# Ensures that the passed record is valid by Active Record standards and
|
||||||
|
# returns any error messages if it is not.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
#
|
#
|
||||||
|
|
|
@ -59,7 +59,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Asserts that the provided options can be used to generate the provided path. This is the inverse of #assert_recognizes.
|
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
|
||||||
# The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
|
# The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
|
||||||
# a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
|
# a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
|
||||||
#
|
#
|
||||||
|
@ -96,8 +96,8 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
# Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
|
# Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
|
||||||
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines #assert_recognizes
|
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines +assert_recognizes+
|
||||||
# and #assert_generates into one step.
|
# and +assert_generates+ into one step.
|
||||||
#
|
#
|
||||||
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
|
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
|
||||||
# +message+ parameter allows you to specify a custom error message to display upon failure.
|
# +message+ parameter allows you to specify a custom error message to display upon failure.
|
||||||
|
|
|
@ -12,12 +12,12 @@ module ActionController
|
||||||
NO_STRIP = %w{pre script style textarea}
|
NO_STRIP = %w{pre script style textarea}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds the #assert_select method for use in Rails functional
|
# Adds the +assert_select+ method for use in Rails functional
|
||||||
# test cases, which can be used to make assertions on the response HTML of a controller
|
# test cases, which can be used to make assertions on the response HTML of a controller
|
||||||
# action. You can also call #assert_select within another #assert_select to
|
# action. You can also call +assert_select+ within another +assert_select+ to
|
||||||
# make assertions on elements selected by the enclosing assertion.
|
# make assertions on elements selected by the enclosing assertion.
|
||||||
#
|
#
|
||||||
# Use #css_select to select elements without making an assertions, either
|
# Use +css_select+ to select elements without making an assertions, either
|
||||||
# from the response HTML or elements selected by the enclosing assertion.
|
# from the response HTML or elements selected by the enclosing assertion.
|
||||||
#
|
#
|
||||||
# In addition to HTML responses, you can make the following assertions:
|
# In addition to HTML responses, you can make the following assertions:
|
||||||
|
@ -44,8 +44,8 @@ module ActionController
|
||||||
# base element and any of its children. Returns an empty array if no
|
# base element and any of its children. Returns an empty array if no
|
||||||
# match is found.
|
# match is found.
|
||||||
#
|
#
|
||||||
# The selector may be a CSS selector expression (+String+), an expression
|
# The selector may be a CSS selector expression (String), an expression
|
||||||
# with substitution values (+Array+) or an HTML::Selector object.
|
# with substitution values (Array) or an HTML::Selector object.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# # Selects all div tags
|
# # Selects all div tags
|
||||||
|
@ -114,8 +114,8 @@ module ActionController
|
||||||
# starting from (and including) that element and all its children in
|
# starting from (and including) that element and all its children in
|
||||||
# depth-first order.
|
# depth-first order.
|
||||||
#
|
#
|
||||||
# If no element if specified, calling #assert_select will select from the
|
# If no element if specified, calling +assert_select+ will select from the
|
||||||
# response HTML. Calling #assert_select inside an #assert_select block will
|
# response HTML. Calling #assert_select inside an +assert_select+ block will
|
||||||
# run the assertion for each element selected by the enclosing assertion.
|
# run the assertion for each element selected by the enclosing assertion.
|
||||||
#
|
#
|
||||||
# ==== Example
|
# ==== Example
|
||||||
|
@ -130,7 +130,7 @@ module ActionController
|
||||||
# assert_select "li"
|
# assert_select "li"
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# The selector may be a CSS selector expression (+String+), an expression
|
# The selector may be a CSS selector expression (String), an expression
|
||||||
# with substitution values, or an HTML::Selector object.
|
# with substitution values, or an HTML::Selector object.
|
||||||
#
|
#
|
||||||
# === Equality Tests
|
# === Equality Tests
|
||||||
|
@ -356,16 +356,16 @@ module ActionController
|
||||||
#
|
#
|
||||||
# === Using blocks
|
# === Using blocks
|
||||||
#
|
#
|
||||||
# Without a block, #assert_select_rjs merely asserts that the response
|
# Without a block, +assert_select_rjs+ merely asserts that the response
|
||||||
# contains one or more RJS statements that replace or update content.
|
# contains one or more RJS statements that replace or update content.
|
||||||
#
|
#
|
||||||
# With a block, #assert_select_rjs also selects all elements used in
|
# With a block, +assert_select_rjs+ also selects all elements used in
|
||||||
# these statements and passes them to the block. Nested assertions are
|
# these statements and passes them to the block. Nested assertions are
|
||||||
# supported.
|
# supported.
|
||||||
#
|
#
|
||||||
# Calling #assert_select_rjs with no arguments and using nested asserts
|
# Calling +assert_select_rjs+ with no arguments and using nested asserts
|
||||||
# asserts that the HTML content is returned by one or more RJS statements.
|
# asserts that the HTML content is returned by one or more RJS statements.
|
||||||
# Using #assert_select directly makes the same assertion on the content,
|
# Using +assert_select+ directly makes the same assertion on the content,
|
||||||
# but without distinguishing whether the content is returned in an HTML
|
# but without distinguishing whether the content is returned in an HTML
|
||||||
# or JavaScript.
|
# or JavaScript.
|
||||||
#
|
#
|
||||||
|
@ -601,7 +601,7 @@ module ActionController
|
||||||
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
|
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
|
||||||
end
|
end
|
||||||
|
|
||||||
# #assert_select and #css_select call this to obtain the content in the HTML
|
# +assert_select+ and +css_select+ call this to obtain the content in the HTML
|
||||||
# page, or from all the RJS statements, depending on the type of response.
|
# page, or from all the RJS statements, depending on the type of response.
|
||||||
def response_from_page_or_rjs()
|
def response_from_page_or_rjs()
|
||||||
content_type = @response.content_type
|
content_type = @response.content_type
|
||||||
|
|
|
@ -91,7 +91,7 @@ module ActionController
|
||||||
# :descendant => { :tag => "span",
|
# :descendant => { :tag => "span",
|
||||||
# :child => /hello world/ }
|
# :child => /hello world/ }
|
||||||
#
|
#
|
||||||
# <b>Please note</b>: #assert_tag and #assert_no_tag only work
|
# <b>Please note</b>: +assert_tag+ and +assert_no_tag+ only work
|
||||||
# with well-formed XHTML. They recognize a few tags as implicitly self-closing
|
# with well-formed XHTML. They recognize a few tags as implicitly self-closing
|
||||||
# (like br and hr and such) but will not work correctly with tags
|
# (like br and hr and such) but will not work correctly with tags
|
||||||
# that allow optional closing tags (p, li, td). <em>You must explicitly
|
# that allow optional closing tags (p, li, td). <em>You must explicitly
|
||||||
|
@ -104,8 +104,8 @@ module ActionController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Identical to #assert_tag, but asserts that a matching tag does _not_
|
# Identical to +assert_tag+, but asserts that a matching tag does _not_
|
||||||
# exist. (See #assert_tag for a full discussion of the syntax.)
|
# exist. (See +assert_tag+ for a full discussion of the syntax.)
|
||||||
#
|
#
|
||||||
# === Examples
|
# === Examples
|
||||||
# # Assert that there is not a "div" containing a "p"
|
# # Assert that there is not a "div" containing a "p"
|
||||||
|
|
|
@ -104,7 +104,7 @@ module ActionController #:nodoc:
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
|
# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
|
||||||
# after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the
|
# after executing code in the action. For example, the +index+ action of the GuestBookController would render the
|
||||||
# template <tt>app/views/guestbook/index.erb</tt> by default after populating the <tt>@entries</tt> instance variable.
|
# template <tt>app/views/guestbook/index.erb</tt> by default after populating the <tt>@entries</tt> instance variable.
|
||||||
#
|
#
|
||||||
# Unlike index, the sign action will not render a template. After performing its main purpose (creating a
|
# Unlike index, the sign action will not render a template. After performing its main purpose (creating a
|
||||||
|
@ -118,10 +118,10 @@ module ActionController #:nodoc:
|
||||||
#
|
#
|
||||||
# Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters.
|
# Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters.
|
||||||
# This value should hold the name of the action to be performed. Once the action has been identified, the remaining
|
# This value should hold the name of the action to be performed. Once the action has been identified, the remaining
|
||||||
# request parameters, the session (if one is available), and the full request with all the http headers are made available to
|
# request parameters, the session (if one is available), and the full request with all the HTTP headers are made available to
|
||||||
# the action through instance variables. Then the action is performed.
|
# the action through instance variables. Then the action is performed.
|
||||||
#
|
#
|
||||||
# The full request object is available with the request accessor and is primarily used to query for http headers. These queries
|
# The full request object is available with the request accessor and is primarily used to query for HTTP headers. These queries
|
||||||
# are made by accessing the environment hash, like this:
|
# are made by accessing the environment hash, like this:
|
||||||
#
|
#
|
||||||
# def server_ip
|
# def server_ip
|
||||||
|
@ -291,10 +291,10 @@ module ActionController #:nodoc:
|
||||||
cattr_accessor :allow_concurrency
|
cattr_accessor :allow_concurrency
|
||||||
|
|
||||||
# Modern REST web services often need to submit complex data to the web application.
|
# Modern REST web services often need to submit complex data to the web application.
|
||||||
# The param_parsers hash lets you register handlers which will process the http body and add parameters to the
|
# The <tt>@@param_parsers</tt> hash lets you register handlers which will process the HTTP body and add parameters to the
|
||||||
# <tt>params</tt> hash. These handlers are invoked for post and put requests.
|
# <tt>params</tt> hash. These handlers are invoked for POST and PUT requests.
|
||||||
#
|
#
|
||||||
# By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instantiated
|
# By default <tt>application/xml</tt> is enabled. A XmlSimple class with the same param name as the root will be instantiated
|
||||||
# in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one
|
# in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one
|
||||||
# action serve both regular forms and web service requests.
|
# action serve both regular forms and web service requests.
|
||||||
#
|
#
|
||||||
|
@ -307,7 +307,7 @@ module ActionController #:nodoc:
|
||||||
#
|
#
|
||||||
# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the
|
# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the
|
||||||
# root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results
|
# root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results
|
||||||
# in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can
|
# in <tt>params[:r][:name]</tt> for "David" instead of <tt>params[:name]</tt>. To get the old behavior, you can
|
||||||
# re-register XmlSimple as application/xml handler ike this:
|
# re-register XmlSimple as application/xml handler ike this:
|
||||||
#
|
#
|
||||||
# ActionController::Base.param_parsers[Mime::XML] =
|
# ActionController::Base.param_parsers[Mime::XML] =
|
||||||
|
@ -504,6 +504,7 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
filtered_parameters
|
filtered_parameters
|
||||||
end
|
end
|
||||||
|
protected :filter_parameters
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't render layouts for templates with the given extensions.
|
# Don't render layouts for templates with the given extensions.
|
||||||
|
|
|
@ -9,7 +9,7 @@ module ActionController #:nodoc:
|
||||||
# class ListsController < ApplicationController
|
# class ListsController < ApplicationController
|
||||||
# before_filter :authenticate, :except => :public
|
# before_filter :authenticate, :except => :public
|
||||||
# caches_page :public
|
# caches_page :public
|
||||||
# caches_action :show, :feed
|
# caches_action :index, :show, :feed
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
|
# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
|
||||||
|
@ -27,15 +27,19 @@ module ActionController #:nodoc:
|
||||||
# You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy
|
# You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy
|
||||||
# for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
|
# for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
|
||||||
#
|
#
|
||||||
|
# And you can also use :if to pass a Proc that specifies when the action should be cached.
|
||||||
|
#
|
||||||
# class ListsController < ApplicationController
|
# class ListsController < ApplicationController
|
||||||
# before_filter :authenticate, :except => :public
|
# before_filter :authenticate, :except => :public
|
||||||
# caches_page :public
|
# caches_page :public
|
||||||
|
# caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request
|
||||||
# caches_action :show, :cache_path => { :project => 1 }
|
# caches_action :show, :cache_path => { :project => 1 }
|
||||||
# caches_action :show, :cache_path => Proc.new { |controller|
|
# caches_action :feed, :cache_path => Proc.new { |controller|
|
||||||
# controller.params[:user_id] ?
|
# controller.params[:user_id] ?
|
||||||
# controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
|
# controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
|
||||||
# controller.send(:list_url, c.params[:id]) }
|
# controller.send(:list_url, c.params[:id]) }
|
||||||
# end
|
# end
|
||||||
|
#
|
||||||
module Actions
|
module Actions
|
||||||
def self.included(base) #:nodoc:
|
def self.included(base) #:nodoc:
|
||||||
base.extend(ClassMethods)
|
base.extend(ClassMethods)
|
||||||
|
@ -49,7 +53,8 @@ module ActionController #:nodoc:
|
||||||
# See ActionController::Caching::Actions for details.
|
# See ActionController::Caching::Actions for details.
|
||||||
def caches_action(*actions)
|
def caches_action(*actions)
|
||||||
return unless cache_configured?
|
return unless cache_configured?
|
||||||
around_filter(ActionCacheFilter.new(*actions))
|
options = actions.extract_options!
|
||||||
|
around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,16 +72,12 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionCacheFilter #:nodoc:
|
class ActionCacheFilter #:nodoc:
|
||||||
def initialize(*actions, &block)
|
def initialize(options, &block)
|
||||||
@options = actions.extract_options!
|
@options = options
|
||||||
@actions = Set.new(actions)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def before(controller)
|
def before(controller)
|
||||||
return unless @actions.include?(controller.action_name.intern)
|
|
||||||
|
|
||||||
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
|
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
|
||||||
|
|
||||||
if cache = controller.read_fragment(cache_path.path)
|
if cache = controller.read_fragment(cache_path.path)
|
||||||
controller.rendered_action_cache = true
|
controller.rendered_action_cache = true
|
||||||
set_content_type!(controller, cache_path.extension)
|
set_content_type!(controller, cache_path.extension)
|
||||||
|
@ -88,7 +89,7 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def after(controller)
|
def after(controller)
|
||||||
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller)
|
return if controller.rendered_action_cache || !caching_allowed(controller)
|
||||||
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
|
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,17 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Check if a cached fragment from the location signified by <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
|
||||||
|
def fragment_exist?(key, options = nil)
|
||||||
|
return unless cache_configured?
|
||||||
|
|
||||||
|
key = fragment_cache_key(key)
|
||||||
|
|
||||||
|
self.class.benchmark "Cached fragment exists?: #{key}" do
|
||||||
|
cache_store.exist?(key, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Name can take one of three forms:
|
# Name can take one of three forms:
|
||||||
# * String: This would normally take the form of a path like "pages/45/notes"
|
# * String: This would normally take the form of a path like "pages/45/notes"
|
||||||
# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
|
# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
|
||||||
|
|
|
@ -40,7 +40,7 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
sweepers.each do |sweeper|
|
sweepers.each do |sweeper|
|
||||||
ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
|
ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
|
||||||
sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(Inflector.classify(sweeper)) : sweeper).instance
|
sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance
|
||||||
|
|
||||||
if sweeper_instance.is_a?(Sweeper)
|
if sweeper_instance.is_a?(Sweeper)
|
||||||
around_filter(sweeper_instance, :only => configuration[:only])
|
around_filter(sweeper_instance, :only => configuration[:only])
|
||||||
|
|
|
@ -6,25 +6,24 @@ class CGI #:nodoc:
|
||||||
attr_accessor :name, :value, :path, :domain, :expires
|
attr_accessor :name, :value, :path, :domain, :expires
|
||||||
attr_reader :secure, :http_only
|
attr_reader :secure, :http_only
|
||||||
|
|
||||||
# Create a new CGI::Cookie object.
|
# Creates a new CGI::Cookie object.
|
||||||
#
|
#
|
||||||
# The contents of the cookie can be specified as a +name+ and one
|
# The contents of the cookie can be specified as a +name+ and one
|
||||||
# or more +value+ arguments. Alternatively, the contents can
|
# or more +value+ arguments. Alternatively, the contents can
|
||||||
# be specified as a single hash argument. The possible keywords of
|
# be specified as a single hash argument. The possible keywords of
|
||||||
# this hash are as follows:
|
# this hash are as follows:
|
||||||
#
|
#
|
||||||
# name:: the name of the cookie. Required.
|
# * <tt>:name</tt> - The name of the cookie. Required.
|
||||||
# value:: the cookie's value or list of values.
|
# * <tt>:value</tt> - The cookie's value or list of values.
|
||||||
# path:: the path for which this cookie applies. Defaults to the
|
# * <tt>:path</tt> - The path for which this cookie applies. Defaults to the
|
||||||
# base directory of the CGI script.
|
# base directory of the CGI script.
|
||||||
# domain:: the domain for which this cookie applies.
|
# * <tt>:domain</tt> - The domain for which this cookie applies.
|
||||||
# expires:: the time at which this cookie expires, as a +Time+ object.
|
# * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
|
||||||
# secure:: whether this cookie is a secure cookie or not (default to
|
# * <tt>:secure</tt> - Whether this cookie is a secure cookie or not (defaults to
|
||||||
# false). Secure cookies are only transmitted to HTTPS
|
# +false+). Secure cookies are only transmitted to HTTPS servers.
|
||||||
# servers.
|
# * <tt>:http_only</tt> - Whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP.
|
||||||
# http_only:: whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP
|
# More details in http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx. Defaults to +false+.
|
||||||
# More details: http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx
|
#
|
||||||
# Defaults to false.
|
|
||||||
# These keywords correspond to attributes of the cookie object.
|
# These keywords correspond to attributes of the cookie object.
|
||||||
def initialize(name = '', *value)
|
def initialize(name = '', *value)
|
||||||
if name.kind_of?(String)
|
if name.kind_of?(String)
|
||||||
|
@ -37,7 +36,7 @@ class CGI #:nodoc:
|
||||||
@path = nil
|
@path = nil
|
||||||
else
|
else
|
||||||
@name = name['name']
|
@name = name['name']
|
||||||
@value = Array(name['value'])
|
@value = (name['value'].kind_of?(String) ? [name['value']] : Array(name['value'])).delete_if(&:blank?)
|
||||||
@domain = name['domain']
|
@domain = name['domain']
|
||||||
@expires = name['expires']
|
@expires = name['expires']
|
||||||
@secure = name['secure'] || false
|
@secure = name['secure'] || false
|
||||||
|
@ -56,17 +55,17 @@ class CGI #:nodoc:
|
||||||
super(@value)
|
super(@value)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set whether the Cookie is a secure cookie or not.
|
# Sets whether the Cookie is a secure cookie or not.
|
||||||
def secure=(val)
|
def secure=(val)
|
||||||
@secure = val == true
|
@secure = val == true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set whether the Cookie is an HTTP only cookie or not.
|
# Sets whether the Cookie is an HTTP only cookie or not.
|
||||||
def http_only=(val)
|
def http_only=(val)
|
||||||
@http_only = val == true
|
@http_only = val == true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Convert the Cookie to its string representation.
|
# Converts the Cookie to its string representation.
|
||||||
def to_s
|
def to_s
|
||||||
buf = ''
|
buf = ''
|
||||||
buf << @name << '='
|
buf << @name << '='
|
||||||
|
@ -79,11 +78,17 @@ class CGI #:nodoc:
|
||||||
buf
|
buf
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse a raw cookie string into a hash of cookie-name=>Cookie
|
# FIXME: work around broken 1.8.7 DelegateClass#respond_to?
|
||||||
|
def respond_to?(method, include_private = false)
|
||||||
|
return true if super(method)
|
||||||
|
return __getobj__.respond_to?(method, include_private)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parses a raw cookie string into a hash of <tt>cookie-name => cookie-object</tt>
|
||||||
# pairs.
|
# pairs.
|
||||||
#
|
#
|
||||||
# cookies = CGI::Cookie::parse("raw_cookie_string")
|
# cookies = CGI::Cookie::parse("raw_cookie_string")
|
||||||
# # { "name1" => cookie1, "name2" => cookie2, ... }
|
# # => { "name1" => cookie1, "name2" => cookie2, ... }
|
||||||
#
|
#
|
||||||
def self.parse(raw_cookie)
|
def self.parse(raw_cookie)
|
||||||
cookies = Hash.new([])
|
cookies = Hash.new([])
|
||||||
|
|
|
@ -16,6 +16,7 @@ module ActionController
|
||||||
|
|
||||||
def initialize_with_stdinput(type = nil, stdinput = $stdin)
|
def initialize_with_stdinput(type = nil, stdinput = $stdin)
|
||||||
@stdinput = stdinput
|
@stdinput = stdinput
|
||||||
|
@stdinput.set_encoding(Encoding::BINARY) if @stdinput.respond_to?(:set_encoding)
|
||||||
initialize_without_stdinput(type || 'query')
|
initialize_without_stdinput(type || 'query')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@ module ActionController #:nodoc:
|
||||||
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
|
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
|
||||||
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
|
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
|
||||||
# an ArgumentError is raised.
|
# an ArgumentError is raised.
|
||||||
# * <tt>:session_expires</tt> - the time the current session expires, as a +Time+ object. If not set, the session will continue
|
# * <tt>:session_expires</tt> - the time the current session expires, as a Time object. If not set, the session will continue
|
||||||
# indefinitely.
|
# indefinitely.
|
||||||
# * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the
|
# * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the
|
||||||
# server.
|
# server.
|
||||||
|
@ -65,6 +65,7 @@ module ActionController #:nodoc:
|
||||||
# variable is already set, wrap it in a StringIO.
|
# variable is already set, wrap it in a StringIO.
|
||||||
def body
|
def body
|
||||||
if raw_post = env['RAW_POST_DATA']
|
if raw_post = env['RAW_POST_DATA']
|
||||||
|
raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
|
||||||
StringIO.new(raw_post)
|
StringIO.new(raw_post)
|
||||||
else
|
else
|
||||||
@cgi.stdinput
|
@cgi.stdinput
|
||||||
|
|
|
@ -100,10 +100,10 @@ module ActionController #:nodoc:
|
||||||
#
|
#
|
||||||
# Around filters wrap an action, executing code both before and after.
|
# Around filters wrap an action, executing code both before and after.
|
||||||
# They may be declared as method references, blocks, or objects responding
|
# They may be declared as method references, blocks, or objects responding
|
||||||
# to #filter or to both #before and #after.
|
# to +filter+ or to both +before+ and +after+.
|
||||||
#
|
#
|
||||||
# To use a method as an around_filter, pass a symbol naming the Ruby method.
|
# To use a method as an +around_filter+, pass a symbol naming the Ruby method.
|
||||||
# Yield (or block.call) within the method to run the action.
|
# Yield (or <tt>block.call</tt>) within the method to run the action.
|
||||||
#
|
#
|
||||||
# around_filter :catch_exceptions
|
# around_filter :catch_exceptions
|
||||||
#
|
#
|
||||||
|
@ -115,9 +115,9 @@ module ActionController #:nodoc:
|
||||||
# raise
|
# raise
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# To use a block as an around_filter, pass a block taking as args both
|
# To use a block as an +around_filter+, pass a block taking as args both
|
||||||
# the controller and the action block. You can't call yield directly from
|
# the controller and the action block. You can't call yield directly from
|
||||||
# an around_filter block; explicitly call the action block instead:
|
# an +around_filter+ block; explicitly call the action block instead:
|
||||||
#
|
#
|
||||||
# around_filter do |controller, action|
|
# around_filter do |controller, action|
|
||||||
# logger.debug "before #{controller.action_name}"
|
# logger.debug "before #{controller.action_name}"
|
||||||
|
@ -125,7 +125,7 @@ module ActionController #:nodoc:
|
||||||
# logger.debug "after #{controller.action_name}"
|
# logger.debug "after #{controller.action_name}"
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# To use a filter object with around_filter, pass an object responding
|
# To use a filter object with +around_filter+, pass an object responding
|
||||||
# to <tt>:filter</tt> or both <tt>:before</tt> and <tt>:after</tt>. With a
|
# to <tt>:filter</tt> or both <tt>:before</tt> and <tt>:after</tt>. With a
|
||||||
# filter method, yield to the block as above:
|
# filter method, yield to the block as above:
|
||||||
#
|
#
|
||||||
|
@ -137,7 +137,7 @@ module ActionController #:nodoc:
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# With before and after methods:
|
# With +before+ and +after+ methods:
|
||||||
#
|
#
|
||||||
# around_filter Authorizer.new
|
# around_filter Authorizer.new
|
||||||
#
|
#
|
||||||
|
@ -154,9 +154,9 @@ module ActionController #:nodoc:
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# If the filter has before and after methods, the before method will be
|
# If the filter has +before+ and +after+ methods, the +before+ method will be
|
||||||
# called before the action. If before renders or redirects, the filter chain is
|
# called before the action. If +before+ renders or redirects, the filter chain is
|
||||||
# halted and after will not be run. See Filter Chain Halting below for
|
# halted and +after+ will not be run. See Filter Chain Halting below for
|
||||||
# an example.
|
# an example.
|
||||||
#
|
#
|
||||||
# == Filter chain skipping
|
# == Filter chain skipping
|
||||||
|
@ -215,7 +215,7 @@ module ActionController #:nodoc:
|
||||||
#
|
#
|
||||||
# <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
|
# <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
|
||||||
# before a controller action is run. This is useful, for example, to deny
|
# before a controller action is run. This is useful, for example, to deny
|
||||||
# access to unauthenticated users or to redirect from http to https.
|
# access to unauthenticated users or to redirect from HTTP to HTTPS.
|
||||||
# Simply call render or redirect. After filters will not be executed if the filter
|
# Simply call render or redirect. After filters will not be executed if the filter
|
||||||
# chain is halted.
|
# chain is halted.
|
||||||
#
|
#
|
||||||
|
@ -241,10 +241,10 @@ module ActionController #:nodoc:
|
||||||
# . /
|
# . /
|
||||||
# #after (actual filter code is run, unless the around filter does not yield)
|
# #after (actual filter code is run, unless the around filter does not yield)
|
||||||
#
|
#
|
||||||
# If #around returns before yielding, #after will still not be run. The #before
|
# If +around+ returns before yielding, +after+ will still not be run. The +before+
|
||||||
# filter and controller action will not be run. If #before renders or redirects,
|
# filter and controller action will not be run. If +before+ renders or redirects,
|
||||||
# the second half of #around and will still run but #after and the
|
# the second half of +around+ and will still run but +after+ and the
|
||||||
# action will not. If #around fails to yield, #after will not be run.
|
# action will not. If +around+ fails to yield, +after+ will not be run.
|
||||||
|
|
||||||
class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc:
|
class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc:
|
||||||
def append_filter_to_chain(filters, filter_type, &block)
|
def append_filter_to_chain(filters, filter_type, &block)
|
||||||
|
@ -471,7 +471,7 @@ module ActionController #:nodoc:
|
||||||
# Shorthand for append_after_filter since it's the most common.
|
# Shorthand for append_after_filter since it's the most common.
|
||||||
alias :after_filter :append_after_filter
|
alias :after_filter :append_after_filter
|
||||||
|
|
||||||
# If you append_around_filter A.new, B.new, the filter chain looks like
|
# If you <tt>append_around_filter A.new, B.new</tt>, the filter chain looks like
|
||||||
#
|
#
|
||||||
# B#before
|
# B#before
|
||||||
# A#before
|
# A#before
|
||||||
|
@ -479,13 +479,13 @@ module ActionController #:nodoc:
|
||||||
# A#after
|
# A#after
|
||||||
# B#after
|
# B#after
|
||||||
#
|
#
|
||||||
# With around filters which yield to the action block, #before and #after
|
# With around filters which yield to the action block, +before+ and +after+
|
||||||
# are the code before and after the yield.
|
# are the code before and after the yield.
|
||||||
def append_around_filter(*filters, &block)
|
def append_around_filter(*filters, &block)
|
||||||
filter_chain.append_filter_to_chain(filters, :around, &block)
|
filter_chain.append_filter_to_chain(filters, :around, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# If you prepend_around_filter A.new, B.new, the filter chain looks like:
|
# If you <tt>prepend_around_filter A.new, B.new</tt>, the filter chain looks like:
|
||||||
#
|
#
|
||||||
# A#before
|
# A#before
|
||||||
# B#before
|
# B#before
|
||||||
|
@ -493,13 +493,13 @@ module ActionController #:nodoc:
|
||||||
# B#after
|
# B#after
|
||||||
# A#after
|
# A#after
|
||||||
#
|
#
|
||||||
# With around filters which yield to the action block, #before and #after
|
# With around filters which yield to the action block, +before+ and +after+
|
||||||
# are the code before and after the yield.
|
# are the code before and after the yield.
|
||||||
def prepend_around_filter(*filters, &block)
|
def prepend_around_filter(*filters, &block)
|
||||||
filter_chain.prepend_filter_to_chain(filters, :around, &block)
|
filter_chain.prepend_filter_to_chain(filters, :around, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Shorthand for append_around_filter since it's the most common.
|
# Shorthand for +append_around_filter+ since it's the most common.
|
||||||
alias :around_filter :append_around_filter
|
alias :around_filter :append_around_filter
|
||||||
|
|
||||||
# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference
|
# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference
|
||||||
|
|
|
@ -20,7 +20,7 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
# The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+,
|
# The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+,
|
||||||
# +numbers+ and +ActiveRecord+ objects, to name a few. These helpers are available to all templates
|
# +numbers+ and Active Record objects, to name a few. These helpers are available to all templates
|
||||||
# by default.
|
# by default.
|
||||||
#
|
#
|
||||||
# In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to
|
# In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to
|
||||||
|
@ -32,7 +32,7 @@ module ActionController #:nodoc:
|
||||||
# controller which inherits from it.
|
# controller which inherits from it.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# The +to_s+ method from the +Time+ class can be wrapped in a helper method to display a custom message if
|
# The +to_s+ method from the Time class can be wrapped in a helper method to display a custom message if
|
||||||
# the Time object is blank:
|
# the Time object is blank:
|
||||||
#
|
#
|
||||||
# module FormattedTimeHelper
|
# module FormattedTimeHelper
|
||||||
|
@ -41,7 +41,7 @@ module ActionController #:nodoc:
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# +FormattedTimeHelper+ can now be included in a controller, using the +helper+ class method:
|
# FormattedTimeHelper can now be included in a controller, using the +helper+ class method:
|
||||||
#
|
#
|
||||||
# class EventsController < ActionController::Base
|
# class EventsController < ActionController::Base
|
||||||
# helper FormattedTimeHelper
|
# helper FormattedTimeHelper
|
||||||
|
@ -74,22 +74,22 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
# The +helper+ class method can take a series of helper module names, a block, or both.
|
# The +helper+ class method can take a series of helper module names, a block, or both.
|
||||||
#
|
#
|
||||||
# * <tt>*args</tt>: One or more +Modules+, +Strings+ or +Symbols+, or the special symbol <tt>:all</tt>.
|
# * <tt>*args</tt>: One or more modules, strings or symbols, or the special symbol <tt>:all</tt>.
|
||||||
# * <tt>&block</tt>: A block defining helper methods.
|
# * <tt>&block</tt>: A block defining helper methods.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# When the argument is a +String+ or +Symbol+, the method will provide the "_helper" suffix, require the file
|
# When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
|
||||||
# and include the module in the template class. The second form illustrates how to include custom helpers
|
# and include the module in the template class. The second form illustrates how to include custom helpers
|
||||||
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
|
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
|
||||||
# in one of Rails' standard load paths:
|
# in one of Rails' standard load paths:
|
||||||
# helper :foo # => requires 'foo_helper' and includes FooHelper
|
# helper :foo # => requires 'foo_helper' and includes FooHelper
|
||||||
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
|
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
|
||||||
#
|
#
|
||||||
# When the argument is a +Module+, it will be included directly in the template class.
|
# When the argument is a module it will be included directly in the template class.
|
||||||
# helper FooHelper # => includes FooHelper
|
# helper FooHelper # => includes FooHelper
|
||||||
#
|
#
|
||||||
# When the argument is the symbol <tt>:all</tt>, the controller will include all helpers from
|
# When the argument is the symbol <tt>:all</tt>, the controller will include all helpers from
|
||||||
# <tt>app/helpers/**/*.rb</tt> under +RAILS_ROOT+.
|
# <tt>app/helpers/**/*.rb</tt> under RAILS_ROOT.
|
||||||
# helper :all
|
# helper :all
|
||||||
#
|
#
|
||||||
# Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
|
# Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
|
||||||
|
|
|
@ -58,7 +58,7 @@ module ActionController
|
||||||
class MultiPartNeededException < Exception
|
class MultiPartNeededException < Exception
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create and initialize a new +Session+ instance.
|
# Create and initialize a new Session instance.
|
||||||
def initialize
|
def initialize
|
||||||
reset!
|
reset!
|
||||||
end
|
end
|
||||||
|
@ -136,25 +136,25 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a GET request, following any subsequent redirect.
|
# Performs a GET request, following any subsequent redirect.
|
||||||
# See #request_via_redirect() for more information.
|
# See +request_via_redirect+ for more information.
|
||||||
def get_via_redirect(path, parameters = nil, headers = nil)
|
def get_via_redirect(path, parameters = nil, headers = nil)
|
||||||
request_via_redirect(:get, path, parameters, headers)
|
request_via_redirect(:get, path, parameters, headers)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a POST request, following any subsequent redirect.
|
# Performs a POST request, following any subsequent redirect.
|
||||||
# See #request_via_redirect() for more information.
|
# See +request_via_redirect+ for more information.
|
||||||
def post_via_redirect(path, parameters = nil, headers = nil)
|
def post_via_redirect(path, parameters = nil, headers = nil)
|
||||||
request_via_redirect(:post, path, parameters, headers)
|
request_via_redirect(:post, path, parameters, headers)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a PUT request, following any subsequent redirect.
|
# Performs a PUT request, following any subsequent redirect.
|
||||||
# See #request_via_redirect() for more information.
|
# See +request_via_redirect+ for more information.
|
||||||
def put_via_redirect(path, parameters = nil, headers = nil)
|
def put_via_redirect(path, parameters = nil, headers = nil)
|
||||||
request_via_redirect(:put, path, parameters, headers)
|
request_via_redirect(:put, path, parameters, headers)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a DELETE request, following any subsequent redirect.
|
# Performs a DELETE request, following any subsequent redirect.
|
||||||
# See #request_via_redirect() for more information.
|
# See +request_via_redirect+ for more information.
|
||||||
def delete_via_redirect(path, parameters = nil, headers = nil)
|
def delete_via_redirect(path, parameters = nil, headers = nil)
|
||||||
request_via_redirect(:delete, path, parameters, headers)
|
request_via_redirect(:delete, path, parameters, headers)
|
||||||
end
|
end
|
||||||
|
@ -166,12 +166,12 @@ module ActionController
|
||||||
|
|
||||||
# Performs a GET request with the given parameters. The parameters may
|
# Performs a GET request with the given parameters. The parameters may
|
||||||
# be +nil+, a Hash, or a string that is appropriately encoded
|
# be +nil+, a Hash, or a string that is appropriately encoded
|
||||||
# (application/x-www-form-urlencoded or multipart/form-data). The headers
|
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
|
||||||
# should be a hash. The keys will automatically be upcased, with the
|
# The headers should be a hash. The keys will automatically be upcased, with the
|
||||||
# prefix 'HTTP_' added if needed.
|
# prefix 'HTTP_' added if needed.
|
||||||
#
|
#
|
||||||
# You can also perform POST, PUT, DELETE, and HEAD requests with #post,
|
# You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
|
||||||
# #put, #delete, and #head.
|
# +put+, +delete+, and +head+.
|
||||||
def get(path, parameters = nil, headers = nil)
|
def get(path, parameters = nil, headers = nil)
|
||||||
process :get, path, parameters, headers
|
process :get, path, parameters, headers
|
||||||
end
|
end
|
||||||
|
@ -228,6 +228,8 @@ module ActionController
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
|
stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding)
|
||||||
|
stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding)
|
||||||
@stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
|
@stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -382,6 +384,8 @@ module ActionController
|
||||||
multipart_requestify(params).map do |key, value|
|
multipart_requestify(params).map do |key, value|
|
||||||
if value.respond_to?(:original_filename)
|
if value.respond_to?(:original_filename)
|
||||||
File.open(value.path) do |f|
|
File.open(value.path) do |f|
|
||||||
|
f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
|
||||||
|
|
||||||
<<-EOF
|
<<-EOF
|
||||||
--#{boundary}\r
|
--#{boundary}\r
|
||||||
Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
|
Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -17,6 +17,10 @@ module Mime
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class Type
|
class Type
|
||||||
|
@@html_types = Set.new [:html, :all]
|
||||||
|
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
|
||||||
|
cattr_reader :html_types, :unverifiable_types
|
||||||
|
|
||||||
# A simple helper class used in parsing the accept header
|
# A simple helper class used in parsing the accept header
|
||||||
class AcceptItem #:nodoc:
|
class AcceptItem #:nodoc:
|
||||||
attr_accessor :order, :name, :q
|
attr_accessor :order, :name, :q
|
||||||
|
@ -100,7 +104,7 @@ module Mime
|
||||||
list[text_xml].name = Mime::XML.to_s
|
list[text_xml].name = Mime::XML.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# Look for more specific xml-based types and sort them ahead of app/xml
|
# Look for more specific XML-based types and sort them ahead of app/xml
|
||||||
|
|
||||||
if app_xml
|
if app_xml
|
||||||
idx = app_xml
|
idx = app_xml
|
||||||
|
@ -154,11 +158,20 @@ module Mime
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
|
||||||
|
# ActionController::RequestForgerProtection.
|
||||||
|
def verify_request?
|
||||||
|
!@@unverifiable_types.include?(to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
|
def html?
|
||||||
|
@@html_types.include?(to_sym) || @string =~ /html/
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def method_missing(method, *args)
|
def method_missing(method, *args)
|
||||||
if method.to_s =~ /(\w+)\?$/
|
if method.to_s =~ /(\w+)\?$/
|
||||||
mime_type = $1.downcase.to_sym
|
$1.downcase.to_sym == to_sym
|
||||||
mime_type == @symbol || (mime_type == :html && @symbol == :all)
|
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
# Polymorphic URL helpers are methods for smart resolution to a named route call when
|
# Polymorphic URL helpers are methods for smart resolution to a named route call when
|
||||||
# given an ActiveRecord model instance. They are to be used in combination with
|
# given an Active Record model instance. They are to be used in combination with
|
||||||
# ActionController::Resources.
|
# ActionController::Resources.
|
||||||
#
|
#
|
||||||
# These methods are useful when you want to generate correct URL or path to a RESTful
|
# These methods are useful when you want to generate correct URL or path to a RESTful
|
||||||
|
@ -9,7 +9,9 @@ module ActionController
|
||||||
# Nested resources and/or namespaces are also supported, as illustrated in the example:
|
# Nested resources and/or namespaces are also supported, as illustrated in the example:
|
||||||
#
|
#
|
||||||
# polymorphic_url([:admin, @article, @comment])
|
# polymorphic_url([:admin, @article, @comment])
|
||||||
# #-> results in:
|
#
|
||||||
|
# results in:
|
||||||
|
#
|
||||||
# admin_article_comment_url(@article, @comment)
|
# admin_article_comment_url(@article, @comment)
|
||||||
#
|
#
|
||||||
# == Usage within the framework
|
# == Usage within the framework
|
||||||
|
@ -38,11 +40,8 @@ module ActionController
|
||||||
#
|
#
|
||||||
# Example usage:
|
# Example usage:
|
||||||
#
|
#
|
||||||
# edit_polymorphic_path(@post)
|
# edit_polymorphic_path(@post) # => "/posts/1/edit"
|
||||||
# #=> /posts/1/edit
|
# formatted_polymorphic_path([@post, :pdf]) # => "/posts/1.pdf"
|
||||||
#
|
|
||||||
# formatted_polymorphic_path([@post, :pdf])
|
|
||||||
# #=> /posts/1.pdf
|
|
||||||
module PolymorphicRoutes
|
module PolymorphicRoutes
|
||||||
# Constructs a call to a named RESTful route for the given record and returns the
|
# Constructs a call to a named RESTful route for the given record and returns the
|
||||||
# resulting URL string. For example:
|
# resulting URL string. For example:
|
||||||
|
|
|
@ -466,8 +466,8 @@ EOM
|
||||||
parser.result
|
parser.result
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_multipart_form_parameters(body, boundary, content_length, env)
|
def parse_multipart_form_parameters(body, boundary, body_size, env)
|
||||||
parse_request_parameters(read_multipart(body, boundary, content_length, env))
|
parse_request_parameters(read_multipart(body, boundary, body_size, env))
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_multipart_boundary(content_type_with_parameters)
|
def extract_multipart_boundary(content_type_with_parameters)
|
||||||
|
@ -519,7 +519,7 @@ EOM
|
||||||
|
|
||||||
EOL = "\015\012"
|
EOL = "\015\012"
|
||||||
|
|
||||||
def read_multipart(body, boundary, content_length, env)
|
def read_multipart(body, boundary, body_size, env)
|
||||||
params = Hash.new([])
|
params = Hash.new([])
|
||||||
boundary = "--" + boundary
|
boundary = "--" + boundary
|
||||||
quoted_boundary = Regexp.quote(boundary)
|
quoted_boundary = Regexp.quote(boundary)
|
||||||
|
@ -529,8 +529,14 @@ EOM
|
||||||
|
|
||||||
# start multipart/form-data
|
# start multipart/form-data
|
||||||
body.binmode if defined? body.binmode
|
body.binmode if defined? body.binmode
|
||||||
|
case body
|
||||||
|
when File
|
||||||
|
body.set_encoding(Encoding::BINARY) if body.respond_to?(:set_encoding)
|
||||||
|
when StringIO
|
||||||
|
body.string.force_encoding(Encoding::BINARY) if body.string.respond_to?(:force_encoding)
|
||||||
|
end
|
||||||
boundary_size = boundary.size + EOL.size
|
boundary_size = boundary.size + EOL.size
|
||||||
content_length -= boundary_size
|
body_size -= boundary_size
|
||||||
status = body.read(boundary_size)
|
status = body.read(boundary_size)
|
||||||
if nil == status
|
if nil == status
|
||||||
raise EOFError, "no content body"
|
raise EOFError, "no content body"
|
||||||
|
@ -541,7 +547,7 @@ EOM
|
||||||
loop do
|
loop do
|
||||||
head = nil
|
head = nil
|
||||||
content =
|
content =
|
||||||
if 10240 < content_length
|
if 10240 < body_size
|
||||||
UploadedTempfile.new("CGI")
|
UploadedTempfile.new("CGI")
|
||||||
else
|
else
|
||||||
UploadedStringIO.new
|
UploadedStringIO.new
|
||||||
|
@ -563,22 +569,22 @@ EOM
|
||||||
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
|
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
c = if bufsize < content_length
|
c = if bufsize < body_size
|
||||||
body.read(bufsize)
|
body.read(bufsize)
|
||||||
else
|
else
|
||||||
body.read(content_length)
|
body.read(body_size)
|
||||||
end
|
end
|
||||||
if c.nil? || c.empty?
|
if c.nil? || c.empty?
|
||||||
raise EOFError, "bad content body"
|
raise EOFError, "bad content body"
|
||||||
end
|
end
|
||||||
buf.concat(c)
|
buf.concat(c)
|
||||||
content_length -= c.size
|
body_size -= c.size
|
||||||
end
|
end
|
||||||
|
|
||||||
buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
|
buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
|
||||||
content.print $1
|
content.print $1
|
||||||
if "--" == $2
|
if "--" == $2
|
||||||
content_length = -1
|
body_size = -1
|
||||||
end
|
end
|
||||||
boundary_end = $2.dup
|
boundary_end = $2.dup
|
||||||
""
|
""
|
||||||
|
@ -607,7 +613,7 @@ EOM
|
||||||
else
|
else
|
||||||
params[name] = [content]
|
params[name] = [content]
|
||||||
end
|
end
|
||||||
break if content_length == -1
|
break if body_size == -1
|
||||||
end
|
end
|
||||||
raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
|
raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def verifiable_request_format?
|
def verifiable_request_format?
|
||||||
request.format.html? || request.format.js?
|
request.content_type.nil? || request.content_type.verify_request?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
|
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
|
||||||
|
|
|
@ -17,13 +17,13 @@ module ActionController
|
||||||
reset!
|
reset!
|
||||||
end
|
end
|
||||||
|
|
||||||
def benchmark(n)
|
def benchmark(n, profiling = false)
|
||||||
@quiet = true
|
@quiet = true
|
||||||
print ' '
|
print ' '
|
||||||
|
|
||||||
result = Benchmark.realtime do
|
result = Benchmark.realtime do
|
||||||
n.times do |i|
|
n.times do |i|
|
||||||
run
|
run(profiling)
|
||||||
print_progress(i)
|
print_progress(i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -43,8 +43,15 @@ module ActionController
|
||||||
script = File.read(script_path)
|
script = File.read(script_path)
|
||||||
|
|
||||||
source = <<-end_source
|
source = <<-end_source
|
||||||
def run
|
def run(profiling = false)
|
||||||
|
if profiling
|
||||||
|
RubyProf.resume do
|
||||||
#{script}
|
#{script}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
#{script}
|
||||||
|
end
|
||||||
|
|
||||||
old_request_count = request_count
|
old_request_count = request_count
|
||||||
reset!
|
reset!
|
||||||
self.request_count = old_request_count
|
self.request_count = old_request_count
|
||||||
|
@ -91,21 +98,22 @@ module ActionController
|
||||||
def profile(sandbox)
|
def profile(sandbox)
|
||||||
load_ruby_prof
|
load_ruby_prof
|
||||||
|
|
||||||
results = RubyProf.profile { benchmark(sandbox) }
|
benchmark(sandbox, true)
|
||||||
|
results = RubyProf.stop
|
||||||
|
|
||||||
show_profile_results results
|
show_profile_results results
|
||||||
results
|
results
|
||||||
end
|
end
|
||||||
|
|
||||||
def benchmark(sandbox)
|
def benchmark(sandbox, profiling = false)
|
||||||
sandbox.request_count = 0
|
sandbox.request_count = 0
|
||||||
elapsed = sandbox.benchmark(options[:n]).to_f
|
elapsed = sandbox.benchmark(options[:n], profiling).to_f
|
||||||
count = sandbox.request_count.to_i
|
count = sandbox.request_count.to_i
|
||||||
puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed]
|
puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed]
|
||||||
end
|
end
|
||||||
|
|
||||||
def warmup(sandbox)
|
def warmup(sandbox)
|
||||||
Benchmark.realtime { sandbox.run }
|
Benchmark.realtime { sandbox.run(false) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_options
|
def default_options
|
||||||
|
@ -136,6 +144,7 @@ module ActionController
|
||||||
protected
|
protected
|
||||||
def load_ruby_prof
|
def load_ruby_prof
|
||||||
begin
|
begin
|
||||||
|
gem 'ruby-prof', '>= 0.6.1'
|
||||||
require 'ruby-prof'
|
require 'ruby-prof'
|
||||||
if mode = options[:measure]
|
if mode = options[:measure]
|
||||||
RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
|
RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
|
||||||
|
|
|
@ -199,10 +199,8 @@ module ActionController #:nodoc:
|
||||||
private
|
private
|
||||||
def perform_action_with_rescue #:nodoc:
|
def perform_action_with_rescue #:nodoc:
|
||||||
perform_action_without_rescue
|
perform_action_without_rescue
|
||||||
rescue Exception => exception # errors from action performed
|
rescue Exception => exception
|
||||||
return if rescue_action_with_handler(exception)
|
rescue_action_with_handler(exception) || rescue_action(exception)
|
||||||
|
|
||||||
rescue_action(exception)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rescues_path(template_name)
|
def rescues_path(template_name)
|
||||||
|
|
|
@ -191,7 +191,7 @@ module ActionController
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Along with the routes themselves, #resources generates named routes for use in
|
# Along with the routes themselves, +resources+ generates named routes for use in
|
||||||
# controllers and views. <tt>map.resources :messages</tt> produces the following named routes and helpers:
|
# controllers and views. <tt>map.resources :messages</tt> produces the following named routes and helpers:
|
||||||
#
|
#
|
||||||
# Named Route Helpers
|
# Named Route Helpers
|
||||||
|
@ -208,7 +208,7 @@ module ActionController
|
||||||
# edit_message edit_message_url(id), hash_for_edit_message_url(id),
|
# edit_message edit_message_url(id), hash_for_edit_message_url(id),
|
||||||
# edit_message_path(id), hash_for_edit_message_path(id)
|
# edit_message_path(id), hash_for_edit_message_path(id)
|
||||||
#
|
#
|
||||||
# You can use these helpers instead of #url_for or methods that take #url_for parameters. For example:
|
# You can use these helpers instead of +url_for+ or methods that take +url_for+ parameters. For example:
|
||||||
#
|
#
|
||||||
# redirect_to :controller => 'messages', :action => 'index'
|
# redirect_to :controller => 'messages', :action => 'index'
|
||||||
# # and
|
# # and
|
||||||
|
@ -406,7 +406,7 @@ module ActionController
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Along with the routes themselves, #resource generates named routes for
|
# Along with the routes themselves, +resource+ generates named routes for
|
||||||
# use in controllers and views. <tt>map.resource :account</tt> produces
|
# use in controllers and views. <tt>map.resource :account</tt> produces
|
||||||
# these named routes and helpers:
|
# these named routes and helpers:
|
||||||
#
|
#
|
||||||
|
|
|
@ -23,9 +23,9 @@ module ActionController
|
||||||
# Accepts a "route path" (a string defining a route), and returns the array
|
# Accepts a "route path" (a string defining a route), and returns the array
|
||||||
# of segments that corresponds to it. Note that the segment array is only
|
# of segments that corresponds to it. Note that the segment array is only
|
||||||
# partially initialized--the defaults and requirements, for instance, need
|
# partially initialized--the defaults and requirements, for instance, need
|
||||||
# to be set separately, via the #assign_route_options method, and the
|
# to be set separately, via the +assign_route_options+ method, and the
|
||||||
# #optional? method for each segment will not be reliable until after
|
# <tt>optional?</tt> method for each segment will not be reliable until after
|
||||||
# #assign_route_options is called, as well.
|
# +assign_route_options+ is called, as well.
|
||||||
def segments_for_route_path(path)
|
def segments_for_route_path(path)
|
||||||
rest, segments = path, []
|
rest, segments = path, []
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_value
|
def extract_value
|
||||||
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component) }.to_param #{"|| #{default.inspect}" if default}"
|
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def default
|
def default
|
||||||
|
|
|
@ -34,7 +34,7 @@ require 'openssl' # to generate the HMAC message digest
|
||||||
# such as 'MD5', 'RIPEMD160', 'SHA256', etc.
|
# such as 'MD5', 'RIPEMD160', 'SHA256', etc.
|
||||||
#
|
#
|
||||||
# To generate a secret key for an existing application, run
|
# To generate a secret key for an existing application, run
|
||||||
# `rake secret` and set the key in config/environment.rb.
|
# "rake secret" and set the key in config/environment.rb.
|
||||||
#
|
#
|
||||||
# Note that changing digest or secret invalidates all existing sessions!
|
# Note that changing digest or secret invalidates all existing sessions!
|
||||||
class CGI::Session::CookieStore
|
class CGI::Session::CookieStore
|
||||||
|
@ -130,17 +130,20 @@ class CGI::Session::CookieStore
|
||||||
# Marshal a session hash into safe cookie data. Include an integrity hash.
|
# Marshal a session hash into safe cookie data. Include an integrity hash.
|
||||||
def marshal(session)
|
def marshal(session)
|
||||||
data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop
|
data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop
|
||||||
CGI.escape "#{data}--#{generate_digest(data)}"
|
"#{data}--#{generate_digest(data)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Unmarshal cookie data to a hash and verify its integrity.
|
# Unmarshal cookie data to a hash and verify its integrity.
|
||||||
def unmarshal(cookie)
|
def unmarshal(cookie)
|
||||||
if cookie
|
if cookie
|
||||||
data, digest = CGI.unescape(cookie).split('--')
|
data, digest = cookie.split('--')
|
||||||
unless digest == generate_digest(data)
|
|
||||||
|
# Do two checks to transparently support old double-escaped data.
|
||||||
|
unless digest == generate_digest(data) || digest == generate_digest(data = CGI.unescape(data))
|
||||||
delete
|
delete
|
||||||
raise TamperedWithCookie
|
raise TamperedWithCookie
|
||||||
end
|
end
|
||||||
|
|
||||||
Marshal.load(ActiveSupport::Base64.decode64(data))
|
Marshal.load(ActiveSupport::Base64.decode64(data))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ require 'action_controller/test_case'
|
||||||
|
|
||||||
module ActionController #:nodoc:
|
module ActionController #:nodoc:
|
||||||
class Base
|
class Base
|
||||||
# Process a test request called with a +TestRequest+ object.
|
# Process a test request called with a TestRequest object.
|
||||||
def self.process_test(request)
|
def self.process_test(request)
|
||||||
new.process_test(request)
|
new.process_test(request)
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,7 @@ module ActionController #:nodoc:
|
||||||
# Either the RAW_POST_DATA environment variable or the URL-encoded request
|
# Either the RAW_POST_DATA environment variable or the URL-encoded request
|
||||||
# parameters.
|
# parameters.
|
||||||
def raw_post
|
def raw_post
|
||||||
env['RAW_POST_DATA'] ||= url_encoded_request_parameters
|
env['RAW_POST_DATA'] ||= returning(url_encoded_request_parameters) { |b| b.force_encoding(Encoding::BINARY) if b.respond_to?(:force_encoding) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def port=(number)
|
def port=(number)
|
||||||
|
@ -340,6 +340,7 @@ module ActionController #:nodoc:
|
||||||
@content_type = content_type
|
@content_type = content_type
|
||||||
@original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 }
|
@original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 }
|
||||||
@tempfile = Tempfile.new(@original_filename)
|
@tempfile = Tempfile.new(@original_filename)
|
||||||
|
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
||||||
@tempfile.binmode if binary
|
@tempfile.binmode if binary
|
||||||
FileUtils.copy_file(path, @tempfile.path)
|
FileUtils.copy_file(path, @tempfile.path)
|
||||||
end
|
end
|
||||||
|
@ -357,7 +358,7 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
module TestProcess
|
module TestProcess
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
# execute the request simulating a specific http method and set/volley the response
|
# execute the request simulating a specific HTTP method and set/volley the response
|
||||||
%w( get post put delete head ).each do |method|
|
%w( get post put delete head ).each do |method|
|
||||||
base.class_eval <<-EOV, __FILE__, __LINE__
|
base.class_eval <<-EOV, __FILE__, __LINE__
|
||||||
def #{method}(action, parameters = nil, session = nil, flash = nil)
|
def #{method}(action, parameters = nil, session = nil, flash = nil)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
module ActionPack #:nodoc:
|
module ActionPack #:nodoc:
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 0
|
MINOR = 1
|
||||||
TINY = 991
|
TINY = 0
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
@ -169,10 +169,10 @@ module ActionView #:nodoc:
|
||||||
@@cache_template_loading = false
|
@@cache_template_loading = false
|
||||||
cattr_accessor :cache_template_loading
|
cattr_accessor :cache_template_loading
|
||||||
|
|
||||||
# Specify whether file extension lookup should be cached, and whether template base path lookup should be cached.
|
def self.cache_template_extensions=(*args)
|
||||||
# Should be +false+ for development environments. Defaults to +true+.
|
ActiveSupport::Deprecation.warn("config.action_view.cache_template_extensions option has been deprecated and has no affect. " <<
|
||||||
@@cache_template_extensions = true
|
"Please remove it from your config files.", caller)
|
||||||
cattr_accessor :cache_template_extensions
|
end
|
||||||
|
|
||||||
# Specify whether RJS responses should be wrapped in a try/catch block
|
# Specify whether RJS responses should be wrapped in a try/catch block
|
||||||
# that alert()s the caught exception (and then re-raises it).
|
# that alert()s the caught exception (and then re-raises it).
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
module ActionView
|
|
||||||
|
|
||||||
# CompiledTemplates modules hold methods that have been compiled.
|
|
||||||
# Templates are compiled into these methods so that they do not need to be
|
|
||||||
# read and parsed for each request.
|
|
||||||
#
|
|
||||||
# Each template may be compiled into one or more methods. Each method accepts a given
|
|
||||||
# set of parameters which is used to implement local assigns passing.
|
|
||||||
#
|
|
||||||
# To use a compiled template module, create a new instance and include it into the class
|
|
||||||
# in which you want the template to be rendered.
|
|
||||||
class CompiledTemplates < Module
|
|
||||||
attr_reader :method_names
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@method_names = Hash.new do |hash, key|
|
|
||||||
hash[key] = "__compiled_method_#{(hash.length + 1)}"
|
|
||||||
end
|
|
||||||
@mtimes = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the full key for the given identifier and argument names
|
|
||||||
def full_key(identifier, arg_names)
|
|
||||||
[identifier, arg_names]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the selector for this method or nil if it has not been compiled
|
|
||||||
def selector(identifier, arg_names)
|
|
||||||
key = full_key(identifier, arg_names)
|
|
||||||
method_names.key?(key) ? method_names[key] : nil
|
|
||||||
end
|
|
||||||
alias :compiled? :selector
|
|
||||||
|
|
||||||
# Return the time at which the method for the given identifier and argument names was compiled.
|
|
||||||
def mtime(identifier, arg_names)
|
|
||||||
@mtimes[full_key(identifier, arg_names)]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Compile the provided source code for the given argument names and with the given initial line number.
|
|
||||||
# The identifier should be unique to this source.
|
|
||||||
#
|
|
||||||
# The file_name, if provided will appear in backtraces. If not provided, the file_name defaults
|
|
||||||
# to the identifier.
|
|
||||||
#
|
|
||||||
# This method will return the selector for the compiled version of this method.
|
|
||||||
def compile_source(identifier, arg_names, source, initial_line_number = 0, file_name = nil)
|
|
||||||
file_name ||= identifier
|
|
||||||
name = method_names[full_key(identifier, arg_names)]
|
|
||||||
arg_desc = arg_names.empty? ? '' : "(#{arg_names * ', '})"
|
|
||||||
fake_file_name = "#{file_name}#{arg_desc}" # Include the arguments for this version (for now)
|
|
||||||
|
|
||||||
method_def = wrap_source(name, arg_names, source)
|
|
||||||
|
|
||||||
begin
|
|
||||||
module_eval(method_def, fake_file_name, initial_line_number)
|
|
||||||
@mtimes[full_key(identifier, arg_names)] = Time.now
|
|
||||||
rescue Exception => e # errors from compiled source
|
|
||||||
e.blame_file! identifier
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
name
|
|
||||||
end
|
|
||||||
|
|
||||||
# Wrap the provided source in a def ... end block.
|
|
||||||
def wrap_source(name, arg_names, source)
|
|
||||||
"def #{name}(#{arg_names * ', '})\n#{source}\nend"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -11,8 +11,8 @@ module ActionView
|
||||||
# === Using asset hosts
|
# === Using asset hosts
|
||||||
# By default, Rails links to these assets on the current host in the public
|
# By default, Rails links to these assets on the current host in the public
|
||||||
# folder, but you can direct Rails to link to assets from a dedicated assets server by
|
# folder, but you can direct Rails to link to assets from a dedicated assets server by
|
||||||
# setting ActionController::Base.asset_host in your environment.rb. For example,
|
# setting ActionController::Base.asset_host in your <tt>config/environment.rb</tt>. For example,
|
||||||
# let's say your asset host is assets.example.com.
|
# let's say your asset host is <tt>assets.example.com</tt>.
|
||||||
#
|
#
|
||||||
# ActionController::Base.asset_host = "assets.example.com"
|
# ActionController::Base.asset_host = "assets.example.com"
|
||||||
# image_tag("rails.png")
|
# image_tag("rails.png")
|
||||||
|
@ -22,8 +22,8 @@ module ActionView
|
||||||
#
|
#
|
||||||
# This is useful since browsers typically open at most two connections to a single host,
|
# This is useful since browsers typically open at most two connections to a single host,
|
||||||
# which means your assets often wait in single file for their turn to load. You can
|
# which means your assets often wait in single file for their turn to load. You can
|
||||||
# alleviate this by using a %d wildcard in <tt>asset_host</tt> (for example, "assets%d.example.com")
|
# alleviate this by using a <tt>%d</tt> wildcard in <tt>asset_host</tt> (for example, "assets%d.example.com")
|
||||||
# to automatically distribute asset requests among four hosts (e.g., assets0.example.com through assets3.example.com)
|
# to automatically distribute asset requests among four hosts (e.g., "assets0.example.com" through "assets3.example.com")
|
||||||
# so browsers will open eight connections rather than two.
|
# so browsers will open eight connections rather than two.
|
||||||
#
|
#
|
||||||
# image_tag("rails.png")
|
# image_tag("rails.png")
|
||||||
|
@ -293,9 +293,9 @@ module ActionView
|
||||||
end
|
end
|
||||||
|
|
||||||
# Computes the path to a stylesheet asset in the public stylesheets directory.
|
# Computes the path to a stylesheet asset in the public stylesheets directory.
|
||||||
# If the +source+ filename has no extension, .css will be appended.
|
# If the +source+ filename has no extension, <tt>.css</tt> will be appended.
|
||||||
# Full paths from the document root will be passed through.
|
# Full paths from the document root will be passed through.
|
||||||
# Used internally by stylesheet_link_tag to build the stylesheet path.
|
# Used internally by +stylesheet_link_tag+ to build the stylesheet path.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# stylesheet_path "style" # => /stylesheets/style.css
|
# stylesheet_path "style" # => /stylesheets/style.css
|
||||||
|
@ -309,7 +309,7 @@ module ActionView
|
||||||
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
|
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
|
||||||
|
|
||||||
# Returns a stylesheet link tag for the sources specified as arguments. If
|
# Returns a stylesheet link tag for the sources specified as arguments. If
|
||||||
# you don't specify an extension, .css will be appended automatically.
|
# you don't specify an extension, <tt>.css</tt> will be appended automatically.
|
||||||
# You can modify the link attributes by passing a hash as the last argument.
|
# You can modify the link attributes by passing a hash as the last argument.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
|
@ -379,7 +379,7 @@ module ActionView
|
||||||
|
|
||||||
# Computes the path to an image asset in the public images directory.
|
# Computes the path to an image asset in the public images directory.
|
||||||
# Full paths from the document root will be passed through.
|
# Full paths from the document root will be passed through.
|
||||||
# Used internally by image_tag to build the image path.
|
# Used internally by +image_tag+ to build the image path.
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# image_path("edit") # => /images/edit
|
# image_path("edit") # => /images/edit
|
||||||
|
@ -454,8 +454,8 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add the .ext if not present. Return full URLs otherwise untouched.
|
# Add the the extension +ext+ if not present. Return full URLs otherwise untouched.
|
||||||
# Prefix with /dir/ if lacking a leading /. Account for relative URL
|
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
|
||||||
# roots. Rewrite the asset path for cache-busting asset ids. Include
|
# roots. Rewrite the asset path for cache-busting asset ids. Include
|
||||||
# asset host, if configured, with the correct request protocol.
|
# asset host, if configured, with the correct request protocol.
|
||||||
def compute_public_path(source, dir, ext = nil, include_host = true)
|
def compute_public_path(source, dir, ext = nil, include_host = true)
|
||||||
|
@ -502,9 +502,9 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Pick an asset host for this source. Returns nil if no host is set,
|
# Pick an asset host for this source. Returns +nil+ if no host is set,
|
||||||
# the host if no wildcard is set, the host interpolated with the
|
# the host if no wildcard is set, the host interpolated with the
|
||||||
# numbers 0-3 if it contains %d (the number is the source hash mod 4),
|
# numbers 0-3 if it contains <tt>%d</tt> (the number is the source hash mod 4),
|
||||||
# or the value returned from invoking the proc if it's a proc.
|
# or the value returned from invoking the proc if it's a proc.
|
||||||
def compute_asset_host(source)
|
def compute_asset_host(source)
|
||||||
if host = ActionController::Base.asset_host
|
if host = ActionController::Base.asset_host
|
||||||
|
|
|
@ -689,7 +689,7 @@ module ActionView
|
||||||
default[key] ||= time.send(key)
|
default[key] ||= time.send(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
Time.utc(default[:year], default[:month], default[:day], default[:hour], default[:min], default[:sec])
|
Time.utc_time(default[:year], default[:month], default[:day], default[:hour], default[:min], default[:sec])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -73,30 +73,81 @@ 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.
|
||||||
#
|
#
|
||||||
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
# Rails provides succint resource-oriented form generation with +form_for+
|
||||||
# <%= f.error_messages %>
|
# like this:
|
||||||
# First name: <%= f.text_field :first_name %>
|
#
|
||||||
# Last name : <%= f.text_field :last_name %>
|
# <% form_for @offer do |f| %>
|
||||||
# Biography : <%= f.text_area :biography %>
|
# <%= f.label :version, 'Version' %>:
|
||||||
# Admin? : <%= f.check_box :admin %>
|
# <%= f.text_field :version %><br />
|
||||||
|
# <%= f.label :author, 'Author' %>:
|
||||||
|
# <%= f.text_field :author %><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>,
|
# There, +form_for+ is able to generate the rest of RESTful form parameters
|
||||||
# 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
|
# based on introspection on the record, but to understand what it does we
|
||||||
# the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,
|
# need to dig first into the alternative generic usage it is based upon.
|
||||||
# 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
|
# === Generic form_for
|
||||||
# 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
|
# The generic way to call +form_for+ yields a form builder around a model:
|
||||||
# and methods from FormTagHelper. For example:
|
#
|
||||||
|
# <% form_for :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 %>
|
||||||
|
#
|
||||||
|
# There, the first argument is a symbol or string with the name of the
|
||||||
|
# object the form is about, and also the name of the instance variable the
|
||||||
|
# object is stored in.
|
||||||
|
#
|
||||||
|
# The form builder acts as a regular form helper that somehow carries the
|
||||||
|
# model. Thus, the idea is that
|
||||||
|
#
|
||||||
|
# <%= f.text_field :first_name %>
|
||||||
|
#
|
||||||
|
# gets expanded to
|
||||||
|
#
|
||||||
|
# <%= text_field :person, :first_name %>
|
||||||
|
#
|
||||||
|
# If the instance variable is not <tt>@person</tt> you can pass the actual
|
||||||
|
# record as the second argument:
|
||||||
|
#
|
||||||
|
# <% form_for :person, person, :url => { :action => "update" } do |f| %>
|
||||||
|
# ...
|
||||||
|
# <% end %>
|
||||||
|
#
|
||||||
|
# In that case you can think
|
||||||
|
#
|
||||||
|
# <%= f.text_field :first_name %>
|
||||||
|
#
|
||||||
|
# gets expanded to
|
||||||
|
#
|
||||||
|
# <%= text_field :person, :first_name, :object => person %>
|
||||||
|
#
|
||||||
|
# You can even display error messages of the wrapped model this way:
|
||||||
|
#
|
||||||
|
# <%= f.error_messages %>
|
||||||
|
#
|
||||||
|
# In any of its variants, the rightmost argument to +form_for+ is an
|
||||||
|
# optional hash of options:
|
||||||
|
#
|
||||||
|
# * <tt>:url</tt> - The URL the form is submitted to. It takes the same fields
|
||||||
|
# you pass to +url_for+ or +link_to+. In particular you may pass here a
|
||||||
|
# named route directly as well. Defaults to the current action.
|
||||||
|
# * <tt>:html</tt> - Optional HTML attributes for the form tag.
|
||||||
|
#
|
||||||
|
# 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 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| %>
|
# <% form_for :person, @person, :url => { :action => "update" } do |f| %>
|
||||||
# First name: <%= f.text_field :first_name %>
|
# First name: <%= f.text_field :first_name %>
|
||||||
|
@ -105,42 +156,38 @@ 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:
|
# === Resource-oriented style
|
||||||
#
|
#
|
||||||
# <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>
|
# As we said above, in addition to manually configuring the +form_for+ call,
|
||||||
|
# you can rely on automated resource identification, which will use the conventions
|
||||||
|
# and named routes of that approach. This is the preferred way to use +form_for+
|
||||||
|
# nowadays.
|
||||||
|
#
|
||||||
|
# For example, if <tt>@post</tt> is an existing record you want to edit
|
||||||
|
#
|
||||||
|
# <% form_for @post 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
|
# is equivalent to something like:
|
||||||
# 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:
|
|
||||||
#
|
|
||||||
# <% form_for(@post) do |f| %>
|
|
||||||
# ...
|
|
||||||
# <% end %>
|
|
||||||
#
|
|
||||||
# This will expand to be the same as:
|
|
||||||
#
|
#
|
||||||
# <% form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
|
# <% form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
|
||||||
# ...
|
# ...
|
||||||
# <% end %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
# And for new records:
|
# And for new records
|
||||||
#
|
#
|
||||||
# <% form_for(Post.new) do |f| %>
|
# <% form_for(Post.new) do |f| %>
|
||||||
# ...
|
# ...
|
||||||
# <% end %>
|
# <% end %>
|
||||||
#
|
#
|
||||||
# This will expand to be the same as:
|
# expands to
|
||||||
#
|
#
|
||||||
# <% 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 +197,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| %>
|
||||||
# ...
|
# ...
|
||||||
|
@ -277,13 +324,13 @@ module ActionView
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# label(:post, :title)
|
# label(:post, :title)
|
||||||
# #=> <label for="post_title">Title</label>
|
# # => <label for="post_title">Title</label>
|
||||||
#
|
#
|
||||||
# label(:post, :title, "A short title")
|
# label(:post, :title, "A short title")
|
||||||
# #=> <label for="post_title">A short title</label>
|
# # => <label for="post_title">A short title</label>
|
||||||
#
|
#
|
||||||
# label(:post, :title, "A short title", :class => "title_label")
|
# label(:post, :title, "A short title", :class => "title_label")
|
||||||
# #=> <label for="post_title" class="title_label">A short title</label>
|
# # => <label for="post_title" class="title_label">A short title</label>
|
||||||
#
|
#
|
||||||
def label(object_name, method, text = nil, options = {})
|
def label(object_name, method, text = nil, options = {})
|
||||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_label_tag(text, options)
|
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_label_tag(text, options)
|
||||||
|
@ -588,6 +635,8 @@ module ActionView
|
||||||
value != 0
|
value != 0
|
||||||
when String
|
when String
|
||||||
value == checked_value
|
value == checked_value
|
||||||
|
when Array
|
||||||
|
value.include?(checked_value)
|
||||||
else
|
else
|
||||||
value.to_i != 0
|
value.to_i != 0
|
||||||
end
|
end
|
||||||
|
|
|
@ -119,7 +119,7 @@ module ActionView
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Sample usage (selecting the associated +Author+ for an instance of +Post+, <tt>@post</tt>):
|
# Sample usage (selecting the associated Author for an instance of Post, <tt>@post</tt>):
|
||||||
# collection_select(:post, :author_id, Author.find(:all), :id, :name_with_initial, {:prompt => true})
|
# collection_select(:post, :author_id, Author.find(:all), :id, :name_with_initial, {:prompt => true})
|
||||||
#
|
#
|
||||||
# If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return:
|
# If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return:
|
||||||
|
@ -144,10 +144,16 @@ module ActionView
|
||||||
# In addition to the <tt>:include_blank</tt> option documented above,
|
# In addition to the <tt>:include_blank</tt> option documented above,
|
||||||
# this method also supports a <tt>:model</tt> option, which defaults
|
# this method also supports a <tt>:model</tt> option, which defaults
|
||||||
# to TimeZone. This may be used by users to specify a different time
|
# to TimeZone. This may be used by users to specify a different time
|
||||||
# zone model object. (See #time_zone_options_for_select for more
|
# zone model object. (See +time_zone_options_for_select+ for more
|
||||||
# information.)
|
# information.)
|
||||||
|
#
|
||||||
|
# You can also supply an array of TimeZone objects
|
||||||
|
# as +priority_zones+, so that they will be listed above the rest of the
|
||||||
|
# (long) list. (You can use TimeZone.us_zones as a convenience for
|
||||||
|
# obtaining a list of the US time zones.)
|
||||||
|
#
|
||||||
# Finally, this method supports a <tt>:default</tt> option, which selects
|
# Finally, this method supports a <tt>:default</tt> option, which selects
|
||||||
# a default TimeZone if the object's time zone is nil.
|
# a default TimeZone if the object's time zone is +nil+.
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# time_zone_select( "user", "time_zone", nil, :include_blank => true)
|
# time_zone_select( "user", "time_zone", nil, :include_blank => true)
|
||||||
|
@ -156,6 +162,8 @@ module ActionView
|
||||||
#
|
#
|
||||||
# time_zone_select( "user", 'time_zone', TimeZone.us_zones, :default => "Pacific Time (US & Canada)")
|
# time_zone_select( "user", 'time_zone', TimeZone.us_zones, :default => "Pacific Time (US & Canada)")
|
||||||
#
|
#
|
||||||
|
# time_zone_select( "user", 'time_zone', [ TimeZone['Alaska'], TimeZone['Hawaii'] ])
|
||||||
|
#
|
||||||
# time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone)
|
# time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone)
|
||||||
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
|
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
|
||||||
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options)
|
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options)
|
||||||
|
@ -164,7 +172,7 @@ module ActionView
|
||||||
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
|
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
|
||||||
# where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
|
# where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
|
||||||
# the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
|
# the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
|
||||||
# become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +Selected+
|
# become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +selected+
|
||||||
# may also be an array of values to be selected when using a multiple select.
|
# may also be an array of values to be selected when using a multiple select.
|
||||||
#
|
#
|
||||||
# Examples (call, result):
|
# Examples (call, result):
|
||||||
|
@ -209,24 +217,22 @@ module ActionView
|
||||||
options_for_select(options, selected)
|
options_for_select(options, selected)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a string of <tt><option></tt> tags, like <tt>#options_from_collection_for_select</tt>, but
|
# Returns a string of <tt><option></tt> tags, like <tt>options_from_collection_for_select</tt>, but
|
||||||
# groups them by <tt><optgroup></tt> tags based on the object relationships of the arguments.
|
# groups them by <tt><optgroup></tt> tags based on the object relationships of the arguments.
|
||||||
#
|
#
|
||||||
# Parameters:
|
# Parameters:
|
||||||
# +collection+:: An array of objects representing the <tt><optgroup></tt> tags
|
# * +collection+ - An array of objects representing the <tt><optgroup></tt> tags.
|
||||||
# +group_method+:: The name of a method which, when called on a member of +collection+, returns an
|
# * +group_method+ - The name of a method which, when called on a member of +collection+, returns an
|
||||||
# array of child objects representing the <tt><option></tt> tags
|
# array of child objects representing the <tt><option></tt> tags.
|
||||||
# +group_label_method+:: The name of a method which, when called on a member of +collection+, returns a
|
# * group_label_method+ - The name of a method which, when called on a member of +collection+, returns a
|
||||||
# string to be used as the +label+ attribute for its <tt><optgroup></tt> tag
|
# string to be used as the +label+ attribute for its <tt><optgroup></tt> tag.
|
||||||
# +option_key_method+:: The name of a method which, when called on a child object of a member of
|
# * +option_key_method+ - The name of a method which, when called on a child object of a member of
|
||||||
# +collection+, returns a value to be used as the +value+ attribute for its
|
# +collection+, returns a value to be used as the +value+ attribute for its <tt><option></tt> tag.
|
||||||
# <tt><option></tt> tag
|
# * +option_value_method+ - The name of a method which, when called on a child object of a member of
|
||||||
# +option_value_method+:: The name of a method which, when called on a child object of a member of
|
# +collection+, returns a value to be used as the contents of its <tt><option></tt> tag.
|
||||||
# +collection+, returns a value to be used as the contents of its
|
# * +selected_key+ - A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
|
||||||
# <tt><option></tt> tag
|
# which will have the +selected+ attribute set. Corresponds to the return value of one of the calls
|
||||||
# +selected_key+:: A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
|
# to +option_key_method+. If +nil+, no selection is made.
|
||||||
# which will have the +selected+ attribute set. Corresponds to the return value
|
|
||||||
# of one of the calls to +option_key_method+. If +nil+, no selection is made.
|
|
||||||
#
|
#
|
||||||
# Example object structure for use with this method:
|
# Example object structure for use with this method:
|
||||||
# class Continent < ActiveRecord::Base
|
# class Continent < ActiveRecord::Base
|
||||||
|
@ -292,8 +298,8 @@ module ActionView
|
||||||
# a TimeZone.
|
# a TimeZone.
|
||||||
#
|
#
|
||||||
# By default, +model+ is the TimeZone constant (which can be obtained
|
# By default, +model+ is the TimeZone constant (which can be obtained
|
||||||
# in ActiveRecord as a value object). The only requirement is that the
|
# in Active Record as a value object). The only requirement is that the
|
||||||
# +model+ parameter be an object that responds to #all, and returns
|
# +model+ parameter be an object that responds to +all+, and returns
|
||||||
# an array of objects that represent time zones.
|
# an array of objects that represent time zones.
|
||||||
#
|
#
|
||||||
# NOTE: Only the option tags are returned, you have to wrap this call in
|
# NOTE: Only the option tags are returned, you have to wrap this call in
|
||||||
|
|
|
@ -3,7 +3,7 @@ require 'action_view/helpers/tag_helper'
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
module Helpers
|
module Helpers
|
||||||
# Provides a number of methods for creating form tags that doesn't rely on an ActiveRecord object assigned to the template like
|
# Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like
|
||||||
# FormHelper does. Instead, you provide the names and values manually.
|
# FormHelper does. Instead, you provide the names and values manually.
|
||||||
#
|
#
|
||||||
# NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
|
# NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
|
||||||
|
@ -15,7 +15,7 @@ module ActionView
|
||||||
# ==== Options
|
# ==== Options
|
||||||
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
|
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
|
||||||
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
|
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
|
||||||
# If "put", "delete", or another verb is used, a hidden input with name _method
|
# If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
|
||||||
# is added to simulate the verb over post.
|
# is added to simulate the verb over post.
|
||||||
# * A list of parameters to feed to the URL the form will be posted to.
|
# * A list of parameters to feed to the URL the form will be posted to.
|
||||||
#
|
#
|
||||||
|
|
|
@ -458,7 +458,7 @@ module ActionView
|
||||||
|
|
||||||
url_options = options[:url]
|
url_options = options[:url]
|
||||||
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
|
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
|
||||||
function << "'#{url_for(url_options)}'"
|
function << "'#{escape_javascript(url_for(url_options))}'"
|
||||||
function << ", #{javascript_options})"
|
function << ", #{javascript_options})"
|
||||||
|
|
||||||
function = "#{options[:before]}; #{function}" if options[:before]
|
function = "#{options[:before]}; #{function}" if options[:before]
|
||||||
|
@ -595,8 +595,8 @@ module ActionView
|
||||||
# JavaScript sent with a Content-type of "text/javascript".
|
# JavaScript sent with a Content-type of "text/javascript".
|
||||||
#
|
#
|
||||||
# Create new instances with PrototypeHelper#update_page or with
|
# Create new instances with PrototypeHelper#update_page or with
|
||||||
# ActionController::Base#render, then call #insert_html, #replace_html,
|
# ActionController::Base#render, then call +insert_html+, +replace_html+,
|
||||||
# #remove, #show, #hide, #visual_effect, or any other of the built-in
|
# +remove+, +show+, +hide+, +visual_effect+, or any other of the built-in
|
||||||
# methods on the yielded generator in any order you like to modify the
|
# methods on the yielded generator in any order you like to modify the
|
||||||
# content and appearance of the current page.
|
# content and appearance of the current page.
|
||||||
#
|
#
|
||||||
|
@ -687,7 +687,7 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an object whose <tt>#to_json</tt> evaluates to +code+. Use this to pass a literal JavaScript
|
# Returns an object whose <tt>to_json</tt> evaluates to +code+. Use this to pass a literal JavaScript
|
||||||
# expression as an argument to another JavaScriptGenerator method.
|
# expression as an argument to another JavaScriptGenerator method.
|
||||||
def literal(code)
|
def literal(code)
|
||||||
ActiveSupport::JSON::Variable.new(code.to_s)
|
ActiveSupport::JSON::Variable.new(code.to_s)
|
||||||
|
@ -1068,7 +1068,7 @@ module ActionView
|
||||||
|
|
||||||
def build_observer(klass, name, options = {})
|
def build_observer(klass, name, options = {})
|
||||||
if options[:with] && (options[:with] !~ /[\{=(.]/)
|
if options[:with] && (options[:with] !~ /[\{=(.]/)
|
||||||
options[:with] = "'#{options[:with]}=' + value"
|
options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)"
|
||||||
else
|
else
|
||||||
options[:with] ||= 'value' unless options[:function]
|
options[:with] ||= 'value' unless options[:function]
|
||||||
end
|
end
|
||||||
|
@ -1173,7 +1173,7 @@ module ActionView
|
||||||
super(generator)
|
super(generator)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The JSON Encoder calls this to check for the #to_json method
|
# The JSON Encoder calls this to check for the +to_json+ method
|
||||||
# Since it's a blank slate object, I suppose it responds to anything.
|
# Since it's a blank slate object, I suppose it responds to anything.
|
||||||
def respond_to?(method)
|
def respond_to?(method)
|
||||||
true
|
true
|
||||||
|
|
|
@ -2,7 +2,7 @@ module ActionView
|
||||||
module Helpers
|
module Helpers
|
||||||
module RecordTagHelper
|
module RecordTagHelper
|
||||||
# Produces a wrapper DIV element with id and class parameters that
|
# Produces a wrapper DIV element with id and class parameters that
|
||||||
# relate to the specified ActiveRecord object. Usage example:
|
# relate to the specified Active Record object. Usage example:
|
||||||
#
|
#
|
||||||
# <% div_for(@person, :class => "foo") do %>
|
# <% div_for(@person, :class => "foo") do %>
|
||||||
# <%=h @person.name %>
|
# <%=h @person.name %>
|
||||||
|
@ -17,7 +17,7 @@ module ActionView
|
||||||
end
|
end
|
||||||
|
|
||||||
# content_tag_for creates an HTML element with id and class parameters
|
# content_tag_for creates an HTML element with id and class parameters
|
||||||
# that relate to the specified ActiveRecord object. For example:
|
# that relate to the specified Active Record object. For example:
|
||||||
#
|
#
|
||||||
# <% content_tag_for(:tr, @person) do %>
|
# <% content_tag_for(:tr, @person) do %>
|
||||||
# <td><%=h @person.first_name %></td>
|
# <td><%=h @person.first_name %></td>
|
||||||
|
|
|
@ -57,7 +57,7 @@ module ActionView
|
||||||
self.class.white_list_sanitizer.sanitize(html, options)
|
self.class.white_list_sanitizer.sanitize(html, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sanitizes a block of css code. Used by #sanitize when it comes across a style attribute
|
# Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute.
|
||||||
def sanitize_css(style)
|
def sanitize_css(style)
|
||||||
self.class.white_list_sanitizer.sanitize_css(style)
|
self.class.white_list_sanitizer.sanitize_css(style)
|
||||||
end
|
end
|
||||||
|
@ -111,8 +111,8 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets the HTML::FullSanitizer instance used by strip_tags. Replace with
|
# Gets the HTML::FullSanitizer instance used by +strip_tags+. Replace with
|
||||||
# any object that responds to #sanitize
|
# any object that responds to +sanitize+.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.full_sanitizer = MySpecialSanitizer.new
|
# config.action_view.full_sanitizer = MySpecialSanitizer.new
|
||||||
|
@ -122,8 +122,8 @@ module ActionView
|
||||||
@full_sanitizer ||= HTML::FullSanitizer.new
|
@full_sanitizer ||= HTML::FullSanitizer.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets the HTML::LinkSanitizer instance used by strip_links. Replace with
|
# Gets the HTML::LinkSanitizer instance used by +strip_links+. Replace with
|
||||||
# any object that responds to #sanitize
|
# any object that responds to +sanitize+.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.link_sanitizer = MySpecialSanitizer.new
|
# config.action_view.link_sanitizer = MySpecialSanitizer.new
|
||||||
|
@ -133,8 +133,8 @@ module ActionView
|
||||||
@link_sanitizer ||= HTML::LinkSanitizer.new
|
@link_sanitizer ||= HTML::LinkSanitizer.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets the HTML::WhiteListSanitizer instance used by sanitize and sanitize_css.
|
# Gets the HTML::WhiteListSanitizer instance used by sanitize and +sanitize_css+.
|
||||||
# Replace with any object that responds to #sanitize
|
# Replace with any object that responds to +sanitize+.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.white_list_sanitizer = MySpecialSanitizer.new
|
# config.action_view.white_list_sanitizer = MySpecialSanitizer.new
|
||||||
|
@ -144,7 +144,7 @@ module ActionView
|
||||||
@white_list_sanitizer ||= HTML::WhiteListSanitizer.new
|
@white_list_sanitizer ||= HTML::WhiteListSanitizer.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds valid HTML attributes that the #sanitize helper checks for URIs.
|
# Adds valid HTML attributes that the +sanitize+ helper checks for URIs.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
|
# config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
|
||||||
|
@ -154,7 +154,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
|
HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of 'bad' tags for the #sanitize helper.
|
# Adds to the Set of 'bad' tags for the +sanitize+ helper.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_bad_tags = 'embed', 'object'
|
# config.action_view.sanitized_bad_tags = 'embed', 'object'
|
||||||
|
@ -163,7 +163,8 @@ module ActionView
|
||||||
def sanitized_bad_tags=(attributes)
|
def sanitized_bad_tags=(attributes)
|
||||||
HTML::WhiteListSanitizer.bad_tags.merge(attributes)
|
HTML::WhiteListSanitizer.bad_tags.merge(attributes)
|
||||||
end
|
end
|
||||||
# Adds to the Set of allowed tags for the #sanitize helper.
|
|
||||||
|
# Adds to the Set of allowed tags for the +sanitize+ helper.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
|
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
|
||||||
|
@ -173,7 +174,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
|
HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of allowed html attributes for the #sanitize helper.
|
# Adds to the Set of allowed HTML attributes for the +sanitize+ helper.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc'
|
# config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc'
|
||||||
|
@ -183,7 +184,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
|
HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of allowed css properties for the #sanitize and #sanitize_css heleprs.
|
# Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ heleprs.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_allowed_css_properties = 'expression'
|
# config.action_view.sanitized_allowed_css_properties = 'expression'
|
||||||
|
@ -193,7 +194,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
|
HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of allowed css keywords for the #sanitize and #sanitize_css helpers.
|
# Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_allowed_css_keywords = 'expression'
|
# config.action_view.sanitized_allowed_css_keywords = 'expression'
|
||||||
|
@ -203,7 +204,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
|
HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of allowed shorthand css properties for the #sanitize and #sanitize_css helpers.
|
# Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_shorthand_css_properties = 'expression'
|
# config.action_view.sanitized_shorthand_css_properties = 'expression'
|
||||||
|
@ -213,7 +214,7 @@ module ActionView
|
||||||
HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
|
HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds to the Set of allowed protocols for the #sanitize helper.
|
# Adds to the Set of allowed protocols for the +sanitize+ helper.
|
||||||
#
|
#
|
||||||
# Rails::Initializer.run do |config|
|
# Rails::Initializer.run do |config|
|
||||||
# config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
|
# config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
|
||||||
|
|
|
@ -26,9 +26,9 @@ module ActionView
|
||||||
# :url => { :action => "reload" },
|
# :url => { :action => "reload" },
|
||||||
# :complete => visual_effect(:highlight, "posts", :duration => 0.5)
|
# :complete => visual_effect(:highlight, "posts", :duration => 0.5)
|
||||||
#
|
#
|
||||||
# If no element_id is given, it assumes "element" which should be a local
|
# If no +element_id+ is given, it assumes "element" which should be a local
|
||||||
# variable in the generated JavaScript execution context. This can be
|
# variable in the generated JavaScript execution context. This can be
|
||||||
# used for example with drop_receiving_element:
|
# used for example with +drop_receiving_element+:
|
||||||
#
|
#
|
||||||
# <%= drop_receiving_element (...), :loading => visual_effect(:fade) %>
|
# <%= drop_receiving_element (...), :loading => visual_effect(:fade) %>
|
||||||
#
|
#
|
||||||
|
@ -67,6 +67,7 @@ module ActionView
|
||||||
# element as parameters.
|
# element as parameters.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
#
|
||||||
# <%= sortable_element("my_list", :url => { :action => "order" }) %>
|
# <%= sortable_element("my_list", :url => { :action => "order" }) %>
|
||||||
#
|
#
|
||||||
# In the example, the action gets a "my_list" array parameter
|
# In the example, the action gets a "my_list" array parameter
|
||||||
|
@ -79,60 +80,56 @@ module ActionView
|
||||||
#
|
#
|
||||||
# Additional +options+ are:
|
# Additional +options+ are:
|
||||||
#
|
#
|
||||||
# <tt>:format</tt>:: A regular expression to determine what to send
|
# * <tt>:format</tt> - A regular expression to determine what to send as the
|
||||||
# as the serialized id to the server (the default
|
# serialized id to the server (the default is <tt>/^[^_]*_(.*)$/</tt>).
|
||||||
# is <tt>/^[^_]*_(.*)$/</tt>).
|
|
||||||
#
|
#
|
||||||
# <tt>:constraint</tt>:: Whether to constrain the dragging to either <tt>:horizontal</tt>
|
# * <tt>:constraint</tt> - Whether to constrain the dragging to either
|
||||||
# or <tt>:vertical</tt> (or false to make it unconstrained).
|
# <tt>:horizontal</tt> or <tt>:vertical</tt> (or false to make it unconstrained).
|
||||||
#
|
#
|
||||||
# <tt>:overlap</tt>:: Calculate the item overlap in the <tt>:horizontal</tt> or
|
# * <tt>:overlap</tt> - Calculate the item overlap in the <tt>:horizontal</tt>
|
||||||
# <tt>:vertical</tt> direction.
|
# or <tt>:vertical</tt> direction.
|
||||||
#
|
#
|
||||||
# <tt>:tag</tt>:: Which children of the container element to treat as
|
# * <tt>:tag</tt> - Which children of the container element to treat as
|
||||||
# sortable (default is <tt>li</tt>).
|
# sortable (default is <tt>li</tt>).
|
||||||
#
|
#
|
||||||
# <tt>:containment</tt>:: Takes an element or array of elements to treat as
|
# * <tt>:containment</tt> - Takes an element or array of elements to treat as
|
||||||
# potential drop targets (defaults to the original
|
# potential drop targets (defaults to the original target element).
|
||||||
# target element).
|
|
||||||
#
|
#
|
||||||
# <tt>:only</tt>:: A CSS class name or arry of class names used to filter
|
# * <tt>:only</tt> - A CSS class name or arry of class names used to filter
|
||||||
# out child elements as candidates.
|
# out child elements as candidates.
|
||||||
#
|
#
|
||||||
# <tt>:scroll</tt>:: Determines whether to scroll the list during drag
|
# * <tt>:scroll</tt> - Determines whether to scroll the list during drag
|
||||||
# operations if the list runs past the visual border.
|
# operations if the list runs past the visual border.
|
||||||
#
|
#
|
||||||
# <tt>:tree</tt>:: Determines whether to treat nested lists as part of the
|
# * <tt>:tree</tt> - Determines whether to treat nested lists as part of the
|
||||||
# main sortable list. This means that you can create multi-
|
# main sortable list. This means that you can create multi-layer lists,
|
||||||
# layer lists, and not only sort items at the same level,
|
# and not only sort items at the same level, but drag and sort items
|
||||||
# but drag and sort items between levels.
|
# between levels.
|
||||||
#
|
#
|
||||||
# <tt>:hoverclass</tt>:: If set, the Droppable will have this additional CSS class
|
# * <tt>:hoverclass</tt> - If set, the Droppable will have this additional CSS class
|
||||||
# when an accepted Draggable is hovered over it.
|
# when an accepted Draggable is hovered over it.
|
||||||
#
|
#
|
||||||
# <tt>:handle</tt>:: Sets whether the element should only be draggable by an
|
# * <tt>:handle</tt> - Sets whether the element should only be draggable by an
|
||||||
# embedded handle. The value may be a string referencing a
|
# embedded handle. The value may be a string referencing a CSS class value
|
||||||
# CSS class value (as of script.aculo.us V1.5). The first
|
# (as of script.aculo.us V1.5). The first child/grandchild/etc. element
|
||||||
# child/grandchild/etc. element found within the element
|
# found within the element that has this CSS class value will be used as
|
||||||
# that has this CSS class value will be used as the handle.
|
# the handle.
|
||||||
#
|
#
|
||||||
# <tt>:ghosting</tt>:: Clones the element and drags the clone, leaving the original
|
# * <tt>:ghosting</tt> - Clones the element and drags the clone, leaving
|
||||||
# in place until the clone is dropped (default is <tt>false</tt>).
|
# the original in place until the clone is dropped (default is <tt>false</tt>).
|
||||||
#
|
#
|
||||||
# <tt>:dropOnEmpty</tt>:: If set to true, the Sortable container will be made into
|
# * <tt>:dropOnEmpty</tt> - If true the Sortable container will be made into
|
||||||
# a Droppable, that can receive a Draggable (as according to
|
# a Droppable, that can receive a Draggable (as according to the containment
|
||||||
# the containment rules) as a child element when there are no
|
# rules) as a child element when there are no more elements inside (default
|
||||||
# more elements inside (default is <tt>false</tt>).
|
# is <tt>false</tt>).
|
||||||
#
|
#
|
||||||
# <tt>:onChange</tt>:: Called whenever the sort order changes while dragging. When
|
# * <tt>:onChange</tt> - Called whenever the sort order changes while dragging. When
|
||||||
# dragging from one Sortable to another, the callback is
|
# dragging from one Sortable to another, the callback is called once on each
|
||||||
# called once on each Sortable. Gets the affected element as
|
# Sortable. Gets the affected element as its parameter.
|
||||||
# its parameter.
|
|
||||||
#
|
#
|
||||||
# <tt>:onUpdate</tt>:: Called when the drag ends and the Sortable's order is
|
# * <tt>:onUpdate</tt> - Called when the drag ends and the Sortable's order is
|
||||||
# changed in any way. When dragging from one Sortable to
|
# changed in any way. When dragging from one Sortable to another, the callback
|
||||||
# another, the callback is called once on each Sortable. Gets
|
# is called once on each Sortable. Gets the container as its parameter.
|
||||||
# the container as its parameter.
|
|
||||||
#
|
#
|
||||||
# See http://script.aculo.us for more documentation.
|
# See http://script.aculo.us for more documentation.
|
||||||
def sortable_element(element_id, options = {})
|
def sortable_element(element_id, options = {})
|
||||||
|
@ -170,8 +167,8 @@ module ActionView
|
||||||
end
|
end
|
||||||
|
|
||||||
# Makes the element with the DOM ID specified by +element_id+ receive
|
# Makes the element with the DOM ID specified by +element_id+ receive
|
||||||
# dropped draggable elements (created by draggable_element).
|
# dropped draggable elements (created by +draggable_element+).
|
||||||
# and make an AJAX call By default, the action called gets the DOM ID
|
# and make an AJAX call. By default, the action called gets the DOM ID
|
||||||
# of the element as parameter.
|
# of the element as parameter.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -182,32 +179,30 @@ module ActionView
|
||||||
# http://script.aculo.us for more documentation.
|
# http://script.aculo.us for more documentation.
|
||||||
#
|
#
|
||||||
# Some of these +options+ include:
|
# Some of these +options+ include:
|
||||||
# <tt>:accept</tt>:: Set this to a string or an array of strings describing the
|
# * <tt>:accept</tt> - Set this to a string or an array of strings describing the
|
||||||
# allowable CSS classes that the draggable_element must have in order
|
# allowable CSS classes that the +draggable_element+ must have in order
|
||||||
# to be accepted by this drop_receiving_element.
|
# to be accepted by this +drop_receiving_element+.
|
||||||
#
|
#
|
||||||
# <tt>:confirm</tt>:: Adds a confirmation dialog.
|
# * <tt>:confirm</tt> - Adds a confirmation dialog. Example:
|
||||||
#
|
#
|
||||||
# Example:
|
|
||||||
# :confirm => "Are you sure you want to do this?"
|
# :confirm => "Are you sure you want to do this?"
|
||||||
#
|
#
|
||||||
# <tt>:hoverclass</tt>:: If set, the drop_receiving_element will have this additional CSS class
|
# * <tt>:hoverclass</tt> - If set, the +drop_receiving_element+ will have
|
||||||
# when an accepted draggable_element is hovered over it.
|
# this additional CSS class when an accepted +draggable_element+ is
|
||||||
|
# hovered over it.
|
||||||
#
|
#
|
||||||
# <tt>:onDrop</tt>:: Called when a draggable_element is dropped onto this element.
|
# * <tt>:onDrop</tt> - Called when a +draggable_element+ is dropped onto
|
||||||
# Override this callback with a javascript expression to
|
# this element. Override this callback with a JavaScript expression to
|
||||||
# change the default drop behavour.
|
# change the default drop behavour. Example:
|
||||||
#
|
#
|
||||||
# Example:
|
|
||||||
# :onDrop => "function(draggable_element, droppable_element, event) { alert('I like bananas') }"
|
# :onDrop => "function(draggable_element, droppable_element, event) { alert('I like bananas') }"
|
||||||
#
|
#
|
||||||
# This callback gets three parameters:
|
# This callback gets three parameters: The Draggable element, the Droppable
|
||||||
# The +Draggable+ element, the +Droppable+ element and the
|
# element and the Event object. You can extract additional information about
|
||||||
# +Event+ object. You can extract additional information about the
|
# the drop - like if the Ctrl or Shift keys were pressed - from the Event object.
|
||||||
# drop - like if the Ctrl or Shift keys were pressed - from the +Event+ object.
|
|
||||||
#
|
#
|
||||||
# <tt>:with</tt>:: A JavaScript expression specifying the parameters for the XMLHttpRequest.
|
# * <tt>:with</tt> - A JavaScript expression specifying the parameters for
|
||||||
# Any expressions should return a valid URL query string.
|
# the XMLHttpRequest. Any expressions should return a valid URL query string.
|
||||||
def drop_receiving_element(element_id, options = {})
|
def drop_receiving_element(element_id, options = {})
|
||||||
javascript_tag(drop_receiving_element_js(element_id, options).chop!)
|
javascript_tag(drop_receiving_element_js(element_id, options).chop!)
|
||||||
end
|
end
|
||||||
|
|
|
@ -147,10 +147,9 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+
|
# Attempts to pluralize the +singular+ word unless +count+ is 1. If
|
||||||
# is supplied, it will use that when count is > 1, if the ActiveSupport Inflector
|
# +plural+ is supplied, it will use that when count is > 1, otherwise
|
||||||
# is loaded, it will use the Inflector to determine the plural form, otherwise
|
# it will use the Inflector to determine the plural form
|
||||||
# it will just add an 's' to the +singular+ word.
|
|
||||||
#
|
#
|
||||||
# ==== Examples
|
# ==== Examples
|
||||||
# pluralize(1, 'person')
|
# pluralize(1, 'person')
|
||||||
|
@ -165,15 +164,7 @@ module ActionView
|
||||||
# pluralize(0, 'person')
|
# pluralize(0, 'person')
|
||||||
# # => 0 people
|
# # => 0 people
|
||||||
def pluralize(count, singular, plural = nil)
|
def pluralize(count, singular, plural = nil)
|
||||||
"#{count || 0} " + if count == 1 || count == '1'
|
"#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
|
||||||
singular
|
|
||||||
elsif plural
|
|
||||||
plural
|
|
||||||
elsif Object.const_defined?("Inflector")
|
|
||||||
Inflector.pluralize(singular)
|
|
||||||
else
|
|
||||||
singular + "s"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Wraps the +text+ into lines no longer than +line_width+ width. This method
|
# Wraps the +text+ into lines no longer than +line_width+ width. This method
|
||||||
|
@ -473,11 +464,11 @@ module ActionView
|
||||||
[-\w]+ # subdomain or domain
|
[-\w]+ # subdomain or domain
|
||||||
(?:\.[-\w]+)* # remaining subdomains or domain
|
(?:\.[-\w]+)* # remaining subdomains or domain
|
||||||
(?::\d+)? # port
|
(?::\d+)? # port
|
||||||
(?:/(?:(?:[~\w\+@%=-]|(?:[,.;:][^\s$]))+)?)* # path
|
(?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:][^\s$]))+)?)* # path
|
||||||
(?:\?[\w\+@%&=.;-]+)? # query string
|
(?:\?[\w\+@%&=.;-]+)? # query string
|
||||||
(?:\#[\w\-]*)? # trailing anchor
|
(?:\#[\w\-]*)? # trailing anchor
|
||||||
)
|
)
|
||||||
([[:punct:]]|\s|<|$) # trailing text
|
([[:punct:]]|<|$|) # trailing text
|
||||||
}x unless const_defined?(:AUTO_LINK_RE)
|
}x unless const_defined?(:AUTO_LINK_RE)
|
||||||
|
|
||||||
# Turns all urls into clickable links. If a block is given, each url
|
# Turns all urls into clickable links. If a block is given, each url
|
||||||
|
|
|
@ -10,7 +10,7 @@ module ActionView
|
||||||
include JavaScriptHelper
|
include JavaScriptHelper
|
||||||
|
|
||||||
# Returns the URL for the set of +options+ provided. This takes the
|
# Returns the URL for the set of +options+ provided. This takes the
|
||||||
# same options as url_for in ActionController (see the
|
# same options as +url_for+ in Action Controller (see the
|
||||||
# documentation for ActionController::Base#url_for). Note that by default
|
# documentation for ActionController::Base#url_for). Note that by default
|
||||||
# <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative /controller/action
|
# <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative /controller/action
|
||||||
# instead of the fully qualified URL like http://example.com/controller/action.
|
# instead of the fully qualified URL like http://example.com/controller/action.
|
||||||
|
@ -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>
|
||||||
|
|
|
@ -93,9 +93,9 @@ module ActionView #:nodoc:
|
||||||
# Register a class that knows how to handle template files with the given
|
# Register a class that knows how to handle template files with the given
|
||||||
# extension. This can be used to implement new template types.
|
# extension. This can be used to implement new template types.
|
||||||
# The constructor for the class must take the ActiveView::Base instance
|
# The constructor for the class must take the ActiveView::Base instance
|
||||||
# as a parameter, and the class must implement a #render method that
|
# as a parameter, and the class must implement a +render+ method that
|
||||||
# takes the contents of the template to render as well as the Hash of
|
# takes the contents of the template to render as well as the Hash of
|
||||||
# local assigns available to the template. The #render method ought to
|
# local assigns available to the template. The +render+ method ought to
|
||||||
# return the rendered template as a string.
|
# return the rendered template as a string.
|
||||||
def self.register_template_handler(extension, klass)
|
def self.register_template_handler(extension, klass)
|
||||||
@@template_handlers[extension.to_sym] = klass
|
@@template_handlers[extension.to_sym] = klass
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
class NonInferrableHelperError < ActionViewError
|
|
||||||
def initialize(name)
|
|
||||||
super "Unable to determine the helper to test from #{name}. " +
|
|
||||||
"You'll need to specify it using tests YourHelper in your " +
|
|
||||||
"test case definition"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class TestCase < ActiveSupport::TestCase
|
class TestCase < ActiveSupport::TestCase
|
||||||
class_inheritable_accessor :helper_class
|
class_inheritable_accessor :helper_class
|
||||||
@@helper_class = nil
|
@@helper_class = nil
|
||||||
|
@ -29,7 +21,7 @@ module ActionView
|
||||||
def determine_default_helper_class(name)
|
def determine_default_helper_class(name)
|
||||||
name.sub(/Test$/, '').constantize
|
name.sub(/Test$/, '').constantize
|
||||||
rescue NameError
|
rescue NameError
|
||||||
raise NonInferrableHelperError.new(name)
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -42,8 +34,10 @@ module ActionView
|
||||||
setup :setup_with_helper_class
|
setup :setup_with_helper_class
|
||||||
|
|
||||||
def setup_with_helper_class
|
def setup_with_helper_class
|
||||||
|
if helper_class && !self.class.ancestors.include?(helper_class)
|
||||||
self.class.send(:include, helper_class)
|
self.class.send(:include, helper_class)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class TestController < ActionController::Base
|
class TestController < ActionController::Base
|
||||||
attr_accessor :request, :response
|
attr_accessor :request, :response
|
||||||
|
|
|
@ -131,6 +131,10 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base
|
||||||
def index
|
def index
|
||||||
raise 'FAIL'
|
raise 'FAIL'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
render :text => "Boom", :status => 500
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
|
@ -483,6 +487,16 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
||||||
rescue Test::Unit::AssertionFailedError => e
|
rescue Test::Unit::AssertionFailedError => e
|
||||||
assert e.message.include?('FAIL')
|
assert e.message.include?('FAIL')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_assert_response_failure_response_with_no_exception
|
||||||
|
@controller = AssertResponseWithUnexpectedErrorController.new
|
||||||
|
get :show
|
||||||
|
assert_response :success
|
||||||
|
flunk 'Expected non-success response'
|
||||||
|
rescue Test::Unit::AssertionFailedError
|
||||||
|
rescue
|
||||||
|
flunk "assert_response failed to handle failure response with missing, but optional, exception."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionPackHeaderTest < Test::Unit::TestCase
|
class ActionPackHeaderTest < Test::Unit::TestCase
|
||||||
|
|
|
@ -6,6 +6,7 @@ CACHE_DIR = 'test_cache'
|
||||||
FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
|
FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
|
||||||
ActionController::Base.page_cache_directory = FILE_STORE_PATH
|
ActionController::Base.page_cache_directory = FILE_STORE_PATH
|
||||||
ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
|
ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
|
||||||
|
ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/' ]
|
||||||
|
|
||||||
class PageCachingTestController < ActionController::Base
|
class PageCachingTestController < ActionController::Base
|
||||||
caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? }
|
caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? }
|
||||||
|
@ -151,12 +152,15 @@ end
|
||||||
|
|
||||||
|
|
||||||
class ActionCachingTestController < ActionController::Base
|
class ActionCachingTestController < ActionController::Base
|
||||||
caches_action :index, :redirected, :forbidden
|
caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }
|
||||||
caches_action :show, :cache_path => 'http://test.host/custom/show'
|
caches_action :show, :cache_path => 'http://test.host/custom/show'
|
||||||
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
|
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
|
||||||
|
caches_action :with_layout
|
||||||
|
|
||||||
|
layout 'talk_from_action.erb'
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@cache_this = Time.now.to_f.to_s
|
@cache_this = MockTime.now.to_f.to_s
|
||||||
render :text => @cache_this
|
render :text => @cache_this
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -169,14 +173,26 @@ class ActionCachingTestController < ActionController::Base
|
||||||
headers["Status"] = "403 Forbidden"
|
headers["Status"] = "403 Forbidden"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_layout
|
||||||
|
@cache_this = MockTime.now.to_f.to_s
|
||||||
|
render :text => @cache_this, :layout => true
|
||||||
|
end
|
||||||
|
|
||||||
alias_method :show, :index
|
alias_method :show, :index
|
||||||
alias_method :edit, :index
|
alias_method :edit, :index
|
||||||
|
alias_method :destroy, :index
|
||||||
|
|
||||||
def expire
|
def expire
|
||||||
expire_action :controller => 'action_caching_test', :action => 'index'
|
expire_action :controller => 'action_caching_test', :action => 'index'
|
||||||
render :nothing => true
|
render :nothing => true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class MockTime < Time
|
||||||
|
# Let Time spicy to assure that Time.now != Time.now
|
||||||
|
def to_f
|
||||||
|
super+rand
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionCachingMockController
|
class ActionCachingMockController
|
||||||
|
@ -216,18 +232,48 @@ class ActionCacheTest < Test::Unit::TestCase
|
||||||
get :index
|
get :index
|
||||||
cached_time = content_to_cache
|
cached_time = content_to_cache
|
||||||
assert_equal cached_time, @response.body
|
assert_equal cached_time, @response.body
|
||||||
assert_cache_exists 'hostname.com/action_caching_test'
|
assert fragment_exist?('hostname.com/action_caching_test')
|
||||||
reset!
|
reset!
|
||||||
|
|
||||||
get :index
|
get :index
|
||||||
assert_equal cached_time, @response.body
|
assert_equal cached_time, @response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_simple_action_not_cached
|
||||||
|
get :destroy
|
||||||
|
cached_time = content_to_cache
|
||||||
|
assert_equal cached_time, @response.body
|
||||||
|
assert !fragment_exist?('hostname.com/action_caching_test/destroy')
|
||||||
|
reset!
|
||||||
|
|
||||||
|
get :destroy
|
||||||
|
assert_not_equal cached_time, @response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_action_cache_with_layout
|
||||||
|
get :with_layout
|
||||||
|
cached_time = content_to_cache
|
||||||
|
assert_not_equal cached_time, @response.body
|
||||||
|
assert fragment_exist?('hostname.com/action_caching_test/with_layout')
|
||||||
|
reset!
|
||||||
|
|
||||||
|
get :with_layout
|
||||||
|
assert_not_equal cached_time, @response.body
|
||||||
|
|
||||||
|
assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_action_cache_conditional_options
|
||||||
|
@request.env['HTTP_ACCEPT'] = 'application/json'
|
||||||
|
get :index
|
||||||
|
assert !fragment_exist?('hostname.com/action_caching_test')
|
||||||
|
end
|
||||||
|
|
||||||
def test_action_cache_with_custom_cache_path
|
def test_action_cache_with_custom_cache_path
|
||||||
get :show
|
get :show
|
||||||
cached_time = content_to_cache
|
cached_time = content_to_cache
|
||||||
assert_equal cached_time, @response.body
|
assert_equal cached_time, @response.body
|
||||||
assert_cache_exists 'test.host/custom/show'
|
assert fragment_exist?('test.host/custom/show')
|
||||||
reset!
|
reset!
|
||||||
|
|
||||||
get :show
|
get :show
|
||||||
|
@ -236,11 +282,11 @@ class ActionCacheTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_action_cache_with_custom_cache_path_in_block
|
def test_action_cache_with_custom_cache_path_in_block
|
||||||
get :edit
|
get :edit
|
||||||
assert_cache_exists 'test.host/edit'
|
assert fragment_exist?('test.host/edit')
|
||||||
reset!
|
reset!
|
||||||
|
|
||||||
get :edit, :id => 1
|
get :edit, :id => 1
|
||||||
assert_cache_exists 'test.host/1;edit'
|
assert fragment_exist?('test.host/1;edit')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_cache_expiration
|
def test_cache_expiration
|
||||||
|
@ -349,9 +395,12 @@ class ActionCacheTest < Test::Unit::TestCase
|
||||||
@request.host = 'hostname.com'
|
@request.host = 'hostname.com'
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_cache_exists(path)
|
def fragment_exist?(path)
|
||||||
full_path = File.join(FILE_STORE_PATH, "views", path + '.cache')
|
@controller.fragment_exist?(path)
|
||||||
assert File.exist?(full_path), "#{full_path.inspect} does not exist."
|
end
|
||||||
|
|
||||||
|
def read_fragment(path)
|
||||||
|
@controller.read_fragment(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -391,6 +440,19 @@ class FragmentCachingTest < Test::Unit::TestCase
|
||||||
assert_nil @controller.read_fragment('name')
|
assert_nil @controller.read_fragment('name')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_fragment_exist__with_caching_enabled
|
||||||
|
@store.write('views/name', 'value')
|
||||||
|
assert @controller.fragment_exist?('name')
|
||||||
|
assert !@controller.fragment_exist?('other_name')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fragment_exist__with_caching_disabled
|
||||||
|
ActionController::Base.perform_caching = false
|
||||||
|
@store.write('views/name', 'value')
|
||||||
|
assert !@controller.fragment_exist?('name')
|
||||||
|
assert !@controller.fragment_exist?('other_name')
|
||||||
|
end
|
||||||
|
|
||||||
def test_write_fragment__with_caching_enabled
|
def test_write_fragment__with_caching_enabled
|
||||||
assert_nil @store.read('views/name')
|
assert_nil @store.read('views/name')
|
||||||
assert_equal 'value', @controller.write_fragment('name', 'value')
|
assert_equal 'value', @controller.write_fragment('name', 'value')
|
||||||
|
@ -435,7 +497,6 @@ class FragmentCachingTest < Test::Unit::TestCase
|
||||||
assert_equal 'generated till now -> ', buffer
|
assert_equal 'generated till now -> ', buffer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_fragment_for
|
def test_fragment_for
|
||||||
@store.write('views/expensive', 'fragment content')
|
@store.write('views/expensive', 'fragment content')
|
||||||
fragment_computed = false
|
fragment_computed = false
|
||||||
|
@ -547,8 +608,3 @@ CACHED
|
||||||
assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial')
|
assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ class CookieTest < Test::Unit::TestCase
|
||||||
def test_expiring_cookie
|
def test_expiring_cookie
|
||||||
get :logout
|
get :logout
|
||||||
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)) ], @response.headers["cookie"]
|
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)) ], @response.headers["cookie"]
|
||||||
|
assert_equal CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)).value, []
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_cookiejar_accessor
|
def test_cookiejar_accessor
|
||||||
|
@ -137,4 +138,9 @@ class CookieTest < Test::Unit::TestCase
|
||||||
cookies = CGI::Cookie.parse('return_to=http://rubyonrails.org/search?term=api&scope=all&global=true')
|
cookies = CGI::Cookie.parse('return_to=http://rubyonrails.org/search?term=api&scope=all&global=true')
|
||||||
assert_equal({"return_to" => ["http://rubyonrails.org/search?term=api&scope=all&global=true"]}, cookies)
|
assert_equal({"return_to" => ["http://rubyonrails.org/search?term=api&scope=all&global=true"]}, cookies)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_cookies_should_not_be_split_on_values_with_newlines
|
||||||
|
cookies = CGI::Cookie.new("name" => "val", "value" => "this\nis\na\ntest")
|
||||||
|
assert cookies.size == 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,7 @@ class FilterParamTest < Test::Unit::TestCase
|
||||||
|
|
||||||
test_hashes.each do |before_filter, after_filter, filter_words|
|
test_hashes.each do |before_filter, after_filter, filter_words|
|
||||||
FilterParamController.filter_parameter_logging(*filter_words)
|
FilterParamController.filter_parameter_logging(*filter_words)
|
||||||
assert_equal after_filter, @controller.filter_parameters(before_filter)
|
assert_equal after_filter, @controller.send!(:filter_parameters, before_filter)
|
||||||
|
|
||||||
filter_words.push('blah')
|
filter_words.push('blah')
|
||||||
FilterParamController.filter_parameter_logging(*filter_words) do |key, value|
|
FilterParamController.filter_parameter_logging(*filter_words) do |key, value|
|
||||||
|
@ -37,7 +37,13 @@ class FilterParamTest < Test::Unit::TestCase
|
||||||
before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
|
before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
|
||||||
after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
|
after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
|
||||||
|
|
||||||
assert_equal after_filter, @controller.filter_parameters(before_filter)
|
assert_equal after_filter, @controller.send!(:filter_parameters, before_filter)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_filter_parameters_is_protected
|
||||||
|
FilterParamController.filter_parameter_logging(:foo)
|
||||||
|
assert !FilterParamController.action_methods.include?('filter_parameters')
|
||||||
|
assert_raise(NoMethodError) { @controller.filter_parameters([{'password' => '[FILTERED]'}]) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,7 +85,7 @@ class HelperTest < Test::Unit::TestCase
|
||||||
def test_helper_block_include
|
def test_helper_block_include
|
||||||
assert_equal expected_helper_methods, missing_methods
|
assert_equal expected_helper_methods, missing_methods
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
@controller_class.helper { include TestHelper }
|
@controller_class.helper { include HelperTest::TestHelper }
|
||||||
}
|
}
|
||||||
assert [], missing_methods
|
assert [], missing_methods
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,11 +52,16 @@ class MimeTypeTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_type_convenience_methods
|
def test_type_convenience_methods
|
||||||
types = [:html, :xml, :png, :pdf, :yaml, :url_encoded_form]
|
# Don't test Mime::ALL, since it Mime::ALL#html? == true
|
||||||
|
types = Mime::SET.to_a.map(&:to_sym).uniq - [:all]
|
||||||
|
|
||||||
|
# Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
|
||||||
|
types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) }
|
||||||
|
|
||||||
types.each do |type|
|
types.each do |type|
|
||||||
mime = Mime.const_get(type.to_s.upcase)
|
mime = Mime.const_get(type.to_s.upcase)
|
||||||
assert mime.send("#{type}?"), "Mime::#{type.to_s.upcase} is not #{type}?"
|
assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?"
|
||||||
(types - [type]).each { |t| assert !mime.send("#{t}?"), "Mime::#{t.to_s.upcase} is #{t}?" }
|
(types - [type]).each { |other_type| assert !mime.send("#{other_type}?"), "#{mime.inspect} is #{other_type}?" }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,4 +69,16 @@ class MimeTypeTest < Test::Unit::TestCase
|
||||||
assert Mime::ALL.all?, "Mime::ALL is not all?"
|
assert Mime::ALL.all?, "Mime::ALL is not all?"
|
||||||
assert Mime::ALL.html?, "Mime::ALL is not html?"
|
assert Mime::ALL.html?, "Mime::ALL is not html?"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_verifiable_mime_types
|
||||||
|
unverified_types = Mime::Type.unverifiable_types
|
||||||
|
all_types = Mime::SET.to_a.map(&:to_sym)
|
||||||
|
all_types.uniq!
|
||||||
|
# Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
|
||||||
|
all_types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) }
|
||||||
|
|
||||||
|
unverified, verified = all_types.partition { |type| Mime::Type.unverifiable_types.include? type }
|
||||||
|
assert verified.all? { |type| Mime.const_get(type.to_s.upcase).verify_request? }, "Not all Mime Types are verified: #{verified.inspect}"
|
||||||
|
assert unverified.all? { |type| !Mime.const_get(type.to_s.upcase).verify_request? }, "Some Mime Types are verified: #{unverified.inspect}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -114,6 +114,66 @@ module RequestForgeryProtectionTests
|
||||||
assert_raises(ActionController::InvalidAuthenticityToken) { delete :index }
|
assert_raises(ActionController::InvalidAuthenticityToken) { delete :index }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_post_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
post :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_put_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
put :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_delete_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
delete :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
||||||
|
post :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
||||||
|
put :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
||||||
|
delete :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
||||||
|
post :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
||||||
|
put :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
|
||||||
|
assert_raises(ActionController::InvalidAuthenticityToken) do
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
||||||
|
delete :index, :format => 'xml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_not_allow_xhr_post_without_token
|
def test_should_not_allow_xhr_post_without_token
|
||||||
assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
|
assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
|
||||||
end
|
end
|
||||||
|
@ -142,16 +202,19 @@ module RequestForgeryProtectionTests
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_allow_post_with_xml
|
def test_should_allow_post_with_xml
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
||||||
post :index, :format => 'xml'
|
post :index, :format => 'xml'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_allow_put_with_xml
|
def test_should_allow_put_with_xml
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
||||||
put :index, :format => 'xml'
|
put :index, :format => 'xml'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_allow_delete_with_xml
|
def test_should_allow_delete_with_xml
|
||||||
|
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
||||||
delete :index, :format => 'xml'
|
delete :index, :format => 'xml'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
|
|
|
@ -50,6 +50,13 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase
|
||||||
:additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] }
|
:additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] }
|
||||||
assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
|
assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_route_generation_allows_passing_non_string_values_to_generated_helper
|
||||||
|
assert_equal "/controller/action/variable/1/2", @set.generate(:controller => "controller",
|
||||||
|
:action => "action",
|
||||||
|
:variable => "variable",
|
||||||
|
:additional => [1, 2])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LegacyRouteSetTests < Test::Unit::TestCase
|
class LegacyRouteSetTests < Test::Unit::TestCase
|
||||||
|
|
|
@ -43,7 +43,9 @@ class CookieStoreTest < Test::Unit::TestCase
|
||||||
{ :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}],
|
{ :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}],
|
||||||
:a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }],
|
:a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }],
|
||||||
:typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
|
:typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
|
||||||
:flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }] }
|
:flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }],
|
||||||
|
:double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf'), { 'user_id' => 123, 'flash' => {} }] }
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
@ -101,6 +103,15 @@ class CookieStoreTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_restores_double_encoded_cookies
|
||||||
|
set_cookie! cookie_value(:double_escaped)
|
||||||
|
new_session do |session|
|
||||||
|
session.dbman.restore
|
||||||
|
assert_equal session["user_id"], 123
|
||||||
|
assert_equal session["flash"], {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_close_doesnt_write_cookie_if_data_is_blank
|
def test_close_doesnt_write_cookie_if_data_is_blank
|
||||||
new_session do |session|
|
new_session do |session|
|
||||||
assert_no_cookies session
|
assert_no_cookies session
|
||||||
|
@ -241,6 +252,7 @@ class CookieStoreWithMD5DigestTest < CookieStoreTest
|
||||||
{ :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}],
|
{ :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}],
|
||||||
:a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }],
|
:a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }],
|
||||||
:typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
|
:typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
|
||||||
:flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }] }
|
:flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }],
|
||||||
|
:double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -511,16 +511,26 @@ XML
|
||||||
|
|
||||||
FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart'
|
FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart'
|
||||||
|
|
||||||
|
if RUBY_VERSION < '1.9'
|
||||||
|
READ_BINARY = 'rb'
|
||||||
|
READ_PLAIN = 'r'
|
||||||
|
else
|
||||||
|
READ_BINARY = 'rb:binary'
|
||||||
|
READ_PLAIN = 'r:binary'
|
||||||
|
end
|
||||||
|
|
||||||
def test_test_uploaded_file
|
def test_test_uploaded_file
|
||||||
filename = 'mona_lisa.jpg'
|
filename = 'mona_lisa.jpg'
|
||||||
path = "#{FILES_DIR}/#{filename}"
|
path = "#{FILES_DIR}/#{filename}"
|
||||||
content_type = 'image/png'
|
content_type = 'image/png'
|
||||||
|
expected = File.read(path)
|
||||||
|
expected.force_encoding(Encoding::BINARY) if expected.respond_to?(:force_encoding)
|
||||||
|
|
||||||
file = ActionController::TestUploadedFile.new(path, content_type)
|
file = ActionController::TestUploadedFile.new(path, content_type)
|
||||||
assert_equal filename, file.original_filename
|
assert_equal filename, file.original_filename
|
||||||
assert_equal content_type, file.content_type
|
assert_equal content_type, file.content_type
|
||||||
assert_equal file.path, file.local_path
|
assert_equal file.path, file.local_path
|
||||||
assert_equal File.read(path), file.read
|
assert_equal expected, file.read
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_test_uploaded_file_with_binary
|
def test_test_uploaded_file_with_binary
|
||||||
|
@ -529,10 +539,10 @@ XML
|
||||||
content_type = 'image/png'
|
content_type = 'image/png'
|
||||||
|
|
||||||
binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary)
|
binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary)
|
||||||
assert_equal File.open(path, 'rb').read, binary_uploaded_file.read
|
assert_equal File.open(path, READ_BINARY).read, binary_uploaded_file.read
|
||||||
|
|
||||||
plain_uploaded_file = ActionController::TestUploadedFile.new(path, content_type)
|
plain_uploaded_file = ActionController::TestUploadedFile.new(path, content_type)
|
||||||
assert_equal File.open(path, 'r').read, plain_uploaded_file.read
|
assert_equal File.open(path, READ_PLAIN).read, plain_uploaded_file.read
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fixture_file_upload_with_binary
|
def test_fixture_file_upload_with_binary
|
||||||
|
@ -541,10 +551,10 @@ XML
|
||||||
content_type = 'image/jpg'
|
content_type = 'image/jpg'
|
||||||
|
|
||||||
binary_file_upload = fixture_file_upload(path, content_type, :binary)
|
binary_file_upload = fixture_file_upload(path, content_type, :binary)
|
||||||
assert_equal File.open(path, 'rb').read, binary_file_upload.read
|
assert_equal File.open(path, READ_BINARY).read, binary_file_upload.read
|
||||||
|
|
||||||
plain_file_upload = fixture_file_upload(path, content_type)
|
plain_file_upload = fixture_file_upload(path, content_type)
|
||||||
assert_equal File.open(path, 'r').read, plain_file_upload.read
|
assert_equal File.open(path, READ_PLAIN).read, plain_file_upload.read
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fixture_file_upload
|
def test_fixture_file_upload
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
require 'abstract_unit'
|
|
||||||
require 'action_view/helpers/date_helper'
|
|
||||||
require 'action_view/compiled_templates'
|
|
||||||
|
|
||||||
class CompiledTemplateTests < Test::Unit::TestCase
|
|
||||||
def setup
|
|
||||||
@ct = ActionView::CompiledTemplates.new
|
|
||||||
@v = Class.new
|
|
||||||
@v.send :include, @ct
|
|
||||||
@a = './test_compile_template_a.rhtml'
|
|
||||||
@b = './test_compile_template_b.rhtml'
|
|
||||||
@s = './test_compile_template_link.rhtml'
|
|
||||||
end
|
|
||||||
def teardown
|
|
||||||
[@a, @b, @s].each do |f|
|
|
||||||
FileUtils.rm(f) if File.exist?(f) || File.symlink?(f)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
attr_reader :ct, :v
|
|
||||||
|
|
||||||
def test_name_allocation
|
|
||||||
hi_world = ct.method_names['hi world']
|
|
||||||
hi_sexy = ct.method_names['hi sexy']
|
|
||||||
wish_upon_a_star = ct.method_names['I love seeing decent error messages']
|
|
||||||
|
|
||||||
assert_equal hi_world, ct.method_names['hi world']
|
|
||||||
assert_equal hi_sexy, ct.method_names['hi sexy']
|
|
||||||
assert_equal wish_upon_a_star, ct.method_names['I love seeing decent error messages']
|
|
||||||
assert_equal 3, [hi_world, hi_sexy, wish_upon_a_star].uniq.length
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_wrap_source
|
|
||||||
assert_equal(
|
|
||||||
"def aliased_assignment(value)\nself.value = value\nend",
|
|
||||||
@ct.wrap_source(:aliased_assignment, [:value], 'self.value = value')
|
|
||||||
)
|
|
||||||
|
|
||||||
assert_equal(
|
|
||||||
"def simple()\nnil\nend",
|
|
||||||
@ct.wrap_source(:simple, [], 'nil')
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_compile_source_single_method
|
|
||||||
selector = ct.compile_source('doubling method', [:a], 'a + a')
|
|
||||||
assert_equal 2, @v.new.send(selector, 1)
|
|
||||||
assert_equal 4, @v.new.send(selector, 2)
|
|
||||||
assert_equal -4, @v.new.send(selector, -2)
|
|
||||||
assert_equal 0, @v.new.send(selector, 0)
|
|
||||||
selector
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_compile_source_two_method
|
|
||||||
sel1 = test_compile_source_single_method # compile the method in the other test
|
|
||||||
sel2 = ct.compile_source('doubling method', [:a, :b], 'a + b + a + b')
|
|
||||||
assert_not_equal sel1, sel2
|
|
||||||
|
|
||||||
assert_equal 2, @v.new.send(sel1, 1)
|
|
||||||
assert_equal 4, @v.new.send(sel1, 2)
|
|
||||||
|
|
||||||
assert_equal 6, @v.new.send(sel2, 1, 2)
|
|
||||||
assert_equal 32, @v.new.send(sel2, 15, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_mtime
|
|
||||||
t1 = Time.now
|
|
||||||
|
|
||||||
test_compile_source_single_method
|
|
||||||
mtime = ct.mtime('doubling method', [:a])
|
|
||||||
|
|
||||||
assert mtime < Time.now
|
|
||||||
assert mtime > t1
|
|
||||||
end
|
|
||||||
|
|
||||||
uses_mocha 'test_compile_time' do
|
|
||||||
|
|
||||||
def test_compile_time
|
|
||||||
t = Time.now
|
|
||||||
|
|
||||||
File.open(@a, "w"){|f| f.puts @a}
|
|
||||||
File.open(@b, "w"){|f| f.puts @b}
|
|
||||||
# windows doesn't support symlinks (even under cygwin)
|
|
||||||
windows = (RUBY_PLATFORM =~ /win32/)
|
|
||||||
`ln -s #{@a} #{@s}` unless windows
|
|
||||||
|
|
||||||
v = ActionView::Base.new
|
|
||||||
v.base_path = '.'
|
|
||||||
v.cache_template_loading = false
|
|
||||||
|
|
||||||
ta = ActionView::Template.new(v, @a, false, {})
|
|
||||||
tb = ActionView::Template.new(v, @b, false, {})
|
|
||||||
ts = ActionView::Template.new(v, @s, false, {})
|
|
||||||
|
|
||||||
@handler_class = ActionView::Template.handler_class_for_extension(:rhtml)
|
|
||||||
@handler = @handler_class.new(v)
|
|
||||||
|
|
||||||
# All templates were created at t+1
|
|
||||||
File::Stat.any_instance.expects(:mtime).times(windows ? 2 : 3).returns(t + 1.second)
|
|
||||||
|
|
||||||
# private methods template_changed_since? and compile_template?
|
|
||||||
# should report true for all since they have not been compiled
|
|
||||||
assert @handler.send(:template_changed_since?, @a, t)
|
|
||||||
assert @handler.send(:template_changed_since?, @b, t)
|
|
||||||
assert @handler.send(:template_changed_since?, @s, t) unless windows
|
|
||||||
|
|
||||||
assert @handler.send(:compile_template?, ta)
|
|
||||||
assert @handler.send(:compile_template?, tb)
|
|
||||||
assert @handler.send(:compile_template?, ts) unless windows
|
|
||||||
|
|
||||||
# All templates are rendered at t+2
|
|
||||||
Time.expects(:now).times(windows ? 2 : 3).returns(t + 2.seconds)
|
|
||||||
v.send(:render_template, ta)
|
|
||||||
v.send(:render_template, tb)
|
|
||||||
v.send(:render_template, ts) unless windows
|
|
||||||
a_n = v.method_names[@a]
|
|
||||||
b_n = v.method_names[@b]
|
|
||||||
s_n = v.method_names[@s] unless windows
|
|
||||||
# all of the files have changed since last compile
|
|
||||||
assert @handler.compile_time[a_n] > t
|
|
||||||
assert @handler.compile_time[b_n] > t
|
|
||||||
assert @handler.compile_time[s_n] > t unless windows
|
|
||||||
|
|
||||||
# private methods template_changed_since? and compile_template?
|
|
||||||
# should report false for all since none have changed since compile
|
|
||||||
File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 12).returns(t + 1.second)
|
|
||||||
assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n])
|
|
||||||
assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n])
|
|
||||||
assert !@handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows
|
|
||||||
assert !@handler.send(:compile_template?, ta)
|
|
||||||
assert !@handler.send(:compile_template?, tb)
|
|
||||||
assert !@handler.send(:compile_template?, ts) unless windows
|
|
||||||
v.send(:render_template, ta)
|
|
||||||
v.send(:render_template, tb)
|
|
||||||
v.send(:render_template, ts) unless windows
|
|
||||||
# none of the files have changed since last compile
|
|
||||||
assert @handler.compile_time[a_n] < t + 3.seconds
|
|
||||||
assert @handler.compile_time[b_n] < t + 3.seconds
|
|
||||||
assert @handler.compile_time[s_n] < t + 3.seconds unless windows
|
|
||||||
|
|
||||||
`rm #{@s}; ln -s #{@b} #{@s}` unless windows
|
|
||||||
# private methods template_changed_since? and compile_template?
|
|
||||||
# should report true for symlink since it has changed since compile
|
|
||||||
|
|
||||||
# t + 3.seconds is for the symlink
|
|
||||||
File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 9).returns(
|
|
||||||
*(windows ? [ t + 1.second, t + 1.second ] :
|
|
||||||
[ t + 1.second, t + 1.second, t + 3.second ]) * 3)
|
|
||||||
assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n])
|
|
||||||
assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n])
|
|
||||||
assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows
|
|
||||||
assert !@handler.send(:compile_template?, ta)
|
|
||||||
assert !@handler.send(:compile_template?, tb)
|
|
||||||
assert @handler.send(:compile_template?, ts) unless windows
|
|
||||||
|
|
||||||
# Only the symlink template gets rendered at t+3
|
|
||||||
Time.stubs(:now).returns(t + 3.seconds) unless windows
|
|
||||||
v.send(:render_template, ta)
|
|
||||||
v.send(:render_template, tb)
|
|
||||||
v.send(:render_template, ts) unless windows
|
|
||||||
# the symlink has changed since last compile
|
|
||||||
assert @handler.compile_time[a_n] < t + 3.seconds
|
|
||||||
assert @handler.compile_time[b_n] < t + 3.seconds
|
|
||||||
assert_equal @handler.compile_time[s_n], t + 3.seconds unless windows
|
|
||||||
|
|
||||||
FileUtils.touch @b
|
|
||||||
# private methods template_changed_since? and compile_template?
|
|
||||||
# should report true for symlink and file at end of symlink
|
|
||||||
# since it has changed since last compile
|
|
||||||
#
|
|
||||||
# t+4 is for @b and also for the file that @s points to, which is @b
|
|
||||||
File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 12).returns(
|
|
||||||
*(windows ? [ t + 1.second, t + 4.seconds ] :
|
|
||||||
[ t + 1.second, t + 4.seconds, t + 3.second, t + 4.seconds ]) * 3)
|
|
||||||
assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n])
|
|
||||||
assert @handler.send(:template_changed_since?, @b, @handler.compile_time[b_n])
|
|
||||||
assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows
|
|
||||||
assert !@handler.send(:compile_template?, ta)
|
|
||||||
assert @handler.send(:compile_template?, tb)
|
|
||||||
assert @handler.send(:compile_template?, ts) unless windows
|
|
||||||
|
|
||||||
Time.expects(:now).times(windows ? 1 : 2).returns(t + 5.seconds)
|
|
||||||
v.send(:render_template, ta)
|
|
||||||
v.send(:render_template, tb)
|
|
||||||
v.send(:render_template, ts) unless windows
|
|
||||||
# the file at the end of the symlink has changed since last compile
|
|
||||||
# both the symlink and the file at the end of it should be recompiled
|
|
||||||
assert @handler.compile_time[a_n] < t + 5.seconds
|
|
||||||
assert_equal @handler.compile_time[b_n], t + 5.seconds
|
|
||||||
assert_equal @handler.compile_time[s_n], t + 5.seconds unless windows
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1722,6 +1722,12 @@ class DateHelperTest < ActionView::TestCase
|
||||||
assert_equal 2, dummy_instance_tag.send!(:default_time_from_options, :hour => 2).hour
|
assert_equal 2, dummy_instance_tag.send!(:default_time_from_options, :hour => 2).hour
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_instance_tag_default_time_from_options_handles_far_future_date
|
||||||
|
dummy_instance_tag = ActionView::Helpers::InstanceTag.new(1,2,3)
|
||||||
|
time = dummy_instance_tag.send!(:default_time_from_options, :year => 2050, :month => 2, :day => 10, :hour => 15, :min => 30, :sec => 45)
|
||||||
|
assert_equal 2050, time.year
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -181,6 +181,17 @@ class FormHelperTest < ActionView::TestCase
|
||||||
'<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />',
|
'<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />',
|
||||||
check_box("post", "secret?")
|
check_box("post", "secret?")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@post.secret = ['0']
|
||||||
|
assert_dom_equal(
|
||||||
|
'<input id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />',
|
||||||
|
check_box("post", "secret")
|
||||||
|
)
|
||||||
|
@post.secret = ['1']
|
||||||
|
assert_dom_equal(
|
||||||
|
'<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />',
|
||||||
|
check_box("post", "secret")
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_check_box_with_explicit_checked_and_unchecked_values
|
def test_check_box_with_explicit_checked_and_unchecked_values
|
||||||
|
|
|
@ -25,8 +25,6 @@ class Author::Nested < Author; end
|
||||||
|
|
||||||
|
|
||||||
class PrototypeHelperBaseTest < ActionView::TestCase
|
class PrototypeHelperBaseTest < ActionView::TestCase
|
||||||
tests ActionView::Helpers::PrototypeHelper
|
|
||||||
|
|
||||||
attr_accessor :template_format
|
attr_accessor :template_format
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
@ -86,6 +84,11 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
|
||||||
link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } })
|
link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_link_to_remote_url_quote_escaping
|
||||||
|
assert_dom_equal %(<a href="#" onclick="new Ajax.Request('http://www.example.com/whatnot\\\'s', {asynchronous:true, evalScripts:true}); return false;">Remote</a>),
|
||||||
|
link_to_remote("Remote", { :url => { :action => "whatnot's" } })
|
||||||
|
end
|
||||||
|
|
||||||
def test_periodically_call_remote
|
def test_periodically_call_remote
|
||||||
assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
|
assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
|
||||||
periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
|
periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
|
||||||
|
@ -214,9 +217,9 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_observe_field_using_with_option
|
def test_observe_field_using_with_option
|
||||||
expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + value})})\n//]]>\n</script>)
|
expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(value)})})\n//]]>\n</script>)
|
||||||
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
|
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
|
||||||
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + value")
|
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_observe_field_using_json_in_with_option
|
def test_observe_field_using_json_in_with_option
|
||||||
|
|
|
@ -167,17 +167,8 @@ class TextHelperTest < ActionView::TestCase
|
||||||
assert_equal("0 counters", pluralize(nil, "count", "counters"))
|
assert_equal("0 counters", pluralize(nil, "count", "counters"))
|
||||||
assert_equal("2 people", pluralize(2, "person"))
|
assert_equal("2 people", pluralize(2, "person"))
|
||||||
assert_equal("10 buffaloes", pluralize(10, "buffalo"))
|
assert_equal("10 buffaloes", pluralize(10, "buffalo"))
|
||||||
end
|
assert_equal("1 berry", pluralize(1, "berry"))
|
||||||
|
assert_equal("12 berries", pluralize(12, "berry"))
|
||||||
uses_mocha("should_just_add_s_for_pluralize_without_inflector_loaded") do
|
|
||||||
def test_should_just_add_s_for_pluralize_without_inflector_loaded
|
|
||||||
Object.expects(:const_defined?).with("Inflector").times(4).returns(false)
|
|
||||||
assert_equal("1 count", pluralize(1, "count"))
|
|
||||||
assert_equal("2 persons", pluralize(2, "person"))
|
|
||||||
assert_equal("2 personss", pluralize("2", "persons"))
|
|
||||||
assert_equal("2 counts", pluralize(2, "count"))
|
|
||||||
assert_equal("10 buffalos", pluralize(10, "buffalo"))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_auto_link_parsing
|
def test_auto_link_parsing
|
||||||
|
@ -195,6 +186,7 @@ class TextHelperTest < ActionView::TestCase
|
||||||
http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007
|
http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007
|
||||||
http://www.mail-archive.com/rails@lists.rubyonrails.org/
|
http://www.mail-archive.com/rails@lists.rubyonrails.org/
|
||||||
http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1
|
http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1
|
||||||
|
http://en.wikipedia.org/wiki/Sprite_(computer_graphics)
|
||||||
)
|
)
|
||||||
|
|
||||||
urls.each do |url|
|
urls.each do |url|
|
||||||
|
@ -271,6 +263,8 @@ class TextHelperTest < ActionView::TestCase
|
||||||
assert_equal email2_result, auto_link(email2_raw)
|
assert_equal email2_result, auto_link(email2_raw)
|
||||||
assert_equal '', auto_link(nil)
|
assert_equal '', auto_link(nil)
|
||||||
assert_equal '', auto_link('')
|
assert_equal '', auto_link('')
|
||||||
|
assert_equal "#{link_result} #{link_result} #{link_result}", auto_link("#{link_raw} #{link_raw} #{link_raw}")
|
||||||
|
assert_equal '<a href="http://www.rubyonrails.com">Ruby On Rails</a>', auto_link('<a href="http://www.rubyonrails.com">Ruby On Rails</a>')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_auto_link_at_eol
|
def test_auto_link_at_eol
|
||||||
|
|
12
vendor/rails/activemodel/CHANGES
vendored
Normal file
12
vendor/rails/activemodel/CHANGES
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Changes from extracting bits to ActiveModel
|
||||||
|
|
||||||
|
* ActiveModel::Observer#add_observer!
|
||||||
|
|
||||||
|
It has a custom hook to define after_find that should really be in a
|
||||||
|
ActiveRecord::Observer subclass:
|
||||||
|
|
||||||
|
def add_observer!(klass)
|
||||||
|
klass.add_observer(self)
|
||||||
|
klass.class_eval 'def after_find() end' unless
|
||||||
|
klass.respond_to?(:after_find)
|
||||||
|
end
|
21
vendor/rails/activemodel/README
vendored
Normal file
21
vendor/rails/activemodel/README
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Active Model
|
||||||
|
==============
|
||||||
|
|
||||||
|
Totally experimental library that aims to extract common model mixins from
|
||||||
|
ActiveRecord for use in ActiveResource (and other similar libraries).
|
||||||
|
This is in a very rough state (no autotest or spec rake tasks set up yet),
|
||||||
|
so please excuse the mess.
|
||||||
|
|
||||||
|
Here's what I plan to extract:
|
||||||
|
* ActiveModel::Observing
|
||||||
|
* ActiveModel::Callbacks
|
||||||
|
* ActiveModel::Validations
|
||||||
|
|
||||||
|
# for ActiveResource params and ActiveRecord options
|
||||||
|
* ActiveModel::Scoping
|
||||||
|
|
||||||
|
# to_json, to_xml, etc
|
||||||
|
* ActiveModel::Serialization
|
||||||
|
|
||||||
|
I'm trying to keep ActiveRecord compatibility where possible, but I'm
|
||||||
|
annotating the spots where I'm diverging a bit.
|
16
vendor/rails/activemodel/Rakefile
vendored
Normal file
16
vendor/rails/activemodel/Rakefile
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
$LOAD_PATH << File.join(File.dirname(__FILE__), 'vendor', 'rspec', 'lib')
|
||||||
|
require 'rake'
|
||||||
|
require 'spec/rake/spectask'
|
||||||
|
require 'rake/rdoctask'
|
||||||
|
|
||||||
|
# Generate the RDoc documentation
|
||||||
|
Rake::RDocTask.new { |rdoc|
|
||||||
|
rdoc.rdoc_dir = 'doc'
|
||||||
|
rdoc.title = "Active Model"
|
||||||
|
rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
||||||
|
rdoc.options << '--charset' << 'utf-8'
|
||||||
|
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
||||||
|
rdoc.rdoc_files.include('README', 'CHANGES')
|
||||||
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||||
|
}
|
17
vendor/rails/activemodel/lib/active_model.rb
vendored
Normal file
17
vendor/rails/activemodel/lib/active_model.rb
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..', 'activesupport', 'lib')
|
||||||
|
|
||||||
|
# premature optimization?
|
||||||
|
require 'active_support/inflector'
|
||||||
|
require 'active_support/core_ext/string/inflections'
|
||||||
|
String.send :include, ActiveSupport::CoreExtensions::String::Inflections
|
||||||
|
|
||||||
|
require 'active_model/base'
|
||||||
|
require 'active_model/observing'
|
||||||
|
require 'active_model/callbacks'
|
||||||
|
require 'active_model/validations'
|
||||||
|
|
||||||
|
ActiveModel::Base.class_eval do
|
||||||
|
include ActiveModel::Observing
|
||||||
|
include ActiveModel::Callbacks
|
||||||
|
include ActiveModel::Validations
|
||||||
|
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue