1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

ActionMailer should depend just on AbstractController.

This commit is contained in:
José Valim 2010-01-29 16:16:01 +01:00
parent 2960077445
commit 3f84091937
13 changed files with 200 additions and 198 deletions

View file

@ -24,9 +24,17 @@
actionpack_path = File.expand_path('../../../actionpack/lib', __FILE__)
$:.unshift(actionpack_path) if File.directory?(actionpack_path) && !$:.include?(actionpack_path)
require 'action_controller'
require 'abstract_controller'
require 'action_view'
# Common ActiveSupport usage in ActionMailer
require 'active_support/core_ext/class'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/array/uniq_by'
require 'active_support/core_ext/module/attr_internal'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/string/inflections'
module ActionMailer
extend ::ActiveSupport::Autoload

View file

@ -1,8 +1,3 @@
require 'active_support/core_ext/class'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/array/uniq_by'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/string/inflections'
require 'mail'
require 'action_mailer/tmail_compat'
require 'action_mailer/collector'
@ -254,7 +249,6 @@ module ActionMailer #:nodoc:
include AbstractController::LocalizedCache
include AbstractController::Layouts
include AbstractController::Helpers
include AbstractController::UrlFor
include AbstractController::Translation
helper ActionMailer::MailHelper

View file

@ -17,5 +17,9 @@ module ActionMailer
ActionMailer::Base.send "#{k}=", v
end
end
initializer "action_mailer.url_for" do |app|
ActionMailer::Base.send(:include, ActionController::UrlFor) if defined?(ActionController)
end
end
end

View file

@ -415,6 +415,21 @@ class BaseTest < ActiveSupport::TestCase
assert_equal("7bit", email.parts[1].content_transfer_encoding)
end
test "explicit multipart should be multipart" do
mail = BaseMailer.explicit_multipart
assert_not_nil(mail.content_type_parameters[:boundary])
end
test "should set a content type if only has an html part" do
mail = BaseMailer.html_only
assert_equal('text/html', mail.mime_type)
end
test "should set a content type if only has an plain text part" do
mail = BaseMailer.plain_text_only
assert_equal('text/plain', mail.mime_type)
end
test "explicit multipart with one part is rendered as body" do
email = BaseMailer.custom_block
assert_equal(0, email.parts.size)
@ -456,22 +471,8 @@ class BaseTest < ActiveSupport::TestCase
BaseMailer.expects(:welcome).returns(mail)
BaseMailer.welcome.deliver
end
test "explicit multipart should be multipart" do
mail = BaseMailer.explicit_multipart
assert_not_nil(mail.content_type_parameters[:boundary])
end
test "should set a content type if only has an html part" do
mail = BaseMailer.html_only
assert_equal('text/html', mail.mime_type)
end
test "should set a content type if only has an plain text part" do
mail = BaseMailer.plain_text_only
assert_equal('text/plain', mail.mime_type)
end
# Rendering
test "that you can specify a different template" do
mail = BaseMailer.different_template('explicit_multipart_templates')
assert_equal("HTML Explicit Multipart Templates", mail.html_part.body.decoded)

View file

@ -1,9 +1,12 @@
require 'abstract_unit'
require 'action_controller'
class WelcomeController < ActionController::Base
end
class TestMailer < ActionMailer::Base
include ActionController::UrlFor
default_url_options[:host] = 'www.basecamphq.com'
def signed_up_with_url(recipient)

View file

@ -2,6 +2,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
require 'active_support/ruby/shim'
require 'active_support/dependencies/autoload'
require 'active_support/core_ext/module/attr_internal'
require 'active_support/core_ext/module/delegation'
@ -17,5 +18,4 @@ module AbstractController
autoload :Logger
autoload :Rendering
autoload :Translation
autoload :UrlFor
end

View file

@ -1,156 +0,0 @@
module AbstractController
# In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
# is also possible: an URL can be generated from one of your routing definitions.
# URL generation functionality is centralized in this module.
#
# See AbstractController::Routing and AbstractController::Resources for general
# information about routing and routes.rb.
#
# <b>Tip:</b> If you need to generate URLs from your models or some other place,
# then AbstractController::UrlFor is what you're looking for. Read on for
# an introduction.
#
# == URL generation from parameters
#
# As you may know, some functions - such as AbstractController::Base#url_for
# and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
# of parameters. For example, you've probably had the chance to write code
# like this in one of your views:
#
# <%= link_to('Click here', :controller => 'users',
# :action => 'new', :message => 'Welcome!') %>
#
# #=> Generates a link to: /users/new?message=Welcome%21
#
# link_to, and all other functions that require URL generation functionality,
# actually use AbstractController::UrlFor under the hood. And in particular,
# they use the AbstractController::UrlFor#url_for method. One can generate
# the same path as the above example by using the following code:
#
# include UrlFor
# url_for(:controller => 'users',
# :action => 'new',
# :message => 'Welcome!',
# :only_path => true)
# # => "/users/new?message=Welcome%21"
#
# Notice the <tt>:only_path => true</tt> part. This is because UrlFor has no
# information about the website hostname that your Rails app is serving. So if you
# want to include the hostname as well, then you must also pass the <tt>:host</tt>
# argument:
#
# include UrlFor
# url_for(:controller => 'users',
# :action => 'new',
# :message => 'Welcome!',
# :host => 'www.example.com') # Changed this.
# # => "http://www.example.com/users/new?message=Welcome%21"
#
# By default, all controllers and views have access to a special version of url_for,
# that already knows what the current hostname is. So if you use url_for in your
# controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
# argument.
#
# For convenience reasons, mailers provide a shortcut for AbstractController::UrlFor#url_for.
# So within mailers, you only have to type 'url_for' instead of 'AbstractController::UrlFor#url_for'
# in full. However, mailers don't have hostname information, and what's why you'll still
# have to specify the <tt>:host</tt> argument when generating URLs in mailers.
#
#
# == URL generation for named routes
#
# UrlFor also allows one to access methods that have been auto-generated from
# named routes. For example, suppose that you have a 'users' resource in your
# <b>routes.rb</b>:
#
# map.resources :users
#
# This generates, among other things, the method <tt>users_path</tt>. By default,
# this method is accessible from your controllers, views and mailers. If you need
# to access this auto-generated method from other places (such as a model), then
# you can do that by including AbstractController::UrlFor in your class:
#
# class User < ActiveRecord::Base
# include AbstractController::UrlFor
#
# def base_uri
# user_path(self)
# end
# end
#
# User.find(1).base_uri # => "/users/1"
#
module UrlFor
extend ActiveSupport::Concern
included do
ActionController::Routing::Routes.install_helpers(self)
extlib_inheritable_accessor :default_url_options,
:instance_writer => false, :instance_reader => false
self.default_url_options ||= {}
end
# Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
# the form of a hash, just like the one you would use for url_for directly. Example:
#
# def default_url_options(options)
# { :project => @project.active? ? @project.url_name : "unknown" }
# end
#
# As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the
# urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set
# by this method.
def default_url_options(options = nil)
self.class.default_url_options
end
def rewrite_options(options) #:nodoc:
if options.delete(:use_defaults) != false && (defaults = default_url_options(options))
defaults.merge(options)
else
options
end
end
# Generate a url based on the options provided, default_url_options and the
# routes defined in routes.rb. The following options are supported:
#
# * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
# If <tt>:only_path</tt> is false, this option must be
# provided either explicitly, or via +default_url_options+.
# * <tt>:port</tt> - Optionally specify the port to connect to.
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
# * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the
# +relative_url_root+ set in AbstractController::Base.relative_url_root.
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
#
# Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
# +url_for+ is forwarded to the Routes module.
#
# Examples:
#
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
# url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
def url_for(options = {})
options ||= {}
case options
when String
options
when Hash
_url_rewriter.rewrite(rewrite_options(options))
else
polymorphic_url(options)
end
end
protected
def _url_rewriter
ActionController::UrlRewriter
end
end
end

View file

@ -1,6 +1,5 @@
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
require 'active_support/ruby/shim'
require 'abstract_controller'
require 'action_dispatch'
module ActionController
extend ActiveSupport::Autoload
@ -41,6 +40,7 @@ module ActionController
autoload :Integration, 'action_controller/deprecated/integration_test'
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
autoload :UrlWriter, 'action_controller/deprecated'
autoload :Routing, 'action_controller/deprecated'
autoload :TestCase, 'action_controller/test_case'
@ -66,13 +66,11 @@ module ActionController
end
# All of these simply register additional autoloads
require 'abstract_controller'
require 'action_dispatch'
require 'action_view'
require 'action_controller/vendor/html-scanner'
# Common ActiveSupport usage in ActionController
require "active_support/concern"
require 'active_support/concern'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/load_error'
require 'active_support/core_ext/module/attr_internal'

View file

@ -81,5 +81,13 @@ module ActionController
filter << block if block
filter
end
protected
# Overwrite url rewriter to use request.
def _url_rewriter
return ActionController::UrlRewriter unless request
@_url_rewriter ||= ActionController::UrlRewriter.new(request, params)
end
end
end

View file

@ -2,4 +2,4 @@ ActionController::AbstractRequest = ActionController::Request = ActionDispatch::
ActionController::AbstractResponse = ActionController::Response = ActionDispatch::Response
ActionController::Routing = ActionDispatch::Routing
ActionController::Routing::Routes = ActionDispatch::Routing::RouteSet.new
ActionController::UrlWriter = AbstractController::UrlFor
ActionController::UrlWriter = ActionController::UrlFor

View file

@ -1,15 +1,156 @@
module ActionController
# In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
# is also possible: an URL can be generated from one of your routing definitions.
# URL generation functionality is centralized in this module.
#
# See ActionController::Routing and ActionController::Resources for general
# information about routing and routes.rb.
#
# <b>Tip:</b> If you need to generate URLs from your models or some other place,
# then ActionController::UrlFor is what you're looking for. Read on for
# an introduction.
#
# == URL generation from parameters
#
# As you may know, some functions - such as ActionController::Base#url_for
# and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
# of parameters. For example, you've probably had the chance to write code
# like this in one of your views:
#
# <%= link_to('Click here', :controller => 'users',
# :action => 'new', :message => 'Welcome!') %>
#
# #=> Generates a link to: /users/new?message=Welcome%21
#
# link_to, and all other functions that require URL generation functionality,
# actually use ActionController::UrlFor under the hood. And in particular,
# they use the ActionController::UrlFor#url_for method. One can generate
# the same path as the above example by using the following code:
#
# include UrlFor
# url_for(:controller => 'users',
# :action => 'new',
# :message => 'Welcome!',
# :only_path => true)
# # => "/users/new?message=Welcome%21"
#
# Notice the <tt>:only_path => true</tt> part. This is because UrlFor has no
# information about the website hostname that your Rails app is serving. So if you
# want to include the hostname as well, then you must also pass the <tt>:host</tt>
# argument:
#
# include UrlFor
# url_for(:controller => 'users',
# :action => 'new',
# :message => 'Welcome!',
# :host => 'www.example.com') # Changed this.
# # => "http://www.example.com/users/new?message=Welcome%21"
#
# By default, all controllers and views have access to a special version of url_for,
# that already knows what the current hostname is. So if you use url_for in your
# controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
# argument.
#
# For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for.
# So within mailers, you only have to type 'url_for' instead of 'ActionController::UrlFor#url_for'
# in full. However, mailers don't have hostname information, and what's why you'll still
# have to specify the <tt>:host</tt> argument when generating URLs in mailers.
#
#
# == URL generation for named routes
#
# UrlFor also allows one to access methods that have been auto-generated from
# named routes. For example, suppose that you have a 'users' resource in your
# <b>routes.rb</b>:
#
# map.resources :users
#
# This generates, among other things, the method <tt>users_path</tt>. By default,
# this method is accessible from your controllers, views and mailers. If you need
# to access this auto-generated method from other places (such as a model), then
# you can do that by including ActionController::UrlFor in your class:
#
# class User < ActiveRecord::Base
# include ActionController::UrlFor
#
# def base_uri
# user_path(self)
# end
# end
#
# User.find(1).base_uri # => "/users/1"
#
module UrlFor
extend ActiveSupport::Concern
include AbstractController::UrlFor
include ActionController::RackDelegation
included do
ActionController::Routing::Routes.install_helpers(self)
extlib_inheritable_accessor :default_url_options,
:instance_writer => false, :instance_reader => false
self.default_url_options ||= {}
end
# Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
# the form of a hash, just like the one you would use for url_for directly. Example:
#
# def default_url_options(options)
# { :project => @project.active? ? @project.url_name : "unknown" }
# end
#
# As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the
# urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set
# by this method.
def default_url_options(options = nil)
self.class.default_url_options
end
def rewrite_options(options) #:nodoc:
if options.delete(:use_defaults) != false && (defaults = default_url_options(options))
defaults.merge(options)
else
options
end
end
# Generate a url based on the options provided, default_url_options and the
# routes defined in routes.rb. The following options are supported:
#
# * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
# If <tt>:only_path</tt> is false, this option must be
# provided either explicitly, or via +default_url_options+.
# * <tt>:port</tt> - Optionally specify the port to connect to.
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
# * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the
# +relative_url_root+ set in ActionController::Base.relative_url_root.
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
#
# Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
# +url_for+ is forwarded to the Routes module.
#
# Examples:
#
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
# url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
def url_for(options = {})
options ||= {}
case options
when String
options
when Hash
_url_rewriter.rewrite(rewrite_options(options))
else
polymorphic_url(options)
end
end
protected
def _url_rewriter
return ActionController::UrlRewriter unless request
@_url_rewriter ||= ActionController::UrlRewriter.new(request, params)
ActionController::UrlRewriter
end
end
end

View file

@ -23,6 +23,7 @@
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
require 'active_support'
require 'active_support/dependencies/autoload'

View file

@ -5,7 +5,7 @@ module AbstractController
class UrlForTests < ActionController::TestCase
class W
include AbstractController::UrlFor
include ActionController::UrlFor
end
def teardown
@ -132,7 +132,7 @@ module AbstractController
end
# We need to create a new class in order to install the new named route.
kls = Class.new { include AbstractController::UrlFor }
kls = Class.new { include ActionController::UrlFor }
controller = kls.new
assert controller.respond_to?(:home_url)
assert_equal 'http://www.basecamphq.com/home/sweet/home/again',
@ -153,7 +153,7 @@ module AbstractController
match '/home/sweet/home/:user', :to => 'home#index', :as => :home
end
kls = Class.new { include AbstractController::UrlFor }
kls = Class.new { include ActionController::UrlFor }
controller = kls.new
assert_equal 'http://www.basecamphq.com/subdir/home/sweet/home/again',
@ -171,7 +171,7 @@ module AbstractController
end
# We need to create a new class in order to install the new named route.
kls = Class.new { include AbstractController::UrlFor }
kls = Class.new { include ActionController::UrlFor }
controller = kls.new
assert controller.respond_to?(:home_url)
assert_equal '/brave/new/world',
@ -239,7 +239,7 @@ module AbstractController
end
# We need to create a new class in order to install the new named route.
kls = Class.new { include AbstractController::UrlFor }
kls = Class.new { include ActionController::UrlFor }
kls.default_url_options[:host] = 'www.basecamphq.com'
controller = kls.new
@ -251,8 +251,8 @@ module AbstractController
end
def test_multiple_includes_maintain_distinct_options
first_class = Class.new { include AbstractController::UrlFor }
second_class = Class.new { include AbstractController::UrlFor }
first_class = Class.new { include ActionController::UrlFor }
second_class = Class.new { include ActionController::UrlFor }
first_host, second_host = 'firsthost.com', 'secondhost.com'