Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/lifo/docrails
Browse files Browse the repository at this point in the history
  • Loading branch information
tekin committed Mar 10, 2009
2 parents 7fa0a8d + 5739626 commit f1e903a
Show file tree
Hide file tree
Showing 207 changed files with 3,188 additions and 1,509 deletions.
2 changes: 1 addition & 1 deletion actionmailer/CHANGELOG
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,4 @@
*Edge* *2.3.1 [RC2] (March 5, 2009)*


* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones] * Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones]


Expand Down
2 changes: 1 addition & 1 deletion actionmailer/Rakefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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.3.0' + PKG_BUILD) s.add_dependency('actionpack', '= 2.3.1' + PKG_BUILD)


s.has_rdoc = true s.has_rdoc = true
s.requirements << 'none' s.requirements << 'none'
Expand Down
3 changes: 2 additions & 1 deletion actionmailer/lib/action_mailer.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ module Net
end end


autoload :MailHelper, 'action_mailer/mail_helper' autoload :MailHelper, 'action_mailer/mail_helper'
autoload :TMail, 'action_mailer/vendor/tmail'
require 'action_mailer/vendor/tmail'
5 changes: 4 additions & 1 deletion actionmailer/lib/action_mailer/part.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ def to_mail(defaults)
part.parts << prt part.parts << prt
end end


part.set_content_type(real_content_type, nil, ctype_attrs) if real_content_type =~ /multipart/ if real_content_type =~ /multipart/
ctype_attrs.delete 'charset'
part.set_content_type(real_content_type, nil, ctype_attrs)
end
end end


headers.each { |k,v| part[k] = v } headers.each { |k,v| part[k] = v }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ def test_format_style
assert_equal(Text::Format::JUSTIFY, @format_o.format_style) assert_equal(Text::Format::JUSTIFY, @format_o.format_style)
assert_match(/^of freedom, and that government of the people, by the people, for the$/, assert_match(/^of freedom, and that government of the people, by the people, for the$/,
@format_o.format(GETTYSBURG).split("\n")[-3]) @format_o.format(GETTYSBURG).split("\n")[-3])
assert_raises(ArgumentError) { @format_o.format_style = 33 } assert_raise(ArgumentError) { @format_o.format_style = 33 }
end end


def test_tag_paragraph def test_tag_paragraph
Expand Down
2 changes: 1 addition & 1 deletion actionmailer/lib/action_mailer/version.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module ActionMailer
module VERSION #:nodoc: module VERSION #:nodoc:
MAJOR = 2 MAJOR = 2
MINOR = 3 MINOR = 3
TINY = 0 TINY = 1


STRING = [MAJOR, MINOR, TINY].join('.') STRING = [MAJOR, MINOR, TINY].join('.')
end end
Expand Down
3 changes: 2 additions & 1 deletion actionmailer/test/mail_service_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ def test_nested_parts
assert_equal "multipart/mixed", created.content_type assert_equal "multipart/mixed", created.content_type
assert_equal "multipart/alternative", created.parts.first.content_type assert_equal "multipart/alternative", created.parts.first.content_type
assert_equal "bar", created.parts.first.header['foo'].to_s assert_equal "bar", created.parts.first.header['foo'].to_s
assert_nil created.parts.first.charset
assert_equal "text/plain", created.parts.first.parts.first.content_type assert_equal "text/plain", created.parts.first.parts.first.content_type
assert_equal "text/html", created.parts.first.parts[1].content_type assert_equal "text/html", created.parts.first.parts[1].content_type
assert_equal "application/octet-stream", created.parts[1].content_type assert_equal "application/octet-stream", created.parts[1].content_type
Expand Down Expand Up @@ -1068,7 +1069,7 @@ def test_should_not_respond_to_method_where_deliver_is_not_a_suffix
end end


def test_should_still_raise_exception_with_expected_message_when_calling_an_undefined_method def test_should_still_raise_exception_with_expected_message_when_calling_an_undefined_method
error = assert_raises NoMethodError do error = assert_raise NoMethodError do
RespondToMailer.not_a_method RespondToMailer.not_a_method
end end


Expand Down
8 changes: 4 additions & 4 deletions actionmailer/test/test_helper_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_mailer_class_is_correctly_inferred
end end


def test_determine_default_mailer_raises_correct_error def test_determine_default_mailer_raises_correct_error
assert_raises(ActionMailer::NonInferrableMailerError) do assert_raise(ActionMailer::NonInferrableMailerError) do
self.class.determine_default_mailer("NotAMailerTest") self.class.determine_default_mailer("NotAMailerTest")
end end
end end
Expand Down Expand Up @@ -84,7 +84,7 @@ def test_assert_no_emails
end end


def test_assert_emails_too_few_sent def test_assert_emails_too_few_sent
error = assert_raises ActiveSupport::TestCase::Assertion do error = assert_raise ActiveSupport::TestCase::Assertion do
assert_emails 2 do assert_emails 2 do
TestHelperMailer.deliver_test TestHelperMailer.deliver_test
end end
Expand All @@ -94,7 +94,7 @@ def test_assert_emails_too_few_sent
end end


def test_assert_emails_too_many_sent def test_assert_emails_too_many_sent
error = assert_raises ActiveSupport::TestCase::Assertion do error = assert_raise ActiveSupport::TestCase::Assertion do
assert_emails 1 do assert_emails 1 do
TestHelperMailer.deliver_test TestHelperMailer.deliver_test
TestHelperMailer.deliver_test TestHelperMailer.deliver_test
Expand All @@ -105,7 +105,7 @@ def test_assert_emails_too_many_sent
end end


def test_assert_no_emails_failure def test_assert_no_emails_failure
error = assert_raises ActiveSupport::TestCase::Assertion do error = assert_raise ActiveSupport::TestCase::Assertion do
assert_no_emails do assert_no_emails do
TestHelperMailer.deliver_test TestHelperMailer.deliver_test
end end
Expand Down
8 changes: 7 additions & 1 deletion actionpack/CHANGELOG
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,10 @@
*Edge* *2.3.1 [RC2] (March 5, 2009)*

* Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #<Post:0x23150b8>") [DHH]

* Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable #2095 [Gregg Pollack]

* Fixed that passing a custom form builder would be forwarded to nested fields_for calls #2023 [Eloy Duran/Nate Wiger]


* Form option helpers now support disabled option tags and the use of lambdas for selecting/disabling option tags from collections #837 [Tekin] * Form option helpers now support disabled option tags and the use of lambdas for selecting/disabling option tags from collections #837 [Tekin]


Expand Down
2 changes: 1 addition & 1 deletion actionpack/Rakefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -80,7 +80,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.3.0' + PKG_BUILD) s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD)
s.add_dependency('rack', '>= 0.9.0') s.add_dependency('rack', '>= 0.9.0')


s.require_path = 'lib' s.require_path = 'lib'
Expand Down
54 changes: 43 additions & 11 deletions actionpack/lib/action_controller/base.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MethodNotAllowed < ActionControllerError #:nodoc:
attr_reader :allowed_methods attr_reader :allowed_methods


def initialize(*allowed_methods) def initialize(*allowed_methods)
super("Only #{allowed_methods.to_sentence} requests are allowed.") super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
@allowed_methods = allowed_methods @allowed_methods = allowed_methods
end end


Expand Down Expand Up @@ -907,13 +907,15 @@ def render(options = nil, extra_options = {}, &block) #:doc:
extra_options[:template] = options extra_options[:template] = options
end end


options = extra_options
elsif !options.is_a?(Hash)
extra_options[:partial] = options
options = extra_options options = extra_options
end end


layout = pick_layout(options) layout = pick_layout(options)
response.layout = layout.path_without_format_and_extension if layout response.layout = layout.path_without_format_and_extension if layout
logger.info("Rendering template within #{layout.path_without_format_and_extension}") if logger && layout logger.info("Rendering template within #{layout.path_without_format_and_extension}") if logger && layout
layout = layout.path_without_format_and_extension if layout


if content_type = options[:content_type] if content_type = options[:content_type]
response.content_type = content_type.to_s response.content_type = content_type.to_s
Expand Down Expand Up @@ -1101,7 +1103,6 @@ def redirect_to(options = {}, response_status = {}) #:doc:
end end


response.redirected_to = options response.redirected_to = options
logger.info("Redirected to #{options}") if logger && logger.info?


case options case options
# The scheme name consist of a letter followed by any combination of # The scheme name consist of a letter followed by any combination of
Expand All @@ -1124,6 +1125,7 @@ def redirect_to(options = {}, response_status = {}) #:doc:


def redirect_to_full_url(url, status) def redirect_to_full_url(url, status)
raise DoubleRenderError if performed? raise DoubleRenderError if performed?
logger.info("Redirected to #{url}") if logger && logger.info?
response.redirect(url, interpret_status(status)) response.redirect(url, interpret_status(status))
@performed_redirect = true @performed_redirect = true
end end
Expand All @@ -1133,6 +1135,11 @@ def redirect_to_full_url(url, status)
# request is considered stale and should be generated from scratch. Otherwise, # request is considered stale and should be generated from scratch. Otherwise,
# it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent. # it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent.
# #
# Parameters:
# * <tt>:etag</tt>
# * <tt>:last_modified</tt>
# * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
#
# Example: # Example:
# #
# def show # def show
Expand All @@ -1153,20 +1160,34 @@ def stale?(options)
# Sets the etag, last_modified, or both on the response and renders a # Sets the etag, last_modified, or both on the response and renders a
# "304 Not Modified" response if the request is already fresh. # "304 Not Modified" response if the request is already fresh.
# #
# Parameters:
# * <tt>:etag</tt>
# * <tt>:last_modified</tt>
# * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
#
# Example: # Example:
# #
# def show # def show
# @article = Article.find(params[:id]) # @article = Article.find(params[:id])
# fresh_when(:etag => @article, :last_modified => @article.created_at.utc) # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
# end # end
# #
# This will render the show template if the request isn't sending a matching etag or # This will render the show template if the request isn't sending a matching etag or
# If-Modified-Since header and just a "304 Not Modified" response if there's a match. # If-Modified-Since header and just a "304 Not Modified" response if there's a match.
#
def fresh_when(options) def fresh_when(options)
options.assert_valid_keys(:etag, :last_modified) options.assert_valid_keys(:etag, :last_modified, :public)


response.etag = options[:etag] if options[:etag] response.etag = options[:etag] if options[:etag]
response.last_modified = options[:last_modified] if options[:last_modified] response.last_modified = options[:last_modified] if options[:last_modified]

if options[:public]
cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
cache_control.delete("private")
cache_control.delete("no-cache")
cache_control << "public"
response.headers["Cache-Control"] = cache_control.join(', ')
end


if request.fresh?(response) if request.fresh?(response)
head :not_modified head :not_modified
Expand All @@ -1178,15 +1199,26 @@ def fresh_when(options)
# #
# Examples: # Examples:
# expires_in 20.minutes # expires_in 20.minutes
# expires_in 3.hours, :private => false # expires_in 3.hours, :public => true
# expires in 3.hours, 'max-stale' => 5.hours, :private => nil, :public => true # expires in 3.hours, 'max-stale' => 5.hours, :public => true
# #
# This method will overwrite an existing Cache-Control header. # This method will overwrite an existing Cache-Control header.
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
def expires_in(seconds, options = {}) #:doc: def expires_in(seconds, options = {}) #:doc:
cache_options = { 'max-age' => seconds, 'private' => true }.symbolize_keys.merge!(options.symbolize_keys) cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
cache_options.delete_if { |k,v| v.nil? or v == false }
cache_control = cache_options.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"} cache_control << "max-age=#{seconds}"
cache_control.delete("no-cache")
if options[:public]
cache_control.delete("private")
cache_control << "public"
else
cache_control << "private"
end

# This allows for additional headers to be passed through like 'max-stale' => 5.hours
cache_control += options.symbolize_keys.reject{|k,v| k == :public || k == :private }.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"}

response.headers["Cache-Control"] = cache_control.join(', ') response.headers["Cache-Control"] = cache_control.join(', ')
end end


Expand Down Expand Up @@ -1298,7 +1330,7 @@ def perform_action
rescue ActionView::MissingTemplate => e rescue ActionView::MissingTemplate => e
# Was the implicit template missing, or was it another template? # Was the implicit template missing, or was it another template?
if e.path == default_template_name if e.path == default_template_name
raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence}", caller raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence(:locale => :en)}", caller
else else
raise e raise e
end end
Expand Down
7 changes: 0 additions & 7 deletions actionpack/lib/action_controller/dispatcher.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def define_dispatcher_callbacks(cache_classes)
end end


if defined?(ActiveRecord) if defined?(ActiveRecord)
after_dispatch :checkin_connections
to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
end end


Expand Down Expand Up @@ -115,11 +114,5 @@ def _call(env)
def flush_logger def flush_logger
Base.logger.flush Base.logger.flush
end end

def checkin_connections
# Don't return connection (and peform implicit rollback) if this request is a part of integration test
return if @env.key?("rack.test")
ActiveRecord::Base.clear_active_connections!
end
end end
end end
25 changes: 16 additions & 9 deletions actionpack/lib/action_controller/layout.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def normalize_conditions(conditions)
# is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method # is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return # object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard. # weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
def active_layout(passed_layout = nil) def active_layout(passed_layout = nil, options = {})
layout = passed_layout || default_layout layout = passed_layout || default_layout
return layout if layout.respond_to?(:render) return layout if layout.respond_to?(:render)


Expand All @@ -207,21 +207,23 @@ def active_layout(passed_layout = nil)
when Proc then layout.call(self) when Proc then layout.call(self)
else layout else layout
end end

find_layout(active_layout, @template.template_format) if active_layout find_layout(active_layout, default_template_format, options[:html_fallback]) if active_layout
end end


private private
def default_layout #:nodoc: def default_layout #:nodoc:
layout = self.class.read_inheritable_attribute(:layout) unless default_template_format == :js layout = self.class.read_inheritable_attribute(:layout)
return layout unless self.class.read_inheritable_attribute(:auto_layout) return layout unless self.class.read_inheritable_attribute(:auto_layout)
find_layout(layout, default_template_format) find_layout(layout, default_template_format)
rescue ActionView::MissingTemplate rescue ActionView::MissingTemplate
nil nil
end end


def find_layout(layout, *formats) #:nodoc: def find_layout(layout, format, html_fallback=false) #:nodoc:
view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", *formats) view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", format, html_fallback)
rescue ActionView::MissingTemplate
raise if Mime::Type.lookup_by_extension(format.to_s).html?
end end


def pick_layout(options) def pick_layout(options)
Expand All @@ -232,7 +234,7 @@ def pick_layout(options)
when NilClass, TrueClass when NilClass, TrueClass
active_layout if action_has_layout? && candidate_for_layout?(:template => default_template_name) active_layout if action_has_layout? && candidate_for_layout?(:template => default_template_name)
else else
active_layout(layout) active_layout(layout, :html_fallback => true)
end end
else else
active_layout if action_has_layout? && candidate_for_layout?(options) active_layout if action_has_layout? && candidate_for_layout?(options)
Expand All @@ -258,7 +260,12 @@ def candidate_for_layout?(options)
template = options[:template] || default_template(options[:action]) template = options[:template] || default_template(options[:action])
if options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty? if options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty?
begin begin
!self.view_paths.find_template(template, default_template_format).exempt_from_layout? template_object = self.view_paths.find_template(template, default_template_format)
# this restores the behavior from 2.2.2, where response.template.template_format was reset
# to :html for :js requests with a matching html template.
# see v2.2.2, ActionView::Base, lines 328-330
@real_format = :html if response.template.template_format == :js && template_object.format == "html"
!template_object.exempt_from_layout?
rescue ActionView::MissingTemplate rescue ActionView::MissingTemplate
true true
end end
Expand All @@ -268,7 +275,7 @@ def candidate_for_layout?(options)
end end


def default_template_format def default_template_format
response.template.template_format @real_format || response.template.template_format
end end
end end
end end
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/request.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def key?(key)
# <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS # <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS
# constant above, an UnknownHttpMethod exception is raised. # constant above, an UnknownHttpMethod exception is raised.
def request_method def request_method
@request_method ||= HTTP_METHOD_LOOKUP[super] || raise(UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence}") @request_method ||= HTTP_METHOD_LOOKUP[super] || raise(UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
end end


# Returns the HTTP request \method used for action processing as a # Returns the HTTP request \method used for action processing as a
Expand Down
11 changes: 8 additions & 3 deletions actionpack/lib/action_controller/resources.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def new_path
end end


def shallow_path_prefix def shallow_path_prefix
@shallow_path_prefix ||= "#{path_prefix unless @options[:shallow]}" @shallow_path_prefix ||= @options[:shallow] ? @options[:namespace].try(:sub, /\/$/, '') : path_prefix
end end


def member_path def member_path
Expand All @@ -103,7 +103,7 @@ def nesting_path_prefix
end end


def shallow_name_prefix def shallow_name_prefix
@shallow_name_prefix ||= "#{name_prefix unless @options[:shallow]}" @shallow_name_prefix ||= @options[:shallow] ? @options[:namespace].try(:gsub, /\//, '_') : name_prefix
end end


def nesting_name_prefix def nesting_name_prefix
Expand Down Expand Up @@ -670,7 +670,12 @@ def action_options_for(action, resource, method = nil)
when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id)) when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id))
when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id)) when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id))
when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id)) when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id))
else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements) else
if method.nil? || resource.member_methods.nil? || resource.member_methods[method.to_sym].nil?
default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements)
else
resource.member_methods[method.to_sym].include?(action) ? default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(require_id)) : default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements)
end
end end
end end
end end
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/routing.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ module ActionController
module Routing module Routing
SEPARATORS = %w( / . ? ) SEPARATORS = %w( / . ? )


HTTP_METHODS = [:get, :head, :post, :put, :delete] HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]


ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set


Expand Down
Loading

0 comments on commit f1e903a

Please sign in to comment.