Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/rails/rails into rails
Browse files Browse the repository at this point in the history
  • Loading branch information
mikel committed Jan 19, 2010
2 parents ccb7d9d + ed8501e commit 2107921
Show file tree
Hide file tree
Showing 357 changed files with 6,790 additions and 3,122 deletions.
43 changes: 38 additions & 5 deletions actionmailer/lib/action_mailer/base.rb
Expand Up @@ -23,8 +23,7 @@ module ActionMailer #:nodoc:
# bcc ["bcc@example.com", "Order Watcher <watcher@example.com>"] # bcc ["bcc@example.com", "Order Watcher <watcher@example.com>"]
# from "system@example.com" # from "system@example.com"
# subject "New account information" # subject "New account information"
# # body :account => recipient
# @account = recipient
# end # end
# end # end
# #
Expand All @@ -36,7 +35,7 @@ module ActionMailer #:nodoc:
# * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header. # * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header.
# * <tt>bcc</tt> - Takes one or more email addresses. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc:</tt> header. # * <tt>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>reply_to</tt> - Takes one or more email addresses. These addresses will be listed as the default recipients when replying to your email. Sets the <tt>Reply-To:</tt> header.
# * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent. # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header will be set by the delivery agent.
# * <tt>content_type</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>. # * <tt>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>.
# #
Expand Down Expand Up @@ -144,12 +143,13 @@ module ActionMailer #:nodoc:
# subject "New account information" # subject "New account information"
# from "system@example.com" # from "system@example.com"
# content_type "multipart/alternative" # content_type "multipart/alternative"
# body :account => recipient
# #
# part :content_type => "text/html", # part :content_type => "text/html",
# :body => render_message("signup-as-html", :account => recipient) # :data => render_message("signup-as-html")
# #
# part "text/plain" do |p| # part "text/plain" do |p|
# p.body = render_message("signup-as-plain", :account => recipient) # p.body = render_message("signup-as-plain")
# p.content_transfer_encoding = "base64" # p.content_transfer_encoding = "base64"
# end # end
# end # end
Expand Down Expand Up @@ -492,11 +492,13 @@ def matches_dynamic_method?(method_name) #:nodoc:
# body, headers, etc.) can be set on it. # body, headers, etc.) can be set on it.
def part(params) def part(params)
params = {:content_type => params} if String === params params = {:content_type => params} if String === params

if custom_headers = params.delete(:headers) if custom_headers = params.delete(:headers)
ActiveSupport::Deprecation.warn('Passing custom headers with :headers => {} is deprecated. ' << ActiveSupport::Deprecation.warn('Passing custom headers with :headers => {} is deprecated. ' <<
'Please just pass in custom headers directly.', caller[0,10]) 'Please just pass in custom headers directly.', caller[0,10])
params.merge!(custom_headers) params.merge!(custom_headers)
end end

part = Mail::Part.new(params) part = Mail::Part.new(params)
yield part if block_given? yield part if block_given?
@parts << part @parts << part
Expand All @@ -514,6 +516,20 @@ def attachment(params, &block)
part(params, &block) part(params, &block)
end end


# Allow you to set assigns for your template:
#
# body :greetings => "Hi"
#
# Will make @greetings available in the template to be rendered.
def body(object=nil)
returning(super) do # Run deprecation hooks
if object.is_a?(Hash)
@assigns_set = true
object.each { |k, v| instance_variable_set(:"@#{k}", v) }
end
end
end

# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
# will be initialized according to the named method. If not, the mailer will # will be initialized according to the named method. If not, the mailer will
# remain uninitialized (useful when you only need to invoke the "receive" # remain uninitialized (useful when you only need to invoke the "receive"
Expand Down Expand Up @@ -549,6 +565,23 @@ def deliver!(mail = @mail)


private private


# Render a message but does not set it as mail body. Useful for rendering
# data for part and attachments.
#
# Examples:
#
# render_message "special_message"
# render_message :template => "special_message"
# render_message :inline => "<%= 'Hi!' %>"
def render_message(object)
case object
when String
render_to_body(:template => object)
else
render_to_body(object)
end
end

# Set up the default values for the various instance variables of this # Set up the default values for the various instance variables of this
# mailer. Subclasses may override this method to provide different # mailer. Subclasses may override this method to provide different
# defaults. # defaults.
Expand Down
38 changes: 16 additions & 22 deletions actionmailer/lib/action_mailer/deprecated_body.rb
@@ -1,15 +1,13 @@
module ActionMailer module ActionMailer
# TODO Remove this module all together in a next release. Ensure that super # TODO Remove this module all together in a next release. Ensure that super
# hooks in ActionMailer::Base are removed as well. # hooks and @assigns_set in ActionMailer::Base are removed as well.
module DeprecatedBody module DeprecatedBody
def self.included(base) extend ActionMailer::AdvAttrAccessor
base.class_eval do
# Define the body of the message. This is either a Hash (in which case it # Define the body of the message. This is either a Hash (in which case it
# specifies the variables to pass to the template when it is rendered), # specifies the variables to pass to the template when it is rendered),
# or a string, in which case it specifies the actual text of the message. # or a string, in which case it specifies the actual text of the message.
adv_attr_accessor :body adv_attr_accessor :body
end
end


def initialize_defaults(method_name) def initialize_defaults(method_name)
@body ||= {} @body ||= {}
Expand All @@ -18,32 +16,28 @@ def initialize_defaults(method_name)
def attachment(params, &block) def attachment(params, &block)
if params[:body] if params[:body]
ActiveSupport::Deprecation.warn('attachment :body => "string" is deprecated. To set the body of an attachment ' << ActiveSupport::Deprecation.warn('attachment :body => "string" is deprecated. To set the body of an attachment ' <<
'please use :data instead, like attachment :data => "string".', caller[0,10]) 'please use :data instead, like attachment :data => "string"', caller[0,10])
params[:data] = params.delete(:body) params[:data] = params.delete(:body)
end end
end end


def create_parts def create_parts
if String === @body if String === @body && !defined?(@assigns_set)
ActiveSupport::Deprecation.warn('body is deprecated. To set the body with a text ' << ActiveSupport::Deprecation.warn('body(String) is deprecated. To set the body with a text ' <<
'call render(:text => "body").', caller[0,10]) 'call render(:text => "body")', caller[0,10])
self.response_body = @body self.response_body = @body
elsif @body.is_a?(Hash) && !@body.empty? elsif self.response_body
ActiveSupport::Deprecation.warn('body is deprecated. To set assigns simply ' << @body = self.response_body
'use instance variables', caller[0,10])
@body.each { |k, v| instance_variable_set(:"@#{k}", v) }
end end
end end


def render(*args) def render(*args)
options = args.last.is_a?(Hash) ? args.last : {} options = args.last.is_a?(Hash) ? args.last : {}
if options[:body] if options[:body]
ActiveSupport::Deprecation.warn(':body is deprecated. To set assigns simply ' << ActiveSupport::Deprecation.warn(':body in render deprecated. Please call body ' <<
'use instance variables', caller[0,1]) 'with a hash instead', caller[0,1])


options.delete(:body).each do |k, v| body options.delete(:body)
instance_variable_set(:"@#{k}", v)
end
end end


super super
Expand Down
10 changes: 4 additions & 6 deletions actionmailer/test/mail_service_test.rb
Expand Up @@ -120,11 +120,11 @@ def multipart_with_mime_version(recipient)
content_type "multipart/alternative" content_type "multipart/alternative"


part "text/plain" do |p| part "text/plain" do |p|
p.body = "blah" p.body = render_message(:text => "blah")
end end


part "text/html" do |p| part "text/html" do |p|
p.body = "<b>blah</b>" p.body = render_message(:inline => "<%= content_tag(:b, 'blah') %>")
end end
end end


Expand Down Expand Up @@ -301,7 +301,6 @@ def return_path
render :text => "testing" render :text => "testing"
end end


# This tests body calls accepeting a hash, which is deprecated.
def body_ivar(recipient) def body_ivar(recipient)
recipients recipient recipients recipient
subject "Body as a local variable" subject "Body as a local variable"
Expand Down Expand Up @@ -1075,7 +1074,7 @@ def test_return_path_with_create


def test_return_path_with_create def test_return_path_with_create
mail = TestMailer.create_return_path mail = TestMailer.create_return_path
assert_equal "another@somewhere.test", mail.return_path assert_equal ["another@somewhere.test"], mail.return_path
end end


def test_return_path_with_deliver def test_return_path_with_deliver
Expand All @@ -1086,8 +1085,7 @@ def test_return_path_with_deliver
end end


def test_body_is_stored_as_an_ivar def test_body_is_stored_as_an_ivar
mail = nil mail = TestMailer.create_body_ivar(@recipient)
ActiveSupport::Deprecation.silence { mail = TestMailer.create_body_ivar(@recipient) }
assert_equal "body: foo\nbar: baz", mail.body.to_s assert_equal "body: foo\nbar: baz", mail.body.to_s
end end


Expand Down
140 changes: 74 additions & 66 deletions actionpack/lib/abstract_controller/base.rb
Expand Up @@ -62,15 +62,19 @@ def hidden_actions
# Array[String]:: A list of all methods that should be considered # Array[String]:: A list of all methods that should be considered
# actions. # actions.
def action_methods def action_methods
@action_methods ||= @action_methods ||= begin
# All public instance methods of this class, including ancestors # All public instance methods of this class, including ancestors
public_instance_methods(true).map { |m| m.to_s }.to_set - methods = public_instance_methods(true).map { |m| m.to_s }.to_set -
# Except for public instance methods of Base and its ancestors # Except for public instance methods of Base and its ancestors
internal_methods.map { |m| m.to_s } + internal_methods.map { |m| m.to_s } +
# Be sure to include shadowed public instance methods of this class # Be sure to include shadowed public instance methods of this class
public_instance_methods(false).map { |m| m.to_s } - public_instance_methods(false).map { |m| m.to_s } -
# And always exclude explicitly hidden actions # And always exclude explicitly hidden actions
hidden_actions hidden_actions

# Clear out AS callback method pollution
methods.reject { |method| method =~ /_one_time_conditions/ }
end
end end


# Returns the full controller name, underscored, without the ending Controller. # Returns the full controller name, underscored, without the ending Controller.
Expand Down Expand Up @@ -116,68 +120,72 @@ def controller_path
self.class.controller_path self.class.controller_path
end end


private def action_methods
# Returns true if the name can be considered an action. This can self.class.action_methods
# be overridden in subclasses to modify the semantics of what
# can be considered an action.
#
# ==== Parameters
# name<String>:: The name of an action to be tested
#
# ==== Returns
# TrueClass, FalseClass
def action_method?(name)
self.class.action_methods.include?(name)
end end


# Call the action. Override this in a subclass to modify the private
# behavior around processing an action. This, and not #process, # Returns true if the name can be considered an action. This can
# is the intended way to override action dispatching. # be overridden in subclasses to modify the semantics of what
def process_action(method_name, *args) # can be considered an action.
send_action(method_name, *args) #
end # ==== Parameters
# name<String>:: The name of an action to be tested
#
# ==== Returns
# TrueClass, FalseClass
def action_method?(name)
self.class.action_methods.include?(name)
end


# Actually call the method associated with the action. Override # Call the action. Override this in a subclass to modify the
# this method if you wish to change how action methods are called, # behavior around processing an action. This, and not #process,
# not to add additional behavior around it. For example, you would # is the intended way to override action dispatching.
# override #send_action if you want to inject arguments into the def process_action(method_name, *args)
# method. send_action(method_name, *args)
alias send_action send end

# If the action name was not found, but a method called "action_missing"
# was found, #method_for_action will return "_handle_action_missing".
# This method calls #action_missing with the current action name.
def _handle_action_missing
action_missing(@_action_name)
end


# Takes an action name and returns the name of the method that will # Actually call the method associated with the action. Override
# handle the action. In normal cases, this method returns the same # this method if you wish to change how action methods are called,
# name as it receives. By default, if #method_for_action receives # not to add additional behavior around it. For example, you would
# a name that is not an action, it will look for an #action_missing # override #send_action if you want to inject arguments into the
# method and return "_handle_action_missing" if one is found. # method.
# alias send_action send
# Subclasses may override this method to add additional conditions
# that should be considered an action. For instance, an HTTP controller # If the action name was not found, but a method called "action_missing"
# with a template matching the action name is considered to exist. # was found, #method_for_action will return "_handle_action_missing".
# # This method calls #action_missing with the current action name.
# If you override this method to handle additional cases, you may def _handle_action_missing
# also provide a method (like _handle_method_missing) to handle action_missing(@_action_name)
# the case. end
#
# If none of these conditions are true, and method_for_action # Takes an action name and returns the name of the method that will
# returns nil, an ActionNotFound exception will be raised. # handle the action. In normal cases, this method returns the same
# # name as it receives. By default, if #method_for_action receives
# ==== Parameters # a name that is not an action, it will look for an #action_missing
# action_name<String>:: An action name to find a method name for # method and return "_handle_action_missing" if one is found.
# #
# ==== Returns # Subclasses may override this method to add additional conditions
# String:: The name of the method that handles the action # that should be considered an action. For instance, an HTTP controller
# nil:: No method name could be found. Raise ActionNotFound. # with a template matching the action name is considered to exist.
def method_for_action(action_name) #
if action_method?(action_name) then action_name # If you override this method to handle additional cases, you may
elsif respond_to?(:action_missing, true) then "_handle_action_missing" # also provide a method (like _handle_method_missing) to handle
# the case.
#
# If none of these conditions are true, and method_for_action
# returns nil, an ActionNotFound exception will be raised.
#
# ==== Parameters
# action_name<String>:: An action name to find a method name for
#
# ==== Returns
# String:: The name of the method that handles the action
# nil:: No method name could be found. Raise ActionNotFound.
def method_for_action(action_name)
if action_method?(action_name) then action_name
elsif respond_to?(:action_missing, true) then "_handle_action_missing"
end
end end
end
end end
end end
2 changes: 1 addition & 1 deletion actionpack/lib/abstract_controller/rendering.rb
Expand Up @@ -42,7 +42,7 @@ def view_context
# Delegates render_to_body and sticks the result in self.response_body. # Delegates render_to_body and sticks the result in self.response_body.
def render(*args) def render(*args)
if response_body if response_body
raise AbstractController::DoubleRenderError, "OMG" raise AbstractController::DoubleRenderError, "Can only render or redirect once per action"
end end


self.response_body = render_to_body(*args) self.response_body = render_to_body(*args)
Expand Down
5 changes: 1 addition & 4 deletions actionpack/lib/action_controller/deprecated/dispatcher.rb
@@ -1,8 +1,5 @@
module ActionController module ActionController
class Dispatcher class Dispatcher
cattr_accessor :prepare_each_request
self.prepare_each_request = false

class << self class << self
def before_dispatch(*args, &block) def before_dispatch(*args, &block)
ActiveSupport::Deprecation.warn "ActionController::Dispatcher.before_dispatch is deprecated. " << ActiveSupport::Deprecation.warn "ActionController::Dispatcher.before_dispatch is deprecated. " <<
Expand All @@ -18,7 +15,7 @@ def after_dispatch(*args, &block)


def to_prepare(*args, &block) def to_prepare(*args, &block)
ActiveSupport::Deprecation.warn "ActionController::Dispatcher.to_prepare is deprecated. " << ActiveSupport::Deprecation.warn "ActionController::Dispatcher.to_prepare is deprecated. " <<
"Please use ActionDispatch::Callbacks.to_prepare instead.", caller "Please use config.to_prepare instead", caller
ActionDispatch::Callbacks.after(*args, &block) ActionDispatch::Callbacks.after(*args, &block)
end end


Expand Down

0 comments on commit 2107921

Please sign in to comment.