From b35562f432d0807517a614a540026c2fc557e2ac Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Tue, 24 Feb 2009 10:38:07 -0600 Subject: correctly handle layouts for AJAX requests and regular js files [#2052 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_controller/layout.rb | 21 ++++++++++++++------- actionpack/lib/action_view/paths.rb | 6 +++--- actionpack/test/controller/render_test.rb | 9 +++++---- actionpack/test/fixtures/layouts/xhr.html.erb | 2 ++ 4 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 actionpack/test/fixtures/layouts/xhr.html.erb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index a0db7acf72..ccd9605562 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -207,21 +207,23 @@ module ActionController #:nodoc: when Proc then layout.call(self) else layout end - - find_layout(active_layout, @template.template_format) if active_layout + + find_layout(active_layout, default_template_format) if active_layout end private 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) find_layout(layout, default_template_format) rescue ActionView::MissingTemplate nil end - def find_layout(layout, *formats) #:nodoc: - view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", *formats) + def find_layout(layout, format) #:nodoc: + view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", format, false) + rescue ActionView::MissingTemplate + raise if Mime::Type.lookup_by_extension(format.to_s).html? end def pick_layout(options) @@ -258,7 +260,12 @@ module ActionController #:nodoc: template = options[:template] || default_template(options[:action]) if options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty? 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 true end @@ -268,7 +275,7 @@ module ActionController #:nodoc: end def default_template_format - response.template.template_format + @real_format || response.template.template_format end end end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 41f9f486e5..37d96b2f82 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -40,7 +40,7 @@ module ActionView #:nodoc: each(&:load!) end - def find_template(original_template_path, format = nil) + def find_template(original_template_path, format = nil, html_fallback = true) return original_template_path if original_template_path.respond_to?(:render) template_path = original_template_path.sub(/^\//, '') @@ -54,9 +54,9 @@ module ActionView #:nodoc: elsif template = load_path[template_path] return template # Try to find html version if the format is javascript - elsif format == :js && template = load_path["#{template_path}.#{I18n.locale}.html"] + elsif format == :js && html_fallback && template = load_path["#{template_path}.#{I18n.locale}.html"] return template - elsif format == :js && template = load_path["#{template_path}.html"] + elsif format == :js && html_fallback && template = load_path["#{template_path}.html"] return template end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e131a735a9..70e5e62c93 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -684,12 +684,13 @@ class TestController < ActionController::Base "render_with_explicit_string_template", "render_js_with_explicit_template", "render_js_with_explicit_action_template", - "delete_with_js", "update_page", "update_page_with_instance_variables", - "render_implicit_js_template_without_layout" + "delete_with_js", "update_page", "update_page_with_instance_variables" "layouts/standard" when "action_talk_to_layout", "layout_overriding_layout" "layouts/talk_from_action" + when "render_implicit_html_template_from_xhr_request" + (request.xhr? ? 'layouts/xhr' : 'layouts/standard') end end end @@ -1018,8 +1019,8 @@ class RenderTest < ActionController::TestCase end def test_should_implicitly_render_html_template_from_xhr_request - get :render_implicit_html_template_from_xhr_request, :format => :js - assert_equal "Hello HTML!", @response.body + xhr :get, :render_implicit_html_template_from_xhr_request + assert_equal "XHR!\nHello HTML!", @response.body end def test_should_implicitly_render_js_template_without_layout diff --git a/actionpack/test/fixtures/layouts/xhr.html.erb b/actionpack/test/fixtures/layouts/xhr.html.erb new file mode 100644 index 0000000000..85285324ec --- /dev/null +++ b/actionpack/test/fixtures/layouts/xhr.html.erb @@ -0,0 +1,2 @@ +XHR! +<%= yield %> \ No newline at end of file -- cgit v1.2.3 From 85df4841ddb3db3970fa9e798de698cf6f16752a Mon Sep 17 00:00:00 2001 From: thedarkone Date: Tue, 24 Feb 2009 10:41:45 -0600 Subject: Template without a known template handler should only be reachable through its exact path. [#2027 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_view/template.rb | 23 +++++++++++++++-------- actionpack/test/template/render_test.rb | 10 ++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index ea838b9b02..0dd3a7e619 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -103,12 +103,12 @@ module ActionView #:nodoc: @@exempt_from_layout.merge(regexps) end - attr_accessor :filename, :load_path, :base_path + attr_accessor :template_path, :filename, :load_path, :base_path attr_accessor :locale, :name, :format, :extension delegate :to_s, :to => :path def initialize(template_path, load_path) - template_path = template_path.dup + @template_path = template_path.dup @load_path, @filename = load_path, File.join(load_path, template_path) @base_path, @name, @locale, @format, @extension = split(template_path) @base_path.to_s.gsub!(/\/$/, '') # Push to split method @@ -119,13 +119,20 @@ module ActionView #:nodoc: def accessible_paths paths = [] - paths << path - paths << path_without_extension - if multipart? - formats = format.split(".") - paths << "#{path_without_format_and_extension}.#{formats.first}" - paths << "#{path_without_format_and_extension}.#{formats.second}" + + if valid_extension?(extension) + paths << path + paths << path_without_extension + if multipart? + formats = format.split(".") + paths << "#{path_without_format_and_extension}.#{formats.first}" + paths << "#{path_without_format_and_extension}.#{formats.second}" + end + else + # template without explicit template handler should only be reachable through its exact path + paths << template_path end + paths end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 107c625e32..de7fa3de65 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -224,6 +224,16 @@ module RenderTestCases assert_equal 'source: Hello, <%= name %>!; locals: {:name=>"Josh"}', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo) end + def test_render_ignores_templates_with_malformed_template_handlers + %w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name| + assert_raise(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") } + end + end + + def test_template_with_malformed_template_handler_is_reachable_trough_its_exact_filename + assert_equal "Don't render me!", @view.render(:file => 'test/malformed/malformed.html.erb~') + end + def test_render_with_layout assert_equal %(\nHello world!\n), @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield") -- cgit v1.2.3 From 1b22071b276a2a2b3e65e6db40c6a0aa92d9ebc3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 24 Feb 2009 11:34:32 -0600 Subject: Ensure ActiveRecord session store's connections are checked in after each request [#1927 state:resolved] --- actionpack/lib/action_controller/dispatcher.rb | 7 ------- 1 file changed, 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb index ec40b5c4e6..07931e4a4a 100644 --- a/actionpack/lib/action_controller/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatcher.rb @@ -13,7 +13,6 @@ module ActionController end if defined?(ActiveRecord) - after_dispatch :checkin_connections to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } end @@ -115,11 +114,5 @@ module ActionController def flush_logger Base.logger.flush 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 -- cgit v1.2.3 From 92a30b0c88384feafc0da2864c01ff5c3a6f25ff Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 24 Feb 2009 11:36:58 -0600 Subject: missed template fixtures with ~ --- actionpack/test/fixtures/test/malformed/malformed.en.html.erb~ | 1 + actionpack/test/fixtures/test/malformed/malformed.erb~ | 1 + actionpack/test/fixtures/test/malformed/malformed.html.erb~ | 1 + 3 files changed, 3 insertions(+) create mode 100644 actionpack/test/fixtures/test/malformed/malformed.en.html.erb~ create mode 100644 actionpack/test/fixtures/test/malformed/malformed.erb~ create mode 100644 actionpack/test/fixtures/test/malformed/malformed.html.erb~ (limited to 'actionpack') diff --git a/actionpack/test/fixtures/test/malformed/malformed.en.html.erb~ b/actionpack/test/fixtures/test/malformed/malformed.en.html.erb~ new file mode 100644 index 0000000000..d009950384 --- /dev/null +++ b/actionpack/test/fixtures/test/malformed/malformed.en.html.erb~ @@ -0,0 +1 @@ +Don't render me! \ No newline at end of file diff --git a/actionpack/test/fixtures/test/malformed/malformed.erb~ b/actionpack/test/fixtures/test/malformed/malformed.erb~ new file mode 100644 index 0000000000..d009950384 --- /dev/null +++ b/actionpack/test/fixtures/test/malformed/malformed.erb~ @@ -0,0 +1 @@ +Don't render me! \ No newline at end of file diff --git a/actionpack/test/fixtures/test/malformed/malformed.html.erb~ b/actionpack/test/fixtures/test/malformed/malformed.html.erb~ new file mode 100644 index 0000000000..d009950384 --- /dev/null +++ b/actionpack/test/fixtures/test/malformed/malformed.html.erb~ @@ -0,0 +1 @@ +Don't render me! \ No newline at end of file -- cgit v1.2.3 From 0a8c003b1e0459b5bcfa47f49cc74f7a6b3851f8 Mon Sep 17 00:00:00 2001 From: Sam Granieri Date: Sun, 22 Feb 2009 21:24:53 -0600 Subject: Ruby 1.9 compat: silence a warning about regexp languages [#2050 state:committed] Signed-off-by: Jeremy Kemper --- actionpack/lib/action_controller/routing/segments.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb index 129e87c139..cbb1a9c09a 100644 --- a/actionpack/lib/action_controller/routing/segments.rb +++ b/actionpack/lib/action_controller/routing/segments.rb @@ -3,7 +3,11 @@ module ActionController class Segment #:nodoc: RESERVED_PCHAR = ':@&=+$,;' SAFE_PCHAR = "#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}" - UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze + if RUBY_VERSION >= '1.9' + UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false).freeze + else + UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze + end # TODO: Convert :is_optional accessor to read only attr_accessor :is_optional -- cgit v1.2.3 From 3d1d422b8be027417cb640416d154171e75f03d1 Mon Sep 17 00:00:00 2001 From: Eloy Duran Date: Thu, 26 Feb 2009 12:26:17 +0100 Subject: Pass a custom form builder on to nested fields_for calls. [#2023 status:committed] Signed-off-by: David Heinemeier Hansson --- actionpack/CHANGELOG | 2 + actionpack/lib/action_view/helpers/form_helper.rb | 132 ++++++++++++++-------- actionpack/test/template/form_helper_test.rb | 41 +++++++ 3 files changed, 126 insertions(+), 49 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 546adeb61d..3038d2b60b 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Edge* +* Fixed that passing a custom form builder would be forwarded to nested fields_for calls #2023 [Eloy Duran/Nate Wiger] + * Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] * Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White] diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 4fef2b443e..a589bcba2a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -5,17 +5,24 @@ require 'action_view/helpers/form_tag_helper' module ActionView module Helpers - # Form helpers are designed to make working with models much easier compared to using just standard HTML - # elements by providing a set of methods for creating forms based on your models. This helper generates the HTML - # for forms, providing a method for each sort of input (e.g., text, password, select, and so on). When the form - # is submitted (i.e., when the user hits the submit button or form.submit is called via JavaScript), the form inputs will be bundled into the params object and passed back to the controller. + # Form helpers are designed to make working with models much easier + # compared to using just standard HTML elements by providing a set of + # methods for creating forms based on your models. This helper generates + # the HTML for forms, providing a method for each sort of input + # (e.g., text, password, select, and so on). When the form is submitted + # (i.e., when the user hits the submit button or form.submit is + # called via JavaScript), the form inputs will be bundled into the + # params object and passed back to the controller. # - # There are two types of form helpers: those that specifically work with model attributes and those that don't. - # This helper deals with those that work with model attributes; to see an example of form helpers that don't work - # with model attributes, check the ActionView::Helpers::FormTagHelper documentation. + # There are two types of form helpers: those that specifically work with + # model attributes and those that don't. This helper deals with those that + # work with model attributes; to see an example of form helpers that don't + # work with model attributes, check the ActionView::Helpers::FormTagHelper + # documentation. # - # The core method of this helper, form_for, gives you the ability to create a form for a model instance; - # for example, let's say that you have a model Person and want to create a new instance of it: + # The core method of this helper, form_for, gives you the ability to create + # a form for a model instance; for example, let's say that you have a model + # Person and want to create a new instance of it: # # # Note: a @person variable will have been created in the controller. # # For example: @person = Person.new @@ -40,17 +47,22 @@ module ActionView # <%= submit_tag 'Create' %> # <% end %> # - # This example will render the people/_form partial, setting a local variable called form which references the yielded FormBuilder. - # - # The params object created when this form is submitted would look like: + # This example will render the people/_form partial, setting a + # local variable called form which references the yielded + # FormBuilder. The params object created when this form is + # submitted would look like: # # {"action"=>"create", "controller"=>"persons", "person"=>{"first_name"=>"William", "last_name"=>"Smith"}} # - # The params hash has a nested person value, which can therefore be accessed with params[:person] in the controller. - # If were editing/updating an instance (e.g., Person.find(1) rather than Person.new in the controller), the objects - # attribute values are filled into the form (e.g., the person_first_name field would have that person's first name in it). + # The params hash has a nested person value, which can therefore + # be accessed with params[:person] in the controller. If were + # editing/updating an instance (e.g., Person.find(1) rather than + # Person.new in the controller), the objects attribute values are + # filled into the form (e.g., the person_first_name field would + # have that person's first name in it). # - # If the object name contains square brackets the id for the object will be inserted. For example: + # If the object name contains square brackets the id for the object will be + # inserted. For example: # # <%= text_field "person[]", "name" %> # @@ -58,8 +70,10 @@ module ActionView # # # - # If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial - # used by render_collection_of_partials, the index option may come in handy. Example: + # If the helper is being used to generate a repetitive sequence of similar + # form elements, for example in a partial used by + # render_collection_of_partials, the index option may + # come in handy. Example: # # <%= text_field "person", "name", "index" => 1 %> # @@ -67,14 +81,17 @@ module ActionView # # # - # An index option may also be passed to form_for and fields_for. This automatically applies - # the index to all the nested fields. + # An index option may also be passed to form_for and + # fields_for. This automatically applies the index to + # all the nested fields. # - # 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 + # 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 module FormHelper - # Creates a form and a scope around a specific model object that is used as - # a base for questioning about values for the fields. + # Creates a form and a scope around a specific model object that is used + # as a base for questioning about values for the fields. # # Rails provides succinct resource-oriented form generation with +form_for+ # like this: @@ -86,13 +103,15 @@ module ActionView # <%= f.text_field :author %>
# <% end %> # - # There, +form_for+ is able to generate the rest of RESTful form parameters - # based on introspection on the record, but to understand what it does we - # need to dig first into the alternative generic usage it is based upon. + # There, +form_for+ is able to generate the rest of RESTful form + # parameters based on introspection on the record, but to understand what + # it does we need to dig first into the alternative generic usage it is + # based upon. # # === Generic form_for # - # The generic way to call +form_for+ yields a form builder around a model: + # The generic way to call +form_for+ yields a form builder around a + # model: # # <% form_for :person, :url => { :action => "update" } do |f| %> # <%= f.error_messages %> @@ -103,8 +122,8 @@ module ActionView # <% 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. + # 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 @@ -137,17 +156,18 @@ module ActionView # In any of its variants, the rightmost argument to +form_for+ is an # optional hash of options: # - # * :url - 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. + # * :url - 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. # * :html - 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 <% %>, not <%= %>. + # Worth noting is that the +form_for+ tag is called in a ERb evaluation + # block, not an ERb output block. So that's <% %>, not + # <%= %>. # # 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: + # possible to use both the stand-alone FormHelper methods and methods + # from FormTagHelper. For example: # # <% form_for :person, @person, :url => { :action => "update" } do |f| %> # First name: <%= f.text_field :first_name %> @@ -156,16 +176,16 @@ module ActionView # Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %> # <% end %> # - # This also works for the methods in FormOptionHelper and DateHelper that are - # designed to work with an object as base, like FormOptionHelper#collection_select - # and DateHelper#datetime_select. + # This also works for the methods in FormOptionHelper and DateHelper that + # are designed to work with an object as base, like + # FormOptionHelper#collection_select and DateHelper#datetime_select. # # === Resource-oriented style # - # 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. + # 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 @post is an existing record you want to edit # @@ -205,8 +225,10 @@ module ActionView # # === Customized form builders # - # You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, - # then use your custom builder. For example, let's say you made a helper to automatically add labels to form inputs. + # You can also build forms using a customized FormBuilder class. Subclass + # FormBuilder and override or define some more helpers, then use your + # custom builder. For example, let's say you made a helper to + # automatically add labels to form inputs. # # <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %> # <%= f.text_field :first_name %> @@ -219,16 +241,23 @@ module ActionView # # <%= render :partial => f %> # - # The rendered template is people/_labelling_form and the local variable referencing the form builder is called labelling_form. + # The rendered template is people/_labelling_form and the local + # variable referencing the form builder is called + # labelling_form. + # + # The custom FormBuilder class is automatically merged with the options + # of a nested fields_for call, unless it's explicitely set. # - # In many cases you will want to wrap the above in another helper, so you could do something like the following: + # In many cases you will want to wrap the above in another helper, so you + # could do something like the following: # # def labelled_form_for(record_or_name_or_array, *args, &proc) # options = args.extract_options! # form_for(record_or_name_or_array, *(args << options.merge(:builder => LabellingFormBuilder)), &proc) # end # - # If you don't need to attach a form to a model instance, then check out FormTagHelper#form_tag. + # If you don't need to attach a form to a model instance, then check out + # FormTagHelper#form_tag. def form_for(record_or_name_or_array, *args, &proc) raise ArgumentError, "Missing block" unless block_given? @@ -910,6 +939,11 @@ module ActionView index = "" end + if options[:builder] + args << {} unless args.last.is_a?(Hash) + args.last[:builder] ||= options[:builder] + end + case record_or_name_or_array when String, Symbol if nested_attributes_association?(record_or_name_or_array) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 5cc81b4afb..654eee40a3 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -1001,6 +1001,47 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_labelled_builder_with_nested_fields_for_without_options_hash + klass = nil + + form_for(:post, @post, :builder => LabelledFormBuilder) do |f| + f.fields_for(:comments, Comment.new) do |nested_fields| + klass = nested_fields.class + '' + end + end + + assert_equal LabelledFormBuilder, klass + end + + def test_form_for_with_labelled_builder_with_nested_fields_for_with_options_hash + klass = nil + + form_for(:post, @post, :builder => LabelledFormBuilder) do |f| + f.fields_for(:comments, Comment.new, :index => 'foo') do |nested_fields| + klass = nested_fields.class + '' + end + end + + assert_equal LabelledFormBuilder, klass + end + + class LabelledFormBuilderSubclass < LabelledFormBuilder; end + + def test_form_for_with_labelled_builder_with_nested_fields_for_with_custom_builder + klass = nil + + form_for(:post, @post, :builder => LabelledFormBuilder) do |f| + f.fields_for(:comments, Comment.new, :builder => LabelledFormBuilderSubclass) do |nested_fields| + klass = nested_fields.class + '' + end + end + + assert_equal LabelledFormBuilderSubclass, klass + end + def test_form_for_with_html_options_adds_options_to_form_tag form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end expected = "
" -- cgit v1.2.3 From 6de83562f91028629bd24447aa521bc72ef8277a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 27 Feb 2009 14:22:39 +0100 Subject: Force all internal calls to Array#to_sentence to use English [#2010 state:resolved] --- actionpack/lib/action_controller/base.rb | 4 ++-- actionpack/lib/action_controller/request.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 1eda6e3f04..5df94b289a 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -22,7 +22,7 @@ module ActionController #:nodoc: attr_reader :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 end @@ -1298,7 +1298,7 @@ module ActionController #:nodoc: rescue ActionView::MissingTemplate => e # Was the implicit template missing, or was it another template? 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 raise e end diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 0e95cfc147..2cabab9ec8 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -32,7 +32,7 @@ module ActionController # :get. If the request \method is not listed in the HTTP_METHODS # constant above, an UnknownHttpMethod exception is raised. 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 # Returns the HTTP request \method used for action processing as a -- cgit v1.2.3 From 77b0994c7835610982d708ce7ce5cd95e6e99e5a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 27 Feb 2009 14:46:23 +0100 Subject: Prep for RC2 later today --- actionpack/CHANGELOG | 2 +- actionpack/Rakefile | 2 +- actionpack/lib/action_pack/version.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 3038d2b60b..516f281428 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,4 +1,4 @@ -*Edge* +*2.3.1 [RC2] (February 27th, 2009)* * Fixed that passing a custom form builder would be forwarded to nested fields_for calls #2023 [Eloy Duran/Nate Wiger] diff --git a/actionpack/Rakefile b/actionpack/Rakefile index c389e5a8d6..0d673c617d 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -80,7 +80,7 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true 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.require_path = 'lib' diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index f20e44a7d5..f03a2a7605 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -2,7 +2,7 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 0 + TINY = 1 STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 7058c1366ee33f3095b8737c2b71876702cddea6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 28 Feb 2009 10:30:49 +0100 Subject: So it didnt happen yesterday, but very soon! Just need the final details ironed out --- actionpack/CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 516f281428..4520ea24cf 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,4 +1,4 @@ -*2.3.1 [RC2] (February 27th, 2009)* +*2.3.1 [RC2] (February ?, 2009)* * Fixed that passing a custom form builder would be forwarded to nested fields_for calls #2023 [Eloy Duran/Nate Wiger] -- cgit v1.2.3 From f2a32bd0dedf11021027e36cc2c99f97434cae17 Mon Sep 17 00:00:00 2001 From: Gregg Pollack Date: Fri, 27 Feb 2009 13:24:52 -0500 Subject: Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable [#2095 state:committed] Signed-off-by: David Heinemeier Hansson --- actionpack/CHANGELOG | 2 + actionpack/lib/action_controller/base.rb | 42 +++++++++++++++--- actionpack/test/controller/render_test.rb | 72 +++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 4520ea24cf..809e90ffc7 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *2.3.1 [RC2] (February ?, 2009)* +* 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] * Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 5df94b289a..564fdf677e 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1133,6 +1133,11 @@ module ActionController #:nodoc: # 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. # + # Parameters: + # * :etag + # * :last_modified + # * :public 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: # # def show @@ -1153,20 +1158,34 @@ module ActionController #:nodoc: # Sets the etag, last_modified, or both on the response and renders a # "304 Not Modified" response if the request is already fresh. # + # Parameters: + # * :etag + # * :last_modified + # * :public 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: # # def show # @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 # # 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. + # 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.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) head :not_modified @@ -1178,15 +1197,24 @@ module ActionController #:nodoc: # # Examples: # expires_in 20.minutes - # expires_in 3.hours, :private => false - # expires in 3.hours, 'max-stale' => 5.hours, :private => nil, :public => true + # expires_in 3.hours, :public => true + # expires in 3.hours, 'max-stale' => 5.hours, :public => true # # This method will overwrite an existing Cache-Control header. # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. def expires_in(seconds, options = {}) #:doc: - cache_options = { 'max-age' => seconds, 'private' => true }.symbolize_keys.merge!(options.symbolize_keys) - 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 = response.headers["Cache-Control"].split(",").map {|k| k.strip } + + cache_control << "max-age=#{seconds}" + if options[:public] + cache_control.delete("private") + cache_control.delete("no-cache") + cache_control << "public" + 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(', ') end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 70e5e62c93..02ae8ac942 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -36,6 +36,39 @@ class TestController < ActionController::Base render :action => 'hello_world' end end + + def conditional_hello_with_public_header + if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) + render :action => 'hello_world' + end + end + + def conditional_hello_with_public_header_and_expires_at + expires_in 1.minute + if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) + render :action => 'hello_world' + end + end + + def conditional_hello_with_expires_in + expires_in 1.minute + render :action => 'hello_world' + end + + def conditional_hello_with_expires_in_with_public + expires_in 1.minute, :public => true + render :action => 'hello_world' + end + + def conditional_hello_with_expires_in_with_public_with_more_keys + expires_in 1.minute, :public => true, 'max-stale' => 5.hours + render :action => 'hello_world' + end + + def conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax + expires_in 1.minute, :public => true, :private => nil, 'max-stale' => 5.hours + render :action => 'hello_world' + end def conditional_hello_with_bangs render :action => 'hello_world' @@ -1464,6 +1497,35 @@ class RenderTest < ActionController::TestCase end end +class ExpiresInRenderTest < ActionController::TestCase + tests TestController + + def setup + @request.host = "www.nextangle.com" + end + + def test_expires_in_header + get :conditional_hello_with_expires_in + assert_equal "max-age=60, private", @response.headers["Cache-Control"] + end + + def test_expires_in_header + get :conditional_hello_with_expires_in_with_public + assert_equal "max-age=60, public", @response.headers["Cache-Control"] + end + + def test_expires_in_header_with_additional_headers + get :conditional_hello_with_expires_in_with_public_with_more_keys + assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + end + + def test_expires_in_old_syntax + get :conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax + assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + end +end + + class EtagRenderTest < ActionController::TestCase tests TestController @@ -1553,6 +1615,16 @@ class EtagRenderTest < ActionController::TestCase get :conditional_hello_with_bangs assert_response :not_modified end + + def test_etag_with_public_true_should_set_header + get :conditional_hello_with_public_header + assert_equal "public", @response.headers['Cache-Control'] + end + + def test_etag_with_public_true_should_set_header_and_retain_other_headers + get :conditional_hello_with_public_header_and_expires_at + assert_equal "max-age=60, public", @response.headers['Cache-Control'] + end protected def etag_for(text) -- cgit v1.2.3 From dcd9c7f58e7194c026145273c7695cf968569d33 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Sat, 28 Feb 2009 09:21:56 -0600 Subject: Fix spelling in test name. Signed-off-by: Pratik Naik --- actionpack/test/template/render_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index de7fa3de65..b042eb3d9b 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -230,7 +230,7 @@ module RenderTestCases end end - def test_template_with_malformed_template_handler_is_reachable_trough_its_exact_filename + def test_template_with_malformed_template_handler_is_reachable_through_its_exact_filename assert_equal "Don't render me!", @view.render(:file => 'test/malformed/malformed.html.erb~') end -- cgit v1.2.3 From 8607740a29d0f9ceb2ca21c9ef714f74b64d4a88 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 28 Feb 2009 17:42:15 +0000 Subject: Ensure the old behaviour is retained when action_view.cache_template_loading is not set explicitly --- actionpack/lib/action_view/base.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 65b2062337..c373afeac0 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -183,12 +183,12 @@ module ActionView #:nodoc: cattr_accessor :debug_rjs # Specify whether templates should be cached. Otherwise the file we be read everytime it is accessed. - # Automaticaly reloading templates are not thread safe and should only be used in development mode. - @@cache_template_loading = false + # Automatically reloading templates are not thread safe and should only be used in development mode. + @@cache_template_loading = nil cattr_accessor :cache_template_loading def self.cache_template_loading? - ActionController::Base.allow_concurrency || cache_template_loading + ActionController::Base.allow_concurrency || cache_template_loading || !ActiveSupport::Dependencies.load? end attr_internal :request -- cgit v1.2.3 From 5029210914059faa65358b98a9c033a40e803c54 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 28 Feb 2009 19:03:41 +0000 Subject: Use Array.wrap() instead of Array() and handle action_view.cache_template_loading being false --- actionpack/lib/action_view/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index c373afeac0..fe6053e574 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -188,7 +188,7 @@ module ActionView #:nodoc: cattr_accessor :cache_template_loading def self.cache_template_loading? - ActionController::Base.allow_concurrency || cache_template_loading || !ActiveSupport::Dependencies.load? + ActionController::Base.allow_concurrency || (cache_template_loading.nil? ? !ActiveSupport::Dependencies.load? : cache_template_loading) end attr_internal :request -- cgit v1.2.3 From 9b1b88f09cf1498f04e1cd469d0d5ffccf2b93cc Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 3 Mar 2009 13:07:03 -0600 Subject: Fixed reset_session for ActiveRecord session store [#2108 state:resolved] --- .../test/activerecord/active_record_store_test.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'actionpack') diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index 6a75e6050d..7998f9c22f 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -21,6 +21,11 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest render :text => "foo: #{session[:foo].inspect}" end + def call_reset_session + reset_session + head :ok + end + def rescue_action(e) raise end end @@ -61,6 +66,22 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest end end + def test_setting_session_value_after_session_reset + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + + get '/call_reset_session' + assert_response :success + assert_not_equal [], headers['Set-Cookie'] + + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body + end + end + def test_prevents_session_fixation with_test_route_set do get '/set_session_value' -- cgit v1.2.3 From ce56c5daa81d61a745b88220014a846a0eea46a4 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Tue, 3 Mar 2009 17:40:39 -0600 Subject: Allow routes with a trailing slash to be recognized Signed-off-by: Michael Koziarski [#2039 state:committed] --- actionpack/lib/action_controller/routing/segments.rb | 2 +- actionpack/test/controller/resources_test.rb | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb index cbb1a9c09a..358b4a6487 100644 --- a/actionpack/lib/action_controller/routing/segments.rb +++ b/actionpack/lib/action_controller/routing/segments.rb @@ -318,7 +318,7 @@ module ActionController end def regexp_chunk - '(\.[^/?\.]+)?' + '/|(\.[^/?\.]+)?' end def to_s diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index ae2639d245..c441cfd4cf 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -750,9 +750,17 @@ class ResourcesTest < ActionController::TestCase end def test_with_path_segment - with_restful_routing :messages, :as => 'reviews' do - assert_simply_restful_for :messages, :as => 'reviews' + with_restful_routing :messages do + assert_simply_restful_for :messages + assert_recognizes({:controller => "messages", :action => "index"}, "/messages") + assert_recognizes({:controller => "messages", :action => "index"}, "/messages/") end + + with_restful_routing :messages, :as => 'reviews' do + assert_simply_restful_for :messages, :as => 'reviews' + assert_recognizes({:controller => "messages", :action => "index"}, "/reviews") + assert_recognizes({:controller => "messages", :action => "index"}, "/reviews/") + end end def test_multiple_with_path_segment_and_controller -- cgit v1.2.3 From 638b3b15a13c4e274cfb317c40248e9feea3bfae Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 4 Mar 2009 14:37:59 -0600 Subject: Generating routes with optional format segment does not inherit params format [#2043 state:resolved] --- actionpack/lib/action_controller/routing/segments.rb | 6 +++++- actionpack/test/controller/routing_test.rb | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb index 358b4a6487..4f936d51d2 100644 --- a/actionpack/lib/action_controller/routing/segments.rb +++ b/actionpack/lib/action_controller/routing/segments.rb @@ -324,7 +324,11 @@ module ActionController def to_s '(.:format)?' end - + + def extract_value + "#{local_name} = options[:#{key}] && options[:#{key}].to_s.downcase" + end + #the value should not include the period (.) def match_extraction(next_capture) %[ diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 13ba0c30dd..01b3db64fc 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -2237,6 +2237,22 @@ class RouteSetTest < Test::Unit::TestCase ) end + def test_format_is_not_inherit + set.draw do |map| + map.connect '/posts.:format', :controller => 'posts' + end + + assert_equal '/posts', set.generate( + {:controller => 'posts'}, + {:controller => 'posts', :action => 'index', :format => 'xml'} + ) + + assert_equal '/posts.xml', set.generate( + {:controller => 'posts', :format => 'xml'}, + {:controller => 'posts', :action => 'index', :format => 'xml'} + ) + end + def test_expiry_determination_should_consider_values_with_to_param set.draw { |map| map.connect 'projects/:project_id/:controller/:action' } assert_equal '/projects/1/post/show', set.generate( -- cgit v1.2.3 From dfef3d8b14b5d3dcb61d83c30d5d5b27d33ff530 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 5 Mar 2009 11:00:04 +0100 Subject: Release RC2 today --- actionpack/CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 809e90ffc7..303a440c17 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,4 +1,4 @@ -*2.3.1 [RC2] (February ?, 2009)* +*2.3.1 [RC2] (March 5, 2009)* * Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable #2095 [Gregg Pollack] -- cgit v1.2.3 From b1c989f28dd1d619f0e3e3ca1b894b686e517f2f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 5 Mar 2009 12:22:49 +0100 Subject: Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #") [DHH] --- actionpack/CHANGELOG | 2 ++ actionpack/lib/action_controller/base.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 303a440c17..c4e4211c42 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *2.3.1 [RC2] (March 5, 2009)* +* Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #") [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] diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 564fdf677e..b769a2e67e 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1101,7 +1101,6 @@ module ActionController #:nodoc: end response.redirected_to = options - logger.info("Redirected to #{options}") if logger && logger.info? case options # The scheme name consist of a letter followed by any combination of @@ -1124,6 +1123,7 @@ module ActionController #:nodoc: def redirect_to_full_url(url, status) raise DoubleRenderError if performed? + logger.info("Redirected to #{url}") if logger && logger.info? response.redirect(url, interpret_status(status)) @performed_redirect = true end -- cgit v1.2.3 From 5b7527ca44521edf9782b3d7f449bf09a29267f2 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Thu, 5 Mar 2009 18:46:59 -0600 Subject: Failing test for routes with member & requirement [#2054 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_controller/resources.rb | 7 ++++++- actionpack/test/controller/resources_test.rb | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index 3af21967df..8195b38685 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -670,7 +670,12 @@ module ActionController 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 "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 diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index c441cfd4cf..fee41362c1 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -209,6 +209,14 @@ class ResourcesTest < ActionController::TestCase end end + def test_with_member_action_and_requirement + expected_options = {:controller => 'messages', :action => 'mark', :id => '1.1.1'} + + with_restful_routing(:messages, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}, :member => { :mark => :get }) do + assert_recognizes(expected_options, :path => 'messages/1.1.1/mark', :method => :get) + end + end + def test_member_when_override_paths_for_default_restful_actions_with [:put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method }, :path_names => {:new => 'nuevo'} do -- cgit v1.2.3 From 3191535ff0912e751dcf411c57923ec79b72944d Mon Sep 17 00:00:00 2001 From: thedarkone Date: Thu, 5 Mar 2009 18:49:22 -0600 Subject: Fix layouts with absolute paths [#2134 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_controller/base.rb | 1 - actionpack/test/controller/layout_test.rb | 12 +++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index b769a2e67e..5da47ce317 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -913,7 +913,6 @@ module ActionController #:nodoc: layout = pick_layout(options) response.layout = layout.path_without_format_and_extension if 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] response.content_type = content_type.to_s diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index 28555ee3d1..1575674e18 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -79,6 +79,10 @@ end class DefaultLayoutController < LayoutTest end +class AbsolutePathLayoutController < LayoutTest + layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test.rhtml') +end + class HasOwnLayoutController < LayoutTest layout 'item' end @@ -137,12 +141,18 @@ class LayoutSetInResponseTest < ActionController::TestCase ensure ActionController::Base.exempt_from_layout.delete(/\.rhtml$/) end - + def test_layout_is_picked_from_the_controller_instances_view_path @controller = PrependsViewPathController.new get :hello assert_equal 'layouts/alt', @response.layout end + + def test_absolute_pathed_layout + @controller = AbsolutePathLayoutController.new + get :hello + assert_equal "layout_test.rhtml hello.rhtml", @response.body.strip + end end class RenderWithTemplateOptionController < LayoutTest -- cgit v1.2.3 From cb40c761b2ac1c82e6fb0e777eb48426a9dfa055 Mon Sep 17 00:00:00 2001 From: Niels Ganser Date: Fri, 6 Mar 2009 13:45:26 +0100 Subject: Minor spelling fix --- actionpack/lib/action_controller/integration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb index 1c05ab0bf6..26b695570b 100644 --- a/actionpack/lib/action_controller/integration.rb +++ b/actionpack/lib/action_controller/integration.rb @@ -5,7 +5,7 @@ require 'active_support/test_case' module ActionController module Integration #:nodoc: # An integration Session instance represents a set of requests and responses - # performed sequentially by some virtual user. Becase you can instantiate + # performed sequentially by some virtual user. Because you can instantiate # multiple sessions and run them side-by-side, you can also mimic (to some # limited extent) multiple simultaneous users interacting with your system. # -- cgit v1.2.3 From 7fa0a8d7f38a42d2f41a3f4aefc129d7071b0258 Mon Sep 17 00:00:00 2001 From: Tekin Suleyman Date: Fri, 6 Mar 2009 16:46:06 +0000 Subject: Updated actionpack/CHANGELOG to include enhancements to form option helpers --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 546adeb61d..cc1cfe03ab 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Edge* +* Form option helpers now support disabled option tags and the use of lambdas for selecting/disabling option tags from collections #837 [Tekin] + * Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] * Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White] -- cgit v1.2.3 From c071123b3e2d6fd918dd7e419efe7429355445c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20S=C3=B8rensen?= Date: Fri, 6 Mar 2009 10:17:20 +0100 Subject: Ensure expires_in without a :public key sets the Cache-Control header to private. [#2095 state:resolved] This fixes a regression introduced in f2a32bd0, which wasn't exposed due to two test methods having the same name. Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/base.rb | 4 +++- actionpack/test/controller/render_test.rb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 5da47ce317..9d06d052b4 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1205,10 +1205,12 @@ module ActionController #:nodoc: cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip } cache_control << "max-age=#{seconds}" + cache_control.delete("no-cache") if options[:public] cache_control.delete("private") - cache_control.delete("no-cache") cache_control << "public" + else + cache_control << "private" end # This allows for additional headers to be passed through like 'max-stale' => 5.hours diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 02ae8ac942..2f4cc5a615 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -1509,7 +1509,7 @@ class ExpiresInRenderTest < ActionController::TestCase assert_equal "max-age=60, private", @response.headers["Cache-Control"] end - def test_expires_in_header + def test_expires_in_header_with_public get :conditional_hello_with_expires_in_with_public assert_equal "max-age=60, public", @response.headers["Cache-Control"] end -- cgit v1.2.3 From a0bb8bcb166a9d66c81fd68b8c128fb06d6c725d Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 7 Mar 2009 15:53:09 +0000 Subject: =?UTF-8?q?Remove=20unused=20variable=20[#1451=20state:resolved]?= =?UTF-8?q?=20[Rapha=C3=ABl=20Valyi]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- actionpack/lib/action_controller/routing/recognition_optimisation.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing/recognition_optimisation.rb b/actionpack/lib/action_controller/routing/recognition_optimisation.rb index ebc553512f..9bfebff0c0 100644 --- a/actionpack/lib/action_controller/routing/recognition_optimisation.rb +++ b/actionpack/lib/action_controller/routing/recognition_optimisation.rb @@ -98,7 +98,6 @@ module ActionController if Array === item i += 1 start = (i == 1) - final = (i == list.size) tag, sub = item if tag == :dynamic body += padding + "#{start ? 'if' : 'elsif'} true\n" -- cgit v1.2.3 From 272c2d2e9ca38a307878306bff4315183d1ae7ab Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 7 Mar 2009 16:13:34 +0000 Subject: Ensure assert_select works with XML namespaced attributes [#1547 state:resolved] [Jon Yurek] --- .../lib/action_controller/vendor/html-scanner/html/selector.rb | 2 +- actionpack/test/controller/assert_select_test.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/selector.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/selector.rb index 376bb87409..e2c49c284f 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner/html/selector.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner/html/selector.rb @@ -556,7 +556,7 @@ module HTML end # Attribute value. - next if statement.sub!(/^\[\s*([[:alpha:]][\w\-]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do |match| + next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do |match| name, equality, value = $1, $2, $3 if value == "?" value = values.shift diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index 99c57c0c91..c543118530 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -256,6 +256,11 @@ class AssertSelectTest < ActionController::TestCase assert_raises(Assertion) {assert_select_rjs :insert, :top, "test2"} end + def test_elect_with_xml_namespace_attributes + render_html %Q{} + assert_nothing_raised { assert_select "link[xlink:href=http://nowhere.com]" } + end + # # Test css_select. # -- cgit v1.2.3 From 45494580d9405e80ba124d17c8379436883c8c78 Mon Sep 17 00:00:00 2001 From: Dan Barry Date: Sat, 7 Mar 2009 18:55:12 +0000 Subject: =?UTF-8?q?Ensure=20Active=20Record=20error=20related=20view=20hel?= =?UTF-8?q?pers=20escape=20the=20message=20[#1280=20state:resolved]=20[Ing?= =?UTF-8?q?e=20J=C3=B8rgensen,=20Dan=20Barry]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pratik Naik --- .../action_view/helpers/active_record_helper.rb | 4 +-- .../test/template/active_record_helper_test.rb | 34 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 8b56d241ae..541899ea6a 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -121,7 +121,7 @@ module ActionView if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && (errors = obj.errors.on(method)) content_tag("div", - "#{options[:prepend_text]}#{errors.is_a?(Array) ? errors.first : errors}#{options[:append_text]}", + "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.is_a?(Array) ? errors.first : errors)}#{options[:append_text]}", :class => options[:css_class] ) else @@ -198,7 +198,7 @@ module ActionView locale.t :header, :count => count, :model => object_name end message = options.include?(:message) ? options[:message] : locale.t(:body) - error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }.join + error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, ERB::Util.html_escape(msg)) } }.join contents = '' contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank? diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb index e46f95d18b..83c028b5f2 100644 --- a/actionpack/test/template/active_record_helper_test.rb +++ b/actionpack/test/template/active_record_helper_test.rb @@ -19,6 +19,30 @@ class ActiveRecordHelperTest < ActionView::TestCase Column = Struct.new("Column", :type, :name, :human_name) end + class DirtyPost + class Errors + def empty? + false + end + + def count + 1 + end + + def full_messages + ["Author name can't be empty"] + end + + def on(field) + "can't be empty" + end + end + + def errors + Errors.new + end + end + def setup_post @post = Post.new def @post.errors @@ -195,10 +219,20 @@ class ActiveRecordHelperTest < ActionView::TestCase assert_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

  • Author name can't be empty
), error_messages_for("post", :class => "errorDeathByClass", :id => nil, :header_tag => "h1") end + def test_error_messages_for_escapes_html + @dirty_post = DirtyPost.new + assert_dom_equal %(

1 error prohibited this dirty post from being saved

There were problems with the following fields:

  • Author name can't be <em>empty</em>
), error_messages_for("dirty_post") + end + def test_error_messages_for_handles_nil assert_equal "", error_messages_for("notthere") end + def test_error_message_on_escapes_html + @dirty_post = DirtyPost.new + assert_dom_equal "
can't be <em>empty</em>
", error_message_on(:dirty_post, :author_name) + end + def test_error_message_on_handles_nil assert_equal "", error_message_on("notthere", "notthere") end -- cgit v1.2.3 From 77f7d98e38dddf72890c80b4e4b2e088bb76d111 Mon Sep 17 00:00:00 2001 From: Lawrence Pit Date: Sat, 7 Mar 2009 13:29:35 -0600 Subject: submit_tag with confirmation and disable_with [#660 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 4 ++-- actionpack/test/template/form_tag_helper_test.rb | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 4646bc118b..6d39a53adc 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -360,8 +360,8 @@ module ActionView end if confirm = options.delete("confirm") - options["onclick"] ||= '' - options["onclick"] << "return #{confirm_javascript_function(confirm)};" + options["onclick"] ||= 'return true;' + options["onclick"] = "if (!#{confirm_javascript_function(confirm)}) return false; #{options['onclick']}" end tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 0c8af60aa4..c713b8da8e 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -266,11 +266,18 @@ class FormTagHelperTest < ActionView::TestCase def test_submit_tag_with_confirmation assert_dom_equal( - %(), + %(), submit_tag("Save", :confirm => "Are you sure?") ) end - + + def test_submit_tag_with_confirmation_and_with_disable_with + assert_dom_equal( + %(), + submit_tag("Save", :disable_with => "Saving...", :confirm => "Are you sure?") + ) + end + def test_image_submit_tag_with_confirmation assert_dom_equal( %(), -- cgit v1.2.3 From 87e8b162463f13bd50d27398f020769460a770e3 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Sat, 7 Mar 2009 13:32:46 -0600 Subject: fix HTML fallback for explicit templates [#2052 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_controller/layout.rb | 10 +++++----- actionpack/test/controller/render_test.rb | 16 ++++++++++++++++ actionpack/test/fixtures/layouts/default_html.html.erb | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 actionpack/test/fixtures/layouts/default_html.html.erb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index ccd9605562..6ec0c1b304 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -198,7 +198,7 @@ module ActionController #:nodoc: # 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 layout "weblog/standard" will return # weblog/standard, but layout "standard" will return layouts/standard. - def active_layout(passed_layout = nil) + def active_layout(passed_layout = nil, options = {}) layout = passed_layout || default_layout return layout if layout.respond_to?(:render) @@ -208,7 +208,7 @@ module ActionController #:nodoc: else layout end - find_layout(active_layout, default_template_format) if active_layout + find_layout(active_layout, default_template_format, options[:html_fallback]) if active_layout end private @@ -220,8 +220,8 @@ module ActionController #:nodoc: nil end - def find_layout(layout, format) #:nodoc: - view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", format, false) + def find_layout(layout, format, html_fallback=false) #:nodoc: + 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 @@ -234,7 +234,7 @@ module ActionController #:nodoc: when NilClass, TrueClass active_layout if action_has_layout? && candidate_for_layout?(:template => default_template_name) else - active_layout(layout) + active_layout(layout, :html_fallback => true) end else active_layout if action_has_layout? && candidate_for_layout?(options) diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 2f4cc5a615..78a4e8ccbb 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -313,6 +313,10 @@ class TestController < ActionController::Base def render_implicit_js_template_without_layout end + def render_html_explicit_template_and_layout + render :template => 'test/render_implicit_html_template_from_xhr_request', :layout => 'layouts/default_html' + end + def formatted_html_erb end @@ -720,6 +724,8 @@ class TestController < ActionController::Base "delete_with_js", "update_page", "update_page_with_instance_variables" "layouts/standard" + when "render_implicit_js_template_without_layout" + "layouts/default_html" when "action_talk_to_layout", "layout_overriding_layout" "layouts/talk_from_action" when "render_implicit_html_template_from_xhr_request" @@ -817,6 +823,11 @@ class RenderTest < ActionController::TestCase assert_equal "hello world, I'm here!", @response.body end + def test_xhr_with_render_text_and_layout + xhr :get, :render_text_hello_world_with_layout + assert_equal "hello world, I'm here!", @response.body + end + def test_do_with_render_action_and_layout_false get :hello_world_with_layout_false assert_equal 'Hello world!', @response.body @@ -1056,6 +1067,11 @@ class RenderTest < ActionController::TestCase assert_equal "XHR!\nHello HTML!", @response.body end + def test_should_render_explicit_html_template_with_html_layout + xhr :get, :render_html_explicit_template_and_layout + assert_equal "Hello HTML!\n", @response.body + end + def test_should_implicitly_render_js_template_without_layout get :render_implicit_js_template_without_layout, :format => :js assert_no_match //, @response.body diff --git a/actionpack/test/fixtures/layouts/default_html.html.erb b/actionpack/test/fixtures/layouts/default_html.html.erb new file mode 100644 index 0000000000..edd719111c --- /dev/null +++ b/actionpack/test/fixtures/layouts/default_html.html.erb @@ -0,0 +1 @@ +<%= @content_for_layout %> -- cgit v1.2.3 From ea8488caef77cb8cf2031d344e74981ab6ea0e57 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 7 Mar 2009 14:05:18 -0600 Subject: Fixed simplified render with nested models [#2042 state:resolved] --- actionpack/lib/action_controller/base.rb | 3 +++ actionpack/test/controller/fake_models.rb | 8 ++++++++ actionpack/test/controller/render_test.rb | 18 ++++++++++++++++++ .../test/fixtures/quiz/questions/_question.html.erb | 1 + actionpack/test/template/render_test.rb | 4 ++++ 5 files changed, 34 insertions(+) create mode 100644 actionpack/test/fixtures/quiz/questions/_question.html.erb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 9d06d052b4..0facf7066d 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -907,6 +907,9 @@ module ActionController #:nodoc: extra_options[:template] = options end + options = extra_options + elsif !options.is_a?(Hash) + extra_options[:partial] = options options = extra_options end diff --git a/actionpack/test/controller/fake_models.rb b/actionpack/test/controller/fake_models.rb index 7420579ed8..0b30c79b10 100644 --- a/actionpack/test/controller/fake_models.rb +++ b/actionpack/test/controller/fake_models.rb @@ -9,3 +9,11 @@ end class GoodCustomer < Customer end + +module Quiz + class Question < Struct.new(:name, :id) + def to_param + id.to_s + end + end +end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 78a4e8ccbb..e0b3f64b76 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -682,6 +682,14 @@ class TestController < ActionController::Base render :partial => "hash_object", :object => {:first_name => "Sam"} end + def partial_with_nested_object + render :partial => "quiz/questions/question", :object => Quiz::Question.new("first") + end + + def partial_with_nested_object_shorthand + render Quiz::Question.new("first") + end + def partial_hash_collection render :partial => "hash_object", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ] end @@ -1479,6 +1487,16 @@ class RenderTest < ActionController::TestCase assert_equal "Sam\nmaS\n", @response.body end + def test_partial_with_nested_object + get :partial_with_nested_object + assert_equal "first", @response.body + end + + def test_partial_with_nested_object_shorthand + get :partial_with_nested_object_shorthand + assert_equal "first", @response.body + end + def test_hash_partial_collection get :partial_hash_collection assert_equal "Pratik\nkitarP\nAmy\nymA\n", @response.body diff --git a/actionpack/test/fixtures/quiz/questions/_question.html.erb b/actionpack/test/fixtures/quiz/questions/_question.html.erb new file mode 100644 index 0000000000..fb4dcfee64 --- /dev/null +++ b/actionpack/test/fixtures/quiz/questions/_question.html.erb @@ -0,0 +1 @@ +<%= question.name %> \ No newline at end of file diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index b042eb3d9b..9adf053b09 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -145,6 +145,10 @@ module RenderTestCases assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name end + def test_render_object + assert_equal "Hello: david", @view.render(:partial => "test/customer", :object => Customer.new("david")) + end + def test_render_partial_collection assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) end -- cgit v1.2.3 From 5c87e9adddc22703a3dbbb785e32fafe0e91ce78 Mon Sep 17 00:00:00 2001 From: Tom Stuart Date: Sat, 7 Mar 2009 22:50:58 +0000 Subject: Ensure shallow routes respects namespace [#1356 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/resources.rb | 4 ++-- actionpack/test/controller/resources_test.rb | 34 ++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index 8195b38685..0a89c4b3d5 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -91,7 +91,7 @@ module ActionController end def shallow_path_prefix - @shallow_path_prefix ||= "#{path_prefix unless @options[:shallow]}" + @shallow_path_prefix ||= @options[:shallow] ? @options[:namespace].try(:sub, /\/$/, '') : path_prefix end def member_path @@ -103,7 +103,7 @@ module ActionController end def shallow_name_prefix - @shallow_name_prefix ||= "#{name_prefix unless @options[:shallow]}" + @shallow_name_prefix ||= @options[:shallow] ? @options[:namespace].try(:gsub, /\//, '_') : name_prefix end def nesting_name_prefix diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index fee41362c1..17f6d99b21 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -414,6 +414,34 @@ class ResourcesTest < ActionController::TestCase end end + def test_shallow_nested_restful_routes_with_namespaces + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |map| + map.namespace :admin do |map| + map.resources :products, :shallow => true do |map| + map.resources :images + end + end + end + end + + assert_simply_restful_for :products, + :controller => 'backoffice/admin/products', + :namespace => 'backoffice/admin/', + :name_prefix => 'backoffice_admin_', + :path_prefix => 'backoffice/admin/', + :shallow => true + assert_simply_restful_for :images, + :controller => 'backoffice/admin/images', + :namespace => 'backoffice/admin/', + :name_prefix => 'backoffice_admin_product_', + :path_prefix => 'backoffice/admin/products/1/', + :shallow => true, + :options => { :product_id => '1' } + end + end + def test_restful_routes_dont_generate_duplicates with_restful_routing :messages do routes = ActionController::Routing::Routes.routes @@ -1082,7 +1110,7 @@ class ResourcesTest < ActionController::TestCase path = "#{options[:as] || controller_name}" collection_path = "/#{options[:path_prefix]}#{path}" - shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}" + shallow_path = "/#{options[:shallow] ? options[:namespace] : options[:path_prefix]}#{path}" member_path = "#{shallow_path}/1" new_path = "#{collection_path}/#{new_action}" edit_member_path = "#{member_path}/#{edit_action}" @@ -1146,10 +1174,10 @@ class ResourcesTest < ActionController::TestCase options[:options].delete :action path = "#{options[:as] || controller_name}" - shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}" + shallow_path = "/#{options[:shallow] ? options[:namespace] : options[:path_prefix]}#{path}" full_path = "/#{options[:path_prefix]}#{path}" name_prefix = options[:name_prefix] - shallow_prefix = "#{options[:name_prefix] unless options[:shallow]}" + shallow_prefix = options[:shallow] ? options[:namespace].try(:gsub, /\//, '_') : options[:name_prefix] new_action = "new" edit_action = "edit" -- cgit v1.2.3 From 5e0f6214d2421a4931c85ee6a239158c69e57b65 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Sun, 8 Mar 2009 07:31:27 -0500 Subject: Support OPTIONS verb in route conditions [#1727 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/routing.rb | 2 +- actionpack/test/controller/routing_test.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index a2141a77dc..c0eb61340b 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -267,7 +267,7 @@ module ActionController module Routing 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 diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 01b3db64fc..55f3ad23be 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1865,6 +1865,14 @@ class RouteSetTest < Test::Unit::TestCase end end + def test_route_requirements_with_options_method_condition_is_valid + assert_nothing_raised do + set.draw do |map| + map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :options} + end + end + end + def test_route_requirements_with_head_method_condition_is_invalid assert_raises ArgumentError do set.draw do |map| -- cgit v1.2.3 From 9b8cde41bc84466bf60fc4de6af54dbeb11cc0d6 Mon Sep 17 00:00:00 2001 From: Yury Kotlyarov Date: Thu, 5 Mar 2009 15:55:28 +0300 Subject: Remove duplicate test [#2136 state:resolved] Signed-off-by: Pratik Naik --- actionpack/test/template/javascript_helper_test.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index d41111127b..d2fb24e36e 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -45,11 +45,6 @@ class JavaScriptHelperTest < ActionView::TestCase link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') end - def test_link_to_function_with_href - assert_dom_equal %(Greeting), - link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') - end - def test_button_to_function assert_dom_equal %(), button_to_function("Greeting", "alert('Hello world!')") -- cgit v1.2.3 From 1c36172c13fc51b22167f5e8fc41b1da9f8fcb2a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 8 Mar 2009 13:11:58 -0700 Subject: Ruby 1.9 compat: rename deprecated assert_raises to assert_raise. [#1617 state:resolved] --- actionpack/test/controller/assert_select_test.rb | 56 +++++++++++----------- .../test/controller/html-scanner/document_test.rb | 2 +- actionpack/test/controller/mime_responds_test.rb | 2 +- actionpack/test/controller/redirect_test.rb | 4 +- actionpack/test/controller/render_test.rb | 14 +++--- .../controller/request_forgery_protection_test.rb | 18 +++---- actionpack/test/controller/request_test.rb | 6 +-- actionpack/test/controller/resources_test.rb | 12 ++--- actionpack/test/controller/routing_test.rb | 54 ++++++++++----------- actionpack/test/controller/selector_test.rb | 6 +-- actionpack/test/controller/send_file_test.rb | 2 +- actionpack/test/controller/url_rewriter_test.rb | 2 +- actionpack/test/template/url_helper_test.rb | 2 +- 13 files changed, 90 insertions(+), 90 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index c543118530..298c7e4db3 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -76,7 +76,7 @@ class AssertSelectTest < ActionController::TestCase end def assert_failure(message, &block) - e = assert_raises(Assertion, &block) + e = assert_raise(Assertion, &block) assert_match(message, e.message) if Regexp === message assert_equal(message, e.message) if String === message end @@ -95,24 +95,24 @@ class AssertSelectTest < ActionController::TestCase def test_equality_true_false render_html %Q{
} assert_nothing_raised { assert_select "div" } - assert_raises(Assertion) { assert_select "p" } + assert_raise(Assertion) { assert_select "p" } assert_nothing_raised { assert_select "div", true } - assert_raises(Assertion) { assert_select "p", true } - assert_raises(Assertion) { assert_select "div", false } + assert_raise(Assertion) { assert_select "p", true } + assert_raise(Assertion) { assert_select "div", false } assert_nothing_raised { assert_select "p", false } end def test_equality_string_and_regexp render_html %Q{
foo
foo
} assert_nothing_raised { assert_select "div", "foo" } - assert_raises(Assertion) { assert_select "div", "bar" } + assert_raise(Assertion) { assert_select "div", "bar" } assert_nothing_raised { assert_select "div", :text=>"foo" } - assert_raises(Assertion) { assert_select "div", :text=>"bar" } + assert_raise(Assertion) { assert_select "div", :text=>"bar" } assert_nothing_raised { assert_select "div", /(foo|bar)/ } - assert_raises(Assertion) { assert_select "div", /foobar/ } + assert_raise(Assertion) { assert_select "div", /foobar/ } assert_nothing_raised { assert_select "div", :text=>/(foo|bar)/ } - assert_raises(Assertion) { assert_select "div", :text=>/foobar/ } - assert_raises(Assertion) { assert_select "p", :text=>/foobar/ } + assert_raise(Assertion) { assert_select "div", :text=>/foobar/ } + assert_raise(Assertion) { assert_select "p", :text=>/foobar/ } end def test_equality_of_html @@ -120,17 +120,17 @@ class AssertSelectTest < ActionController::TestCase text = "\"This is not a big problem,\" he said." html = "\"This is not a big problem,\" he said." assert_nothing_raised { assert_select "p", text } - assert_raises(Assertion) { assert_select "p", html } + assert_raise(Assertion) { assert_select "p", html } assert_nothing_raised { assert_select "p", :html=>html } - assert_raises(Assertion) { assert_select "p", :html=>text } + assert_raise(Assertion) { assert_select "p", :html=>text } # No stripping for pre. render_html %Q{
\n"This is not a big problem," he said.\n
} text = "\n\"This is not a big problem,\" he said.\n" html = "\n\"This is not a big problem,\" he said.\n" assert_nothing_raised { assert_select "pre", text } - assert_raises(Assertion) { assert_select "pre", html } + assert_raise(Assertion) { assert_select "pre", html } assert_nothing_raised { assert_select "pre", :html=>html } - assert_raises(Assertion) { assert_select "pre", :html=>text } + assert_raise(Assertion) { assert_select "pre", :html=>text } end def test_counts @@ -210,12 +210,12 @@ class AssertSelectTest < ActionController::TestCase assert_nothing_raised { assert_select "div", "bar" } assert_nothing_raised { assert_select "div", /\w*/ } assert_nothing_raised { assert_select "div", /\w*/, :count=>2 } - assert_raises(Assertion) { assert_select "div", :text=>"foo", :count=>2 } + assert_raise(Assertion) { assert_select "div", :text=>"foo", :count=>2 } assert_nothing_raised { assert_select "div", :html=>"bar" } assert_nothing_raised { assert_select "div", :html=>"bar" } assert_nothing_raised { assert_select "div", :html=>/\w*/ } assert_nothing_raised { assert_select "div", :html=>/\w*/, :count=>2 } - assert_raises(Assertion) { assert_select "div", :html=>"foo", :count=>2 } + assert_raise(Assertion) { assert_select "div", :html=>"foo", :count=>2 } end end @@ -253,7 +253,7 @@ class AssertSelectTest < ActionController::TestCase page.insert_html :top, "test1", "
foo
" page.insert_html :bottom, "test2", "
foo
" end - assert_raises(Assertion) {assert_select_rjs :insert, :top, "test2"} + assert_raise(Assertion) {assert_select_rjs :insert, :top, "test2"} end def test_elect_with_xml_namespace_attributes @@ -336,7 +336,7 @@ class AssertSelectTest < ActionController::TestCase # Test that we fail if there is nothing to pick. def test_assert_select_rjs_fails_if_nothing_to_pick render_rjs { } - assert_raises(Assertion) { assert_select_rjs } + assert_raise(Assertion) { assert_select_rjs } end def test_assert_select_rjs_with_unicode @@ -351,10 +351,10 @@ class AssertSelectTest < ActionController::TestCase if str.respond_to?(:force_encoding) str.force_encoding(Encoding::UTF_8) assert_select str, /\343\203\201..\343\203\210/u - assert_raises(Assertion) { assert_select str, /\343\203\201.\343\203\210/u } + assert_raise(Assertion) { assert_select str, /\343\203\201.\343\203\210/u } else assert_select str, Regexp.new("\343\203\201..\343\203\210",0,'U') - assert_raises(Assertion) { assert_select str, Regexp.new("\343\203\201.\343\203\210",0,'U') } + assert_raise(Assertion) { assert_select str, Regexp.new("\343\203\201.\343\203\210",0,'U') } end end end @@ -378,7 +378,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#3" end - assert_raises(Assertion) { assert_select_rjs "test4" } + assert_raise(Assertion) { assert_select_rjs "test4" } end def test_assert_select_rjs_for_replace @@ -396,7 +396,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#1" end - assert_raises(Assertion) { assert_select_rjs :replace, "test2" } + assert_raise(Assertion) { assert_select_rjs :replace, "test2" } # Replace HTML. assert_select_rjs :replace_html do assert_select "div", 1 @@ -406,7 +406,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#2" end - assert_raises(Assertion) { assert_select_rjs :replace_html, "test1" } + assert_raise(Assertion) { assert_select_rjs :replace_html, "test1" } end def test_assert_select_rjs_for_chained_replace @@ -424,7 +424,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#1" end - assert_raises(Assertion) { assert_select_rjs :chained_replace, "test2" } + assert_raise(Assertion) { assert_select_rjs :chained_replace, "test2" } # Replace HTML. assert_select_rjs :chained_replace_html do assert_select "div", 1 @@ -434,7 +434,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#2" end - assert_raises(Assertion) { assert_select_rjs :replace_html, "test1" } + assert_raise(Assertion) { assert_select_rjs :replace_html, "test1" } end # Simple remove @@ -580,7 +580,7 @@ class AssertSelectTest < ActionController::TestCase assert_select "div", 1 assert_select "#3" end - assert_raises(Assertion) { assert_select_rjs :insert_html, "test1" } + assert_raise(Assertion) { assert_select_rjs :insert_html, "test1" } end # Positioned insert. @@ -613,8 +613,8 @@ class AssertSelectTest < ActionController::TestCase end def test_assert_select_rjs_raise_errors - assert_raises(ArgumentError) { assert_select_rjs(:destroy) } - assert_raises(ArgumentError) { assert_select_rjs(:insert, :left) } + assert_raise(ArgumentError) { assert_select_rjs(:destroy) } + assert_raise(ArgumentError) { assert_select_rjs(:insert, :left) } end # Simple selection from a single result. @@ -706,7 +706,7 @@ EOF # def test_assert_select_email - assert_raises(Assertion) { assert_select_email {} } + assert_raise(Assertion) { assert_select_email {} } AssertSelectMailer.deliver_test "

foo

bar

" assert_select_email do assert_select "div:root" do diff --git a/actionpack/test/controller/html-scanner/document_test.rb b/actionpack/test/controller/html-scanner/document_test.rb index 1c3facb9e3..c68f04fa75 100644 --- a/actionpack/test/controller/html-scanner/document_test.rb +++ b/actionpack/test/controller/html-scanner/document_test.rb @@ -134,7 +134,7 @@ HTML end def test_invalid_document_raises_exception_when_strict - assert_raises RuntimeError do + assert_raise RuntimeError do doc = HTML::Document.new(" diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index dc59180a68..edd7162325 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -469,7 +469,7 @@ class MimeControllerTest < ActionController::TestCase assert_equal '
Hello future from Firefox!
', @response.body @request.accept = "text/iphone" - assert_raises(ActionView::MissingTemplate) { get :iphone_with_html_response_type_without_layout } + assert_raise(ActionView::MissingTemplate) { get :iphone_with_html_response_type_without_layout } end end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 27cedc91d2..91e21db854 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -212,7 +212,7 @@ class RedirectTest < ActionController::TestCase end def test_redirect_to_back_with_no_referer - assert_raises(ActionController::RedirectBackError) { + assert_raise(ActionController::RedirectBackError) { @request.env["HTTP_REFERER"] = nil get :redirect_to_back } @@ -239,7 +239,7 @@ class RedirectTest < ActionController::TestCase end def test_redirect_to_nil - assert_raises(ActionController::ActionControllerError) do + assert_raise(ActionController::ActionControllerError) do get :redirect_to_nil end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e0b3f64b76..af623395f0 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -937,11 +937,11 @@ class RenderTest < ActionController::TestCase end def test_attempt_to_access_object_method - assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + assert_raise(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } end def test_private_methods - assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + assert_raise(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } end def test_access_to_request_in_view @@ -1173,7 +1173,7 @@ class RenderTest < ActionController::TestCase end def test_bad_render_to_string_still_throws_exception - assert_raises(ActionView::MissingTemplate) { get :render_to_string_with_exception } + assert_raise(ActionView::MissingTemplate) { get :render_to_string_with_exception } end def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns @@ -1198,15 +1198,15 @@ class RenderTest < ActionController::TestCase end def test_double_render - assert_raises(ActionController::DoubleRenderError) { get :double_render } + assert_raise(ActionController::DoubleRenderError) { get :double_render } end def test_double_redirect - assert_raises(ActionController::DoubleRenderError) { get :double_redirect } + assert_raise(ActionController::DoubleRenderError) { get :double_redirect } end def test_render_and_redirect - assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect } + assert_raise(ActionController::DoubleRenderError) { get :render_and_redirect } end # specify the one exception to double render rule - render_to_string followed by render @@ -1515,7 +1515,7 @@ class RenderTest < ActionController::TestCase end def test_render_missing_partial_template - assert_raises(ActionView::MissingTemplate) do + assert_raise(ActionView::MissingTemplate) do get :missing_partial end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index ef0bf5fd08..835e73e3ab 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -79,17 +79,17 @@ module RequestForgeryProtectionTests def test_should_not_allow_html_post_without_token @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s - assert_raises(ActionController::InvalidAuthenticityToken) { post :index, :format => :html } + assert_raise(ActionController::InvalidAuthenticityToken) { post :index, :format => :html } end def test_should_not_allow_html_put_without_token @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s - assert_raises(ActionController::InvalidAuthenticityToken) { put :index, :format => :html } + assert_raise(ActionController::InvalidAuthenticityToken) { put :index, :format => :html } end def test_should_not_allow_html_delete_without_token @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s - assert_raises(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html } + assert_raise(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html } end def test_should_allow_api_formatted_post_without_token @@ -111,42 +111,42 @@ module RequestForgeryProtectionTests end def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token - assert_raises(ActionController::InvalidAuthenticityToken) do + assert_raise(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 + assert_raise(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 + assert_raise(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 + assert_raise(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 + assert_raise(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 + assert_raise(ActionController::InvalidAuthenticityToken) do @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s delete :index, :format => 'xml' end diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb index efe4f136f5..c72f885a05 100644 --- a/actionpack/test/controller/request_test.rb +++ b/actionpack/test/controller/request_test.rb @@ -59,7 +59,7 @@ class RequestTest < ActiveSupport::TestCase assert_equal '3.4.5.6', @request.remote_ip @request.env['HTTP_CLIENT_IP'] = '8.8.8.8' - e = assert_raises(ActionController::ActionControllerError) { + e = assert_raise(ActionController::ActionControllerError) { @request.remote_ip } assert_match /IP spoofing attack/, e.message @@ -297,7 +297,7 @@ class RequestTest < ActiveSupport::TestCase end def test_invalid_http_method_raises_exception - assert_raises(ActionController::UnknownHttpMethod) do + assert_raise(ActionController::UnknownHttpMethod) do self.request_method = :random_method @request.request_method end @@ -311,7 +311,7 @@ class RequestTest < ActiveSupport::TestCase end def test_invalid_method_hacking_on_post_raises_exception - assert_raises(ActionController::UnknownHttpMethod) do + assert_raise(ActionController::UnknownHttpMethod) do self.request_method = :_random_method @request.request_method end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 17f6d99b21..35f943737f 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -99,7 +99,7 @@ class ResourcesTest < ActionController::TestCase expected_options = {:controller => 'messages', :action => 'show', :id => '1.1.1'} with_restful_routing :messages do - assert_raises(ActionController::RoutingError) do + assert_raise(ActionController::RoutingError) do assert_recognizes(expected_options, :path => 'messages/1.1.1', :method => :get) end end @@ -333,7 +333,7 @@ class ResourcesTest < ActionController::TestCase with_restful_routing :messages do assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get) - assert_raises(ActionController::MethodNotAllowed) do + assert_raise(ActionController::MethodNotAllowed) do ActionController::Routing::Routes.recognize_path("/messages/new", :method => :post) end end @@ -619,11 +619,11 @@ class ResourcesTest < ActionController::TestCase options = { :controller => controller_name.to_s } collection_path = "/#{controller_name}" - assert_raises(ActionController::MethodNotAllowed) do + assert_raise(ActionController::MethodNotAllowed) do assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :put) end - assert_raises(ActionController::MethodNotAllowed) do + assert_raise(ActionController::MethodNotAllowed) do assert_recognizes(options.merge(:action => 'destroy'), :path => collection_path, :method => :delete) end end @@ -632,7 +632,7 @@ class ResourcesTest < ActionController::TestCase def test_should_not_allow_invalid_head_method_for_member_routes with_routing do |set| set.draw do |map| - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do map.resources :messages, :member => {:something => :head} end end @@ -642,7 +642,7 @@ class ResourcesTest < ActionController::TestCase def test_should_not_allow_invalid_http_methods_for_member_routes with_routing do |set| set.draw do |map| - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do map.resources :messages, :member => {:something => :invalid} end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 55f3ad23be..8ed6b471ae 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -219,7 +219,7 @@ class DynamicSegmentTest < Test::Unit::TestCase a_value = nil # Local jump because of return inside eval. - assert_raises(LocalJumpError) { eval(segment.extraction_code) } + assert_raise(LocalJumpError) { eval(segment.extraction_code) } end def test_extraction_code_should_return_on_mismatch @@ -229,7 +229,7 @@ class DynamicSegmentTest < Test::Unit::TestCase a_value = nil # Local jump because of return inside eval. - assert_raises(LocalJumpError) { eval(segment.extraction_code) } + assert_raise(LocalJumpError) { eval(segment.extraction_code) } end def test_extraction_code_should_accept_value_and_set_local @@ -494,7 +494,7 @@ class RouteBuilderTest < Test::Unit::TestCase defaults = {:action => 'buy', :person => nil, :car => nil} requirements = {:person => /\w+/, :car => /^\w+$/} - assert_raises ArgumentError do + assert_raise ArgumentError do route_requirements = builder.assign_route_options(segments, defaults, requirements) end @@ -882,7 +882,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase end assert_equal({:controller => "admin/accounts", :action => "index"}, rs.recognize_path("/admin/accounts")) assert_equal({:controller => "admin/users", :action => "index"}, rs.recognize_path("/admin/users")) - assert_raises(ActionController::RoutingError) { rs.recognize_path("/admin/products") } + assert_raise(ActionController::RoutingError) { rs.recognize_path("/admin/products") } end def test_route_with_regexp_and_dot @@ -1060,11 +1060,11 @@ class LegacyRouteSetTests < Test::Unit::TestCase rs.draw do |map| map.connect ':controller/:action/:id' end - assert_raises(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") } + assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") } end def test_paths_do_not_accept_defaults - assert_raises(ActionController::RoutingError) do + assert_raise(ActionController::RoutingError) do rs.draw do |map| map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default) map.connect ':controller/:action/:id' @@ -1197,7 +1197,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10) - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do rs.generate(:controller => 'post', :action => 'show') end end @@ -1407,7 +1407,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase end x = setup_for_named_route - assert_raises(ActionController::RoutingError) do + assert_raise(ActionController::RoutingError) do x.send(:foo_with_requirement_url, "I am Against the requirements") end end @@ -1539,7 +1539,7 @@ class RouteTest < Test::Unit::TestCase end def test_builder_complains_without_controller - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index" end end @@ -1822,27 +1822,27 @@ class RouteSetTest < Test::Unit::TestCase end def test_route_requirements_with_anchor_chars_are_invalid - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/ end end - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/ end end - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/ end end - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/ end end - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/ end @@ -1851,14 +1851,14 @@ class RouteSetTest < Test::Unit::TestCase set.draw do |map| map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/, :name => /^(david|jamis)/ end - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.generate :controller => 'pages', :action => 'show', :id => 10 end end end def test_route_requirements_with_invalid_http_method_is_invalid - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :invalid} end @@ -1874,7 +1874,7 @@ class RouteSetTest < Test::Unit::TestCase end def test_route_requirements_with_head_method_condition_is_invalid - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :head} end @@ -1886,10 +1886,10 @@ class RouteSetTest < Test::Unit::TestCase map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/ end assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis') - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis') end - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david') end end @@ -1932,7 +1932,7 @@ class RouteSetTest < Test::Unit::TestCase assert_equal("update", request.path_parameters[:action]) request.recycle! - assert_raises(ActionController::UnknownHttpMethod) { + assert_raise(ActionController::UnknownHttpMethod) { request.env["REQUEST_METHOD"] = "BACON" set.recognize(request) } @@ -2317,7 +2317,7 @@ class RouteSetTest < Test::Unit::TestCase end def test_route_requirements_with_unsupported_regexp_options_must_error - assert_raises ArgumentError do + assert_raise ArgumentError do set.draw do |map| map.connect 'page/:name', :controller => 'pages', :action => 'show', @@ -2355,7 +2355,7 @@ class RouteSetTest < Test::Unit::TestCase :requirements => {:name => /(david|jamis)/i} end assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.recognize_path('/page/davidjamis') end assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID')) @@ -2369,7 +2369,7 @@ class RouteSetTest < Test::Unit::TestCase end url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) assert_equal "/page/david", url - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) end url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) @@ -2389,10 +2389,10 @@ class RouteSetTest < Test::Unit::TestCase end assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david')) - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.recognize_path('/page/david #The Creator') end - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do set.recognize_path('/page/David') end end @@ -2410,10 +2410,10 @@ class RouteSetTest < Test::Unit::TestCase end url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) assert_equal "/page/david", url - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) end - assert_raises ActionController::RoutingError do + assert_raise ActionController::RoutingError do url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) end end diff --git a/actionpack/test/controller/selector_test.rb b/actionpack/test/controller/selector_test.rb index 4e31b4573c..9d0613d1e2 100644 --- a/actionpack/test/controller/selector_test.rb +++ b/actionpack/test/controller/selector_test.rb @@ -303,7 +303,7 @@ class SelectorTest < Test::Unit::TestCase assert_equal 1, @matches.size assert_equal "2", @matches[0].attributes["id"] # Before first and past last returns nothing.: - assert_raises(ArgumentError) { select("tr:nth-child(-1)") } + assert_raise(ArgumentError) { select("tr:nth-child(-1)") } select("tr:nth-child(0)") assert_equal 0, @matches.size select("tr:nth-child(5)") @@ -597,8 +597,8 @@ class SelectorTest < Test::Unit::TestCase def test_negation_details parse(%Q{

}) - assert_raises(ArgumentError) { select(":not(") } - assert_raises(ArgumentError) { select(":not(:not())") } + assert_raise(ArgumentError) { select(":not(") } + assert_raise(ArgumentError) { select(":not(:not())") } select("p:not(#1):not(#3)") assert_equal 1, @matches.size assert_equal "2", @matches[0].attributes["id"] diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 5fc79baa44..a27e951929 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -142,7 +142,7 @@ class SendFileTest < ActionController::TestCase } @controller.headers = {} - assert_raises(ArgumentError){ @controller.send(:send_file_headers!, options) } + assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) } end %w(file data).each do |method| diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index 09a8356fec..863f8414c5 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -99,7 +99,7 @@ class UrlWriterTests < ActionController::TestCase end def test_exception_is_thrown_without_host - assert_raises RuntimeError do + assert_raise RuntimeError do W.new.url_for :controller => 'c', :action => 'a', :id => 'i' end end diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index e7799fb204..5900709d81 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -220,7 +220,7 @@ class UrlHelperTest < ActionView::TestCase end def test_link_tag_using_post_javascript_and_popup - assert_raises(ActionView::ActionViewError) { link_to("Hello", "http://www.example.com", :popup => true, :method => :post, :confirm => "Are you serious?") } + assert_raise(ActionView::ActionViewError) { link_to("Hello", "http://www.example.com", :popup => true, :method => :post, :confirm => "Are you serious?") } end def test_link_tag_using_block_in_erb -- cgit v1.2.3 From a3e67a15edcdcfd2fd84f078cb3e2c76d0226794 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 8 Mar 2009 13:41:51 -0700 Subject: Prototype helpers support the onCreate callback. [#1074 state:committed] --- actionpack/lib/action_view/helpers/prototype_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 18a209dcea..91ef72e54b 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -107,7 +107,7 @@ module ActionView # on the page in an Ajax response. module PrototypeHelper unless const_defined? :CALLBACKS - CALLBACKS = Set.new([ :uninitialized, :loading, :loaded, + CALLBACKS = Set.new([ :create, :uninitialized, :loading, :loaded, :interactive, :complete, :failure, :success ] + (100..599).to_a) AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url, -- cgit v1.2.3 From 1ab2ff58eddee8ac523624dd097424f9a760ad8b Mon Sep 17 00:00:00 2001 From: rpheath Date: Sun, 8 Mar 2009 23:52:28 -0400 Subject: Fixed number_to_phone to work with 7 digit numbers [#2176 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/number_helper.rb | 4 +++- actionpack/test/template/number_helper_test.rb | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index e622f97b9e..539f43c6e3 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -15,6 +15,7 @@ module ActionView # * :country_code - Sets the country code for the phone number. # # ==== Examples + # number_to_phone(5551234) # => 555-1234 # number_to_phone(1235551234) # => 123-555-1234 # number_to_phone(1235551234, :area_code => true) # => (123) 555-1234 # number_to_phone(1235551234, :delimiter => " ") # => 123 555 1234 @@ -37,7 +38,8 @@ module ActionView str << if area_code number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{delimiter}\\3") else - number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3") + number.gsub!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3") + number.starts_with?('-') ? number.slice!(1..-1) : number end str << " x #{extension}" unless extension.blank? str diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 9c9f54936c..29cb60fd73 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -4,6 +4,7 @@ class NumberHelperTest < ActionView::TestCase tests ActionView::Helpers::NumberHelper def test_number_to_phone + assert_equal("555-1234", number_to_phone(5551234)) assert_equal("800-555-1212", number_to_phone(8005551212)) assert_equal("(800) 555-1212", number_to_phone(8005551212, {:area_code => true})) assert_equal("800 555 1212", number_to_phone(8005551212, {:delimiter => " "})) -- cgit v1.2.3 From 90dba00822acd1e01f7a39625668ee74ffe5f061 Mon Sep 17 00:00:00 2001 From: Andrew Bloom Date: Mon, 9 Mar 2009 15:27:13 +0000 Subject: Ensure blank path_prefix works as expected [#2122 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_controller/routing/builder.rb | 3 +- actionpack/test/controller/routing_test.rb | 34 ++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index 44d759444a..d9590c88b8 100644 --- a/actionpack/lib/action_controller/routing/builder.rb +++ b/actionpack/lib/action_controller/routing/builder.rb @@ -159,7 +159,8 @@ module ActionController path = "/#{path}" unless path[0] == ?/ path = "#{path}/" unless path[-1] == ?/ - path = "/#{options[:path_prefix].to_s.gsub(/^\//,'')}#{path}" if options[:path_prefix] + prefix = options[:path_prefix].to_s.gsub(/^\//,'') + path = "/#{prefix}#{path}" unless prefix.blank? segments = segments_for_route_path(path) defaults, requirements, conditions = divide_route_options(segments, options) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 8ed6b471ae..ef56119751 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -955,6 +955,13 @@ class LegacyRouteSetTests < Test::Unit::TestCase x.send(:page_url)) end + def test_named_route_with_blank_path_prefix + rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :path_prefix => '' + x = setup_for_named_route + assert_equal("http://test.host/page", + x.send(:page_url)) + end + def test_named_route_with_nested_controller rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index' x = setup_for_named_route @@ -2130,11 +2137,9 @@ class RouteSetTest < Test::Unit::TestCase Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) set.draw do |map| - map.namespace 'api', :path_prefix => 'prefix' do |api| api.route 'inventory', :controller => "products", :action => 'inventory' end - end request.path = "/prefix/inventory" @@ -2146,6 +2151,24 @@ class RouteSetTest < Test::Unit::TestCase Object.send(:remove_const, :Api) end + def test_namespace_with_blank_path_prefix + Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) + + set.draw do |map| + map.namespace 'api', :path_prefix => '' do |api| + api.route 'inventory', :controller => "products", :action => 'inventory' + end + end + + request.path = "/inventory" + request.env["REQUEST_METHOD"] = "GET" + assert_nothing_raised { set.recognize(request) } + assert_equal("api/products", request.path_parameters[:controller]) + assert_equal("inventory", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :Api) + end + def test_generate_finds_best_fit set.draw do |map| map.connect "/people", :controller => "people", :action => "index" @@ -2210,6 +2233,13 @@ class RouteSetTest < Test::Unit::TestCase assert_equal "/my/foo/bar/7?x=y", set.generate(args) end + def test_generate_with_blank_path_prefix + set.draw { |map| map.connect ':controller/:action/:id', :path_prefix => '' } + + args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } + assert_equal "/foo/bar/7?x=y", set.generate(args) + end + def test_named_routes_are_never_relative_to_modules set.draw do |map| map.connect "/connection/manage/:action", :controller => 'connection/manage' -- cgit v1.2.3 From 224a534400fd622dda57058d1eed349b8375e5e3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 9 Mar 2009 22:45:38 -0500 Subject: reset_session should force a new session id to be generated [#2173] --- actionpack/lib/action_controller/request.rb | 1 + .../test/activerecord/active_record_store_test.rb | 25 ++++++++++++++ .../controller/session/mem_cache_store_test.rb | 40 +++++++++++++--------- 3 files changed, 50 insertions(+), 16 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 2cabab9ec8..ef223f157c 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -442,6 +442,7 @@ EOM end def reset_session + @env['rack.session.options'].delete(:id) @env['rack.session'] = {} end diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index 7998f9c22f..c98892edc1 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -21,8 +21,15 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest render :text => "foo: #{session[:foo].inspect}" end + def get_session_id + session[:foo] + render :text => "#{request.session_options[:id]}" + end + def call_reset_session + session[:bar] reset_session + session[:bar] = "baz" head :ok end @@ -71,6 +78,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest get '/set_session_value' assert_response :success assert cookies['_session_id'] + session_id = cookies['_session_id'] get '/call_reset_session' assert_response :success @@ -79,6 +87,23 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest get '/get_session_value' assert_response :success assert_equal 'foo: nil', response.body + + get '/get_session_id' + assert_response :success + assert_not_equal session_id, response.body + end + end + + def test_getting_session_id + with_test_route_set do + get '/set_session_value' + assert_response :success + assert cookies['_session_id'] + session_id = cookies['_session_id'] + + get '/get_session_id' + assert_response :success + assert_equal session_id, response.body end end diff --git a/actionpack/test/controller/session/mem_cache_store_test.rb b/actionpack/test/controller/session/mem_cache_store_test.rb index c3a6c8ce45..2f80a3c7c2 100644 --- a/actionpack/test/controller/session/mem_cache_store_test.rb +++ b/actionpack/test/controller/session/mem_cache_store_test.rb @@ -17,11 +17,14 @@ class MemCacheStoreTest < ActionController::IntegrationTest end def get_session_id - render :text => "foo: #{session[:foo].inspect}; id: #{request.session_options[:id]}" + session[:foo] + render :text => "#{request.session_options[:id]}" end def call_reset_session + session[:bar] reset_session + session[:bar] = "baz" head :ok end @@ -58,47 +61,52 @@ class MemCacheStoreTest < ActionController::IntegrationTest end end - def test_getting_session_id + def test_setting_session_value_after_session_reset with_test_route_set do get '/set_session_value' assert_response :success assert cookies['_session_id'] session_id = cookies['_session_id'] - get '/get_session_id' + get '/call_reset_session' assert_response :success - assert_equal "foo: \"bar\"; id: #{session_id}", response.body - end - end + assert_not_equal [], headers['Set-Cookie'] - def test_prevents_session_fixation - with_test_route_set do get '/get_session_value' assert_response :success assert_equal 'foo: nil', response.body - session_id = cookies['_session_id'] - - reset! - get '/set_session_value', :_session_id => session_id + get '/get_session_id' assert_response :success - assert_equal nil, cookies['_session_id'] + assert_not_equal session_id, response.body end end - def test_setting_session_value_after_session_reset + def test_getting_session_id with_test_route_set do get '/set_session_value' assert_response :success assert cookies['_session_id'] + session_id = cookies['_session_id'] - get '/call_reset_session' + get '/get_session_id' assert_response :success - assert_not_equal [], headers['Set-Cookie'] + assert_equal session_id, response.body + end + end + def test_prevents_session_fixation + with_test_route_set do get '/get_session_value' assert_response :success assert_equal 'foo: nil', response.body + session_id = cookies['_session_id'] + + reset! + + get '/set_session_value', :_session_id => session_id + assert_response :success + assert_equal nil, cookies['_session_id'] end end rescue LoadError, RuntimeError -- cgit v1.2.3 From df4375d75a6a20c314c911627f1e9897a25aa8fe Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 10 Mar 2009 16:06:21 +0000 Subject: Revert "Updated actionpack/CHANGELOG to include enhancements to form option helpers" No CHANGELOG entries please. This reverts commit 7fa0a8d7f38a42d2f41a3f4aefc129d7071b0258. --- actionpack/CHANGELOG | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 90232d8c2d..c4e4211c42 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -6,8 +6,6 @@ * 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] - * Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] * Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White] -- cgit v1.2.3 From bdfa733d04c5843eadc181f2fd1723db614fc3d0 Mon Sep 17 00:00:00 2001 From: Eugene Pimenov Date: Tue, 10 Mar 2009 16:52:21 +0000 Subject: Ensure auto_link doesnt linkify URLs in the middle of a tag [#1523 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/text_helper.rb | 5 +++-- actionpack/test/template/text_helper_test.rb | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 63fe0c1c57..48bf4717ad 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -536,8 +536,9 @@ module ActionView text.gsub(AUTO_LINK_RE) do href = $& punctuation = '' - # detect already linked URLs - if $` =~ /]*href="$/ + left, right = $`, $' + # detect already linked URLs and URLs in the middle of a tag + if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ # do not change string; URL is alreay linked href else diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 564845779f..a370f1458f 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -375,6 +375,12 @@ class TextHelperTest < ActionView::TestCase assert_equal "{link: #{link3_result}}", auto_link("{link: #{link3_raw}}") end + def test_auto_link_in_tags + link_raw = 'http://www.rubyonrails.org/images/rails.png' + link_result = %Q() + assert_equal link_result, auto_link(link_result) + end + def test_auto_link_at_eol url1 = "http://api.rubyonrails.com/Foo.html" url2 = "http://www.ruby-doc.org/core/Bar.html" -- cgit v1.2.3 From 0464254430f1e594cb2f54dc1e37510fc052c63a Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 10 Mar 2009 16:52:40 +0000 Subject: Add a missing CHANGELOG entry --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index c4e4211c42..90232d8c2d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -6,6 +6,8 @@ * 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] + * Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] * Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White] -- cgit v1.2.3 From 8970f8ace59cb9d07e913566d8d6e87b828759e7 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 10 Mar 2009 15:02:58 -0500 Subject: remove rack gem dependency --- actionpack/Rakefile | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 0d673c617d..2c0c28b755 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -81,7 +81,6 @@ spec = Gem::Specification.new do |s| s.requirements << 'none' s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD) - s.add_dependency('rack', '>= 0.9.0') s.require_path = 'lib' s.autorequire = 'action_controller' -- cgit v1.2.3 From 572e0aac802334d2029e67eb1e87356d890f4255 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 10 Mar 2009 15:05:38 -0500 Subject: update bundled version of rack before 2.3 final --- .../lib/action_controller/vendor/rack-1.0/rack.rb | 1 + .../vendor/rack-1.0/rack/auth/abstract/handler.rb | 4 ++-- .../vendor/rack-1.0/rack/auth/digest/md5.rb | 2 +- .../vendor/rack-1.0/rack/auth/digest/request.rb | 2 +- .../vendor/rack-1.0/rack/builder.rb | 6 +----- .../vendor/rack-1.0/rack/content_type.rb | 23 ++++++++++++++++++++++ .../vendor/rack-1.0/rack/directory.rb | 2 ++ .../vendor/rack-1.0/rack/handler/webrick.rb | 7 ++++++- .../action_controller/vendor/rack-1.0/rack/lint.rb | 4 +++- .../vendor/rack-1.0/rack/response.rb | 2 ++ 10 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 actionpack/lib/action_controller/vendor/rack-1.0/rack/content_type.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb index 6c03b55552..e3e20ed2a3 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb @@ -31,6 +31,7 @@ module Rack autoload :CommonLogger, "rack/commonlogger" autoload :ConditionalGet, "rack/conditionalget" autoload :ContentLength, "rack/content_length" + autoload :ContentType, "rack/content_type" autoload :File, "rack/file" autoload :Deflater, "rack/deflater" autoload :Directory, "rack/directory" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb index 8489c9b9c4..214df6299e 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb @@ -8,8 +8,8 @@ module Rack attr_accessor :realm - def initialize(app, &authenticator) - @app, @authenticator = app, authenticator + def initialize(app, realm=nil, &authenticator) + @app, @realm, @authenticator = app, realm, authenticator end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb index 6d2bd29c2e..e579dc9632 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb @@ -21,7 +21,7 @@ module Rack attr_writer :passwords_hashed - def initialize(app) + def initialize(*args) super @passwords_hashed = nil end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb index a40f57b7f1..a8aa3bf996 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb @@ -8,7 +8,7 @@ module Rack class Request < Auth::AbstractRequest def method - @env['REQUEST_METHOD'] + @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD'] end def digest? diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/builder.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/builder.rb index 25994d5a44..295235e56a 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/builder.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/builder.rb @@ -34,11 +34,7 @@ module Rack end def use(middleware, *args, &block) - @ins << if block_given? - lambda { |app| middleware.new(app, *args, &block) } - else - lambda { |app| middleware.new(app, *args) } - end + @ins << lambda { |app| middleware.new(app, *args, &block) } end def run(app) diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_type.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_type.rb new file mode 100644 index 0000000000..0c1e1ca3e1 --- /dev/null +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_type.rb @@ -0,0 +1,23 @@ +require 'rack/utils' + +module Rack + + # Sets the Content-Type header on responses which don't have one. + # + # Builder Usage: + # use Rack::ContentType, "text/plain" + # + # When no content type argument is provided, "text/html" is assumed. + class ContentType + def initialize(app, content_type = "text/html") + @app, @content_type = app, content_type + end + + def call(env) + status, headers, body = @app.call(env) + headers = Utils::HeaderHash.new(headers) + headers['Content-Type'] ||= @content_type + [status, headers.to_hash, body] + end + end +end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb index 56ee5e7b60..0f37df3a86 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb @@ -89,6 +89,8 @@ table { width:100%%; } type = stat.directory? ? 'directory' : Mime.mime_type(ext) size = stat.directory? ? '-' : filesize_format(size) mtime = stat.mtime.httpdate + url << '/' if stat.directory? + basename << '/' if stat.directory? @files << [ url, basename, size, type, mtime ] end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb index 40be79de13..138aae0ee9 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb @@ -35,7 +35,12 @@ module Rack env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["QUERY_STRING"] ||= "" env["REQUEST_PATH"] ||= "/" - env.delete "PATH_INFO" if env["PATH_INFO"] == "" + if env["PATH_INFO"] == "" + env.delete "PATH_INFO" + else + path, n = req.request_uri.path, env["SCRIPT_NAME"].length + env["PATH_INFO"] = path[n, path.length-n] + end status, headers, body = @app.call(env) begin diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb index 7eb05437f0..66d252b8b0 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb @@ -88,7 +88,9 @@ module Rack ## within the application. This may be an ## empty string, if the request URL targets ## the application root and does not have a - ## trailing slash. + ## trailing slash. This information should be + ## decoded by the server if it comes from a + ## URL. ## QUERY_STRING:: The portion of the request URL that ## follows the ?, if any. May be diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/response.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/response.rb index a593110139..caf60d5b19 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/response.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/response.rb @@ -16,6 +16,8 @@ module Rack # Your application's +call+ should end returning Response#finish. class Response + attr_accessor :length + def initialize(body=[], status=200, header={}, &block) @status = status @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}. -- cgit v1.2.3 From 0a887e2386a827f554c685dccf91701bb38422b5 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 10 Mar 2009 15:09:44 -0500 Subject: check for rack 1.0 gem before falling back to bundled version --- actionpack/lib/action_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index ca826e7bfc..d03f4cb231 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -31,7 +31,12 @@ rescue LoadError end end -require 'action_controller/vendor/rack-1.0/rack' +begin + gem 'rack', '~> 1.0.0' + require 'rack' +rescue Gem::LoadError + require 'action_controller/vendor/rack-1.0/rack' +end module ActionController # TODO: Review explicit to see if they will automatically be handled by -- cgit v1.2.3 From fa45540cdb30cee44983c9121e3ebfc317d21668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 11 Mar 2009 00:02:08 +0100 Subject: Ensure correct content type is declared after cache hits on actions with string cache keys [#1585 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_controller/caching/actions.rb | 27 ++++++++-------------- actionpack/test/controller/caching_test.rb | 14 +++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 34e1c3527f..87b5029e57 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -129,24 +129,23 @@ module ActionController #:nodoc: attr_reader :path, :extension class << self - def path_for(controller, options, infer_extension=true) + def path_for(controller, options, infer_extension = true) new(controller, options, infer_extension).path end end # When true, infer_extension will look up the cache path extension from the request's path & format. - # This is desirable when reading and writing the cache, but not when expiring the cache - expire_action should expire the same files regardless of the request format. - def initialize(controller, options = {}, infer_extension=true) - if infer_extension and options.is_a? Hash - request_extension = extract_extension(controller.request) - options = options.reverse_merge(:format => request_extension) + # This is desirable when reading and writing the cache, but not when expiring the cache - + # expire_action should expire the same files regardless of the request format. + def initialize(controller, options = {}, infer_extension = true) + if infer_extension + extract_extension(controller.request) + options = options.reverse_merge(:format => @extension) if options.is_a?(Hash) end + path = controller.url_for(options).split('://').last normalize!(path) - if infer_extension - @extension = request_extension - add_extension!(path, @extension) - end + add_extension!(path, @extension) @path = URI.unescape(path) end @@ -162,13 +161,7 @@ module ActionController #:nodoc: def extract_extension(request) # Don't want just what comes after the last '.' to accommodate multi part extensions # such as tar.gz. - extension = request.path[/^[^.]+\.(.+)$/, 1] - - # If there's no extension in the path, check request.format - if extension.nil? - extension = request.cache_format - end - extension + @extension = request.path[/^[^.]+\.(.+)$/, 1] || request.cache_format end end end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 9af1ccc740..86dafd9221 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -428,6 +428,20 @@ class ActionCacheTest < ActionController::TestCase assert_equal 'application/xml', @response.content_type end + def test_correct_content_type_is_returned_for_cache_hit_on_action_with_string_key + # run it twice to cache it the first time + get :show, :format => 'xml' + get :show, :format => 'xml' + assert_equal 'application/xml', @response.content_type + end + + def test_correct_content_type_is_returned_for_cache_hit_on_action_with_string_key_from_proc + # run it twice to cache it the first time + get :edit, :id => 1, :format => 'xml' + get :edit, :id => 1, :format => 'xml' + assert_equal 'application/xml', @response.content_type + end + def test_empty_path_is_normalized @mock_controller.mock_url_for = 'http://example.org/' @mock_controller.mock_path = '/' -- cgit v1.2.3 From f2c7508befb085ffe19ec7fb9ca2e6919cc919c9 Mon Sep 17 00:00:00 2001 From: Russ Smith Date: Wed, 11 Mar 2009 12:50:24 -0500 Subject: Update bundled Rack to fix Litespeed compatibility [#2198 state:resolved] Signed-off-by: Joshua Peek --- .../vendor/rack-1.0/rack/content_length.rb | 8 +++++--- .../lib/action_controller/vendor/rack-1.0/rack/deflater.rb | 4 ++-- .../lib/action_controller/vendor/rack-1.0/rack/directory.rb | 4 ++-- .../action_controller/vendor/rack-1.0/rack/handler/lsws.rb | 2 +- .../lib/action_controller/vendor/rack-1.0/rack/lint.rb | 2 +- .../action_controller/vendor/rack-1.0/rack/showstatus.rb | 2 +- .../lib/action_controller/vendor/rack-1.0/rack/utils.rb | 13 +++++++++++++ 7 files changed, 25 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_length.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_length.rb index bce22a32c5..1e56d43853 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/content_length.rb @@ -3,21 +3,23 @@ require 'rack/utils' module Rack # Sets the Content-Length header on responses with fixed-length bodies. class ContentLength + include Rack::Utils + def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) + headers = HeaderHash.new(headers) - if !Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) && + if !STATUS_WITH_NO_ENTITY_BODY.include?(status) && !headers['Content-Length'] && !headers['Transfer-Encoding'] && (body.respond_to?(:to_ary) || body.respond_to?(:to_str)) body = [body] if body.respond_to?(:to_str) # rack 0.4 compat - length = body.to_ary.inject(0) { |len, part| len + part.length } + length = body.to_ary.inject(0) { |len, part| len + bytesize(part) } headers['Content-Length'] = length.to_s end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/deflater.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/deflater.rb index 3e66680092..a42b7477ae 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/deflater.rb @@ -36,12 +36,12 @@ module Rack mtime = headers.key?("Last-Modified") ? Time.httpdate(headers["Last-Modified"]) : Time.now body = self.class.gzip(body, mtime) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) headers = headers.merge("Content-Encoding" => "gzip", "Content-Length" => size.to_s) [status, headers, [body]] when "deflate" body = self.class.deflate(body) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) headers = headers.merge("Content-Encoding" => "deflate", "Content-Length" => size.to_s) [status, headers, [body]] when "identity" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb index 0f37df3a86..acdd3029d3 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/directory.rb @@ -70,7 +70,7 @@ table { width:100%%; } return unless @path_info.include? ".." body = "Forbidden\n" - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]] end @@ -122,7 +122,7 @@ table { width:100%%; } def entity_not_found body = "Entity not found: #{@path_info}\n" - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]] end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb index 1f850fc77b..dfc79c204b 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb @@ -13,7 +13,7 @@ module Rack env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], - "rack.input" => $stdin, + "rack.input" => StringIO.new($stdin.read.to_s), "rack.errors" => $stderr, "rack.multithread" => false, "rack.multiprocess" => true, diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb index 66d252b8b0..ec4dac96f8 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb @@ -403,7 +403,7 @@ module Rack break end - bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size) + bytes += Rack::Utils.bytesize(part) } if env["REQUEST_METHOD"] == "HEAD" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb index 5f13404dce..28258c7c89 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb @@ -27,7 +27,7 @@ module Rack message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s detail = env["rack.showstatus.detail"] || message body = @template.result(binding) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) [status, headers.merge("Content-Type" => "text/html", "Content-Length" => size.to_s), [body]] else [status, headers, body] diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb index f352cb6783..e86d4ccdcd 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb @@ -144,6 +144,19 @@ module Rack end module_function :select_best_encoding + # Return the bytesize of String; uses String#length under Ruby 1.8 and + # String#bytesize under 1.9. + if ''.respond_to?(:bytesize) + def bytesize(string) + string.bytesize + end + else + def bytesize(string) + string.size + end + end + module_function :bytesize + # Context allows the use of a compatible middleware at different points # in a request handling stack. A compatible middleware must define # #context which should take the arguments env and app. The first of which -- cgit v1.2.3 From 724eb9e6121b36e61f373ba4bdcce29f3d0c78da Mon Sep 17 00:00:00 2001 From: Henrik N Date: Thu, 12 Mar 2009 07:29:57 +0100 Subject: Fix some typos, including a global "seperator" -> "separator". --- actionpack/lib/action_view/helpers/date_helper.rb | 4 ++-- actionpack/lib/action_view/helpers/number_helper.rb | 2 +- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index b7ef1fb90d..c74909a360 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -876,8 +876,8 @@ module ActionView input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '') end - # Given an ordering of datetime components, create the selection html - # and join them with their appropriate seperators + # Given an ordering of datetime components, create the selection HTML + # and join them with their appropriate separators. def build_selects_from_types(order) select = '' order.reverse.each do |type| diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 539f43c6e3..dea958deaf 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -140,7 +140,7 @@ module ActionView # number_with_delimiter(12345678) # => 12,345,678 # number_with_delimiter(12345678.05) # => 12,345,678.05 # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678 - # number_with_delimiter(12345678, :seperator => ",") # => 12,345,678 + # number_with_delimiter(12345678, :separator => ",") # => 12,345,678 # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",") # # => 98 765 432,98 # diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 63fe0c1c57..feeddba78d 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -538,7 +538,7 @@ module ActionView punctuation = '' # detect already linked URLs if $` =~ /]*href="$/ - # do not change string; URL is alreay linked + # do not change string; URL is already linked href else # don't include trailing punctuation character as part of the URL -- cgit v1.2.3 From be7b64b35aac1c9e9063d1d8317f8b1be2a3411c Mon Sep 17 00:00:00 2001 From: Donald Parish Date: Thu, 12 Mar 2009 13:24:54 +0000 Subject: Support MD5 passwords for Digest auth and use session_options[:secret] in nonce [#2209 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_controller/http_authentication.rb | 72 +++++++++++++++------- .../controller/http_digest_authentication_test.rb | 53 +++++++++++++--- 2 files changed, 97 insertions(+), 28 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/http_authentication.rb b/actionpack/lib/action_controller/http_authentication.rb index 2ccbc22420..b6b5267c66 100644 --- a/actionpack/lib/action_controller/http_authentication.rb +++ b/actionpack/lib/action_controller/http_authentication.rb @@ -68,8 +68,11 @@ module ActionController # # Simple Digest example: # + # require 'digest/md5' # class PostsController < ApplicationController - # USERS = {"dhh" => "secret"} + # REALM = "SuperSecret" + # USERS = {"dhh" => "secret", #plain text password + # "dap" => Digest:MD5::hexdigest(["dap",REALM,"secret"].join(":")) #ha1 digest password # # before_filter :authenticate, :except => [:index] # @@ -83,14 +86,18 @@ module ActionController # # private # def authenticate - # authenticate_or_request_with_http_digest(realm) do |username| + # authenticate_or_request_with_http_digest(REALM) do |username| # USERS[username] # end # end # end # - # NOTE: The +authenticate_or_request_with_http_digest+ block must return the user's password so the framework can appropriately - # hash it to check the user's credentials. Returning +nil+ will cause authentication to fail. + # NOTE: The +authenticate_or_request_with_http_digest+ block must return the user's password or the ha1 digest hash so the framework can appropriately + # hash to check the user's credentials. Returning +nil+ will cause authentication to fail. + # Storing the ha1 hash: MD5(username:realm:password), is better than storing a plain password. If + # the password file or database is compromised, the attacker would be able to use the ha1 hash to + # authenticate as the user at this +realm+, but would not have the user's password to try using at + # other sites. # # On shared hosts, Apache sometimes doesn't pass authentication headers to # FCGI instances. If your environment matches this description and you cannot @@ -177,26 +184,37 @@ module ActionController end # Raises error unless the request credentials response value matches the expected value. + # First try the password as a ha1 digest password. If this fails, then try it as a plain + # text password. def validate_digest_response(request, realm, &password_procedure) credentials = decode_credentials_header(request) valid_nonce = validate_nonce(request, credentials[:nonce]) - if valid_nonce && realm == credentials[:realm] && opaque(request.session.session_id) == credentials[:opaque] + if valid_nonce && realm == credentials[:realm] && opaque == credentials[:opaque] password = password_procedure.call(credentials[:username]) - expected = expected_response(request.env['REQUEST_METHOD'], credentials[:uri], credentials, password) - expected == credentials[:response] + + [true, false].any? do |password_is_ha1| + expected = expected_response(request.env['REQUEST_METHOD'], request.env['REQUEST_URI'], credentials, password, password_is_ha1) + expected == credentials[:response] + end end end # Returns the expected response for a request of +http_method+ to +uri+ with the decoded +credentials+ and the expected +password+ - def expected_response(http_method, uri, credentials, password) - ha1 = ::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(':')) + # Optional parameter +password_is_ha1+ is set to +true+ by default, since best practice is to store ha1 digest instead + # of a plain-text password. + def expected_response(http_method, uri, credentials, password, password_is_ha1=true) + ha1 = password_is_ha1 ? password : ha1(credentials, password) ha2 = ::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(':')) ::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(':')) end - def encode_credentials(http_method, credentials, password) - credentials[:response] = expected_response(http_method, credentials[:uri], credentials, password) + def ha1(credentials, password) + ::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(':')) + end + + def encode_credentials(http_method, credentials, password, password_is_ha1) + credentials[:response] = expected_response(http_method, credentials[:uri], credentials, password, password_is_ha1) "Digest " + credentials.sort_by {|x| x[0].to_s }.inject([]) {|a, v| a << "#{v[0]}='#{v[1]}'" }.join(', ') end @@ -213,8 +231,7 @@ module ActionController end def authentication_header(controller, realm) - session_id = controller.request.session.session_id - controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce(session_id)}", opaque="#{opaque(session_id)}") + controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce}", opaque="#{opaque}") end def authentication_request(controller, realm, message = nil) @@ -252,23 +269,36 @@ module ActionController # POST or PUT requests and a time-stamp for GET requests. For more details on the issues involved see Section 4 # of this document. # - # The nonce is opaque to the client. - def nonce(session_id, time = Time.now) + # The nonce is opaque to the client. Composed of Time, and hash of Time with secret + # key from the Rails session secret generated upon creation of project. Ensures + # the time cannot be modifed by client. + def nonce(time = Time.now) t = time.to_i - hashed = [t, session_id] + hashed = [t, secret_key] digest = ::Digest::MD5.hexdigest(hashed.join(":")) Base64.encode64("#{t}:#{digest}").gsub("\n", '') end - def validate_nonce(request, value) + # Might want a shorter timeout depending on whether the request + # is a PUT or POST, and if client is browser or web service. + # Can be much shorter if the Stale directive is implemented. This would + # allow a user to use new nonce without prompting user again for their + # username and password. + def validate_nonce(request, value, seconds_to_timeout=5*60) t = Base64.decode64(value).split(":").first.to_i - nonce(request.session.session_id, t) == value && (t - Time.now.to_i).abs <= 10 * 60 + nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout end - # Opaque based on digest of session_id - def opaque(session_id) - Base64.encode64(::Digest::MD5::hexdigest(session_id)).gsub("\n", '') + # Opaque based on random generation - but changing each request? + def opaque() + ::Digest::MD5.hexdigest(secret_key) end + + # Set in /initializers/session_store.rb, and loaded even if sessions are not in use. + def secret_key + ActionController::Base.session_options[:secret] + end + end end end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 4913e7633b..00789eea38 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -5,7 +5,8 @@ class HttpDigestAuthenticationTest < ActionController::TestCase before_filter :authenticate, :only => :index before_filter :authenticate_with_request, :only => :display - USERS = { 'lifo' => 'world', 'pretty' => 'please' } + USERS = { 'lifo' => 'world', 'pretty' => 'please', + 'dhh' => ::Digest::MD5::hexdigest(["dhh","SuperSecret","secret"].join(":"))} def index render :text => "Hello Secret" @@ -107,8 +108,42 @@ class HttpDigestAuthenticationTest < ActionController::TestCase assert_equal 'Definitely Maybe', @response.body end - test "authentication request with relative URI" do - @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:uri => "/", :username => 'pretty', :password => 'please') + test "authentication request with valid credential and nil session" do + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + + # session_id = "" in functional test, but is +nil+ in real life + @request.session.session_id = nil + get :display + + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with request-uri that doesn't match credentials digest-uri" do + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + @request.env['REQUEST_URI'] = "/http_digest_authentication_test/dummy_digest/altered/uri" + get :display + + assert_response :unauthorized + assert_equal "Authentication Failed", @response.body + end + + test "authentication request with absolute uri" do + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:uri => "http://test.host/http_digest_authentication_test/dummy_digest/display", + :username => 'pretty', :password => 'please') + @request.env['REQUEST_URI'] = "http://test.host/http_digest_authentication_test/dummy_digest/display" + get :display + + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with password stored as ha1 digest hash" do + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'dhh', + :password => ::Digest::MD5::hexdigest(["dhh","SuperSecret","secret"].join(":")), + :password_is_ha1 => true) get :display assert_response :success @@ -119,18 +154,22 @@ class HttpDigestAuthenticationTest < ActionController::TestCase private def encode_credentials(options) - options.reverse_merge!(:nc => "00000001", :cnonce => "0a4f113b") + options.reverse_merge!(:nc => "00000001", :cnonce => "0a4f113b", :password_is_ha1 => false) password = options.delete(:password) - # Perform unautheticated get to retrieve digest parameters to use on subsequent request + # Set in /initializers/session_store.rb. Used as secret in generating nonce + # to prevent tampering of timestamp + ActionController::Base.session_options[:secret] = "session_options_secret" + + # Perform unauthenticated GET to retrieve digest parameters to use on subsequent request get :index assert_response :unauthorized credentials = decode_credentials(@response.headers['WWW-Authenticate']) credentials.merge!(options) - credentials.reverse_merge!(:uri => "http://#{@request.host}#{@request.env['REQUEST_URI']}") - ActionController::HttpAuthentication::Digest.encode_credentials("GET", credentials, password) + credentials.reverse_merge!(:uri => "#{@request.env['REQUEST_URI']}") + ActionController::HttpAuthentication::Digest.encode_credentials("GET", credentials, password, options[:password_is_ha1]) end def decode_credentials(header) -- cgit v1.2.3 From d771e7d17f4a2c175676f7c8354aa5b161b63c2e Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Wed, 11 Mar 2009 08:08:09 -0500 Subject: Handle irregular plurals in polymorphic_urls [#2212 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_controller/polymorphic_routes.rb | 7 +- .../test/controller/polymorphic_routes_test.rb | 85 ++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb index 924d1aa6bd..d9b614c237 100644 --- a/actionpack/lib/action_controller/polymorphic_routes.rb +++ b/actionpack/lib/action_controller/polymorphic_routes.rb @@ -163,7 +163,8 @@ module ActionController if parent.is_a?(Symbol) || parent.is_a?(String) string << "#{parent}_" else - string << "#{RecordIdentifier.__send__("singular_class_name", parent)}_" + string << "#{RecordIdentifier.__send__("plural_class_name", parent)}".singularize + string << "_" end end end @@ -171,7 +172,9 @@ module ActionController if record.is_a?(Symbol) || record.is_a?(String) route << "#{record}_" else - route << "#{RecordIdentifier.__send__("#{inflection}_class_name", record)}_" + route << "#{RecordIdentifier.__send__("plural_class_name", record)}" + route = route.singularize if inflection == :singular + route << "_" end action_prefix(options) + namespace + route + routing_type(options).to_s diff --git a/actionpack/test/controller/polymorphic_routes_test.rb b/actionpack/test/controller/polymorphic_routes_test.rb index 53295522ae..146d703619 100644 --- a/actionpack/test/controller/polymorphic_routes_test.rb +++ b/actionpack/test/controller/polymorphic_routes_test.rb @@ -18,6 +18,20 @@ class Tag < Article def response_id; 1 end end +class Tax + attr_reader :id + def save; @id = 1 end + def new_record?; @id.nil? end + def name + model = self.class.name.downcase + @id.nil? ? "new #{model}" : "#{model} ##{@id}" + end +end + +class Fax < Tax + def store_id; 1 end +end + # TODO: test nested models class Response::Nested < Response; end @@ -27,6 +41,8 @@ class PolymorphicRoutesTest < ActiveSupport::TestCase def setup @article = Article.new @response = Response.new + @tax = Tax.new + @fax = Fax.new end def test_with_record @@ -205,4 +221,73 @@ class PolymorphicRoutesTest < ActiveSupport::TestCase polymorphic_url(path) end end + + # Tests for names where .plural.singular doesn't round-trip + def test_with_irregular_plural_record + @tax.save + expects(:taxis_url).with(@tax) + polymorphic_url(@tax) + end + + def test_with_irregular_plural_new_record + expects(:taxes_url).with() + @tax.expects(:new_record?).returns(true) + polymorphic_url(@tax) + end + + def test_with_irregular_plural_record_and_action + expects(:new_taxis_url).with() + @tax.expects(:new_record?).never + polymorphic_url(@tax, :action => 'new') + end + + def test_irregular_plural_url_helper_prefixed_with_new + expects(:new_taxis_url).with() + new_polymorphic_url(@tax) + end + + def test_irregular_plural_url_helper_prefixed_with_edit + @tax.save + expects(:edit_taxis_url).with(@tax) + edit_polymorphic_url(@tax) + end + + def test_with_nested_irregular_plurals + @fax.save + expects(:taxis_faxis_url).with(@tax, @fax) + polymorphic_url([@tax, @fax]) + end + + def test_with_nested_unsaved_irregular_plurals + expects(:taxis_faxes_url).with(@tax) + polymorphic_url([@tax, @fax]) + end + + def test_new_with_irregular_plural_array_and_namespace + expects(:new_admin_taxis_url).with() + polymorphic_url([:admin, @tax], :action => 'new') + end + + def test_unsaved_with_irregular_plural_array_and_namespace + expects(:admin_taxes_url).with() + polymorphic_url([:admin, @tax]) + end + + def test_nesting_with_irregular_plurals_and_array_ending_in_singleton_resource + expects(:taxis_faxis_url).with(@tax) + polymorphic_url([@tax, :faxis]) + end + + def test_with_array_containing_single_irregular_plural_object + @tax.save + expects(:taxis_url).with(@tax) + polymorphic_url([nil, @tax]) + end + + def test_with_array_containing_single_name_irregular_plural + @tax.save + expects(:taxes_url) + polymorphic_url([:taxes]) + end + end -- cgit v1.2.3 From c8c2b3820e662a2f9dfbfdae7211625adfabf15f Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 12 Mar 2009 12:22:52 -0700 Subject: Eliminate internal render stack since we only need its head and tail --- actionpack/lib/action_view/base.rb | 18 ++++++++++++++++-- actionpack/lib/action_view/renderable.rb | 26 +++++++++++--------------- 2 files changed, 27 insertions(+), 17 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index fe6053e574..0f396817a5 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -221,10 +221,12 @@ module ActionView #:nodoc: def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc: @assigns = assigns_for_first_render @assigns_added = nil - @_render_stack = [] @controller = controller @helpers = ProxyModule.new(self) self.view_paths = view_paths + + @_first_template = nil + @_current_template = nil end attr_reader :view_paths @@ -286,7 +288,19 @@ module ActionView #:nodoc: # Access the current template being rendered. # Returns a ActionView::Template object. def template - @_render_stack.last + @_current_template + end + + def template=(template) #:nodoc: + @_first_template ||= template + @_current_template = template + end + + def with_template(current_template) + last_template, self.template = template, current_template + yield + ensure + self.template = last_template end private diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 41080ed629..ff7bc7d9de 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -27,23 +27,19 @@ module ActionView def render(view, local_assigns = {}) compile(local_assigns) - stack = view.instance_variable_get(:@_render_stack) - stack.push(self) - - view.send(:_evaluate_assigns_and_ivars) - view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type) - - result = view.send(method_name(local_assigns), local_assigns) do |*names| - ivar = :@_proc_for_layout - if !view.instance_variable_defined?(:"@content_for_#{names.first}") && view.instance_variable_defined?(ivar) && (proc = view.instance_variable_get(ivar)) - view.capture(*names, &proc) - elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}") - view.instance_variable_get(ivar) + view.with_template self do + view.send(:_evaluate_assigns_and_ivars) + view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type) + + view.send(method_name(local_assigns), local_assigns) do |*names| + ivar = :@_proc_for_layout + if !view.instance_variable_defined?(:"@content_for_#{names.first}") && view.instance_variable_defined?(ivar) && (proc = view.instance_variable_get(ivar)) + view.capture(*names, &proc) + elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}") + view.instance_variable_get(ivar) + end end end - - stack.pop - result end def method_name(local_assigns) -- cgit v1.2.3 From 82c6597dc244715c40151c7eb10f2016ed5ebb47 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 12 Mar 2009 12:22:52 -0700 Subject: Eliminate internal render stack since we only need its head and tail --- actionpack/lib/action_view/base.rb | 18 ++++++++++++++++-- actionpack/lib/action_view/renderable.rb | 26 +++++++++++--------------- 2 files changed, 27 insertions(+), 17 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index fe6053e574..0f396817a5 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -221,10 +221,12 @@ module ActionView #:nodoc: def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc: @assigns = assigns_for_first_render @assigns_added = nil - @_render_stack = [] @controller = controller @helpers = ProxyModule.new(self) self.view_paths = view_paths + + @_first_template = nil + @_current_template = nil end attr_reader :view_paths @@ -286,7 +288,19 @@ module ActionView #:nodoc: # Access the current template being rendered. # Returns a ActionView::Template object. def template - @_render_stack.last + @_current_template + end + + def template=(template) #:nodoc: + @_first_template ||= template + @_current_template = template + end + + def with_template(current_template) + last_template, self.template = template, current_template + yield + ensure + self.template = last_template end private diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 41080ed629..ff7bc7d9de 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -27,23 +27,19 @@ module ActionView def render(view, local_assigns = {}) compile(local_assigns) - stack = view.instance_variable_get(:@_render_stack) - stack.push(self) - - view.send(:_evaluate_assigns_and_ivars) - view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type) - - result = view.send(method_name(local_assigns), local_assigns) do |*names| - ivar = :@_proc_for_layout - if !view.instance_variable_defined?(:"@content_for_#{names.first}") && view.instance_variable_defined?(ivar) && (proc = view.instance_variable_get(ivar)) - view.capture(*names, &proc) - elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}") - view.instance_variable_get(ivar) + view.with_template self do + view.send(:_evaluate_assigns_and_ivars) + view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type) + + view.send(method_name(local_assigns), local_assigns) do |*names| + ivar = :@_proc_for_layout + if !view.instance_variable_defined?(:"@content_for_#{names.first}") && view.instance_variable_defined?(ivar) && (proc = view.instance_variable_get(ivar)) + view.capture(*names, &proc) + elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}") + view.instance_variable_get(ivar) + end end end - - stack.pop - result end def method_name(local_assigns) -- cgit v1.2.3 From 5f1d6465b47333db730a4bb4ac3d2a083b7c8f3c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 12 Mar 2009 13:32:52 -0700 Subject: Change naming to match 2.2 so life is easier on plugin developers --- actionpack/lib/action_view/base.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 0f396817a5..e19acc5c29 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -225,8 +225,8 @@ module ActionView #:nodoc: @helpers = ProxyModule.new(self) self.view_paths = view_paths - @_first_template = nil - @_current_template = nil + @_first_render = nil + @_current_render = nil end attr_reader :view_paths @@ -288,12 +288,12 @@ module ActionView #:nodoc: # Access the current template being rendered. # Returns a ActionView::Template object. def template - @_current_template + @_current_render end def template=(template) #:nodoc: - @_first_template ||= template - @_current_template = template + @_first_render ||= template + @_current_render = template end def with_template(current_template) -- cgit v1.2.3 From 91d274059536f09dffd87141e570c3eab9ebd9b4 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 12 Mar 2009 21:47:34 -0700 Subject: Return body parts directly to Rack rather than building a response string ourselves. Allows Rack middleware to orchestrate response building. --- actionpack/lib/action_controller/base.rb | 12 ++++---- actionpack/lib/action_controller/integration.rb | 10 ++++--- actionpack/lib/action_controller/response.rb | 37 +++++++++++++++++------- actionpack/lib/action_controller/test_process.rb | 4 +-- actionpack/test/controller/rack_test.rb | 2 +- actionpack/test/controller/send_file_test.rb | 4 +-- 6 files changed, 43 insertions(+), 26 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 0facf7066d..c6dd99e959 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -984,6 +984,7 @@ module ActionController #:nodoc: # of sending it as the response body to the browser. def render_to_string(options = nil, &block) #:doc: render(options, &block) + response.body ensure response.content_type = nil erase_render_results @@ -1020,7 +1021,7 @@ module ActionController #:nodoc: # Clears the rendered results, allowing for another render to be performed. def erase_render_results #:nodoc: - response.body = nil + response.body = [] @performed_render = false end @@ -1247,13 +1248,12 @@ module ActionController #:nodoc: response.status = interpret_status(status || DEFAULT_RENDER_STATUS_CODE) if append_response - response.body ||= '' - response.body << text.to_s + response.body_parts << text.to_s else response.body = case text - when Proc then text - when nil then " " # Safari doesn't pass the headers of the return if the response is zero length - else text.to_s + when Proc then text + when nil then [" "] # Safari doesn't pass the headers of the return if the response is zero length + else [text.to_s] end end end diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb index 1c05ab0bf6..4faa263e2d 100644 --- a/actionpack/lib/action_controller/integration.rb +++ b/actionpack/lib/action_controller/integration.rb @@ -332,11 +332,13 @@ module ActionController @cookies[name] = value end - @body = "" if body.is_a?(String) - @body << body + @body_parts = [body] + @body = body else - body.each { |part| @body << part } + @body_parts = [] + body.each { |part| @body_parts << part.to_s } + @body = @body_parts.join end if @controller = ActionController::Base.last_instantiation @@ -349,7 +351,7 @@ module ActionController @response = Response.new @response.status = status.to_s @response.headers.replace(@headers) - @response.body = @body + @response.body = @body_parts end # Decorate the response with the standard behavior of the diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb index ccff473df0..c69223dd69 100644 --- a/actionpack/lib/action_controller/response.rb +++ b/actionpack/lib/action_controller/response.rb @@ -40,14 +40,28 @@ module ActionController # :nodoc: delegate :default_charset, :to => 'ActionController::Base' def initialize - @status = 200 + super @header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS) + @session, @assigns = [], [] + end - @writer = lambda { |x| @body << x } - @block = nil + def body + str = '' + each { |part| str << part.to_s } + str + end - @body = "", - @session, @assigns = [], [] + def body=(body) + @body = + if body.is_a?(String) + [body] + else + body + end + end + + def body_parts + @body end def location; headers['Location'] end @@ -152,7 +166,7 @@ module ActionController # :nodoc: @writer = lambda { |x| callback.call(x) } @body.call(self, self) elsif @body.is_a?(String) - @body.each_line(&callback) + callback.call(@body) else @body.each(&callback) end @@ -162,7 +176,8 @@ module ActionController # :nodoc: end def write(str) - @writer.call str.to_s + str = str.to_s + @writer.call str str end @@ -186,7 +201,7 @@ module ActionController # :nodoc: if request && request.etag_matches?(etag) self.status = '304 Not Modified' - self.body = '' + self.body = [] end set_conditional_cache_control! @@ -195,7 +210,7 @@ module ActionController # :nodoc: def nonempty_ok_response? ok = !status || status.to_s[0..2] == '200' - ok && body.is_a?(String) && !body.empty? + ok && !body_parts.respond_to?(:call) && body_parts.any? end def set_conditional_cache_control! @@ -216,8 +231,8 @@ module ActionController # :nodoc: headers.delete('Content-Length') elsif length = headers['Content-Length'] headers['Content-Length'] = length.to_s - elsif !body.respond_to?(:call) && (!status || status.to_s[0..2] != '304') - headers["Content-Length"] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s + elsif !body_parts.respond_to?(:call) && (!status || status.to_s[0..2] != '304') + headers["Content-Length"] = Rack::Utils.bytesize(body).to_s end end diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index dbaec00bee..9dd09c30b4 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -258,11 +258,11 @@ module ActionController #:nodoc: # Returns binary content (downloadable file), converted to a String def binary_content - raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc) + raise "Response body is not a Proc: #{body_parts.inspect}" unless body_parts.kind_of?(Proc) require 'stringio' sio = StringIO.new - body.call(self, sio) + body_parts.call(self, sio) sio.rewind sio.read diff --git a/actionpack/test/controller/rack_test.rb b/actionpack/test/controller/rack_test.rb index b550d3db78..89bf4fdacc 100644 --- a/actionpack/test/controller/rack_test.rb +++ b/actionpack/test/controller/rack_test.rb @@ -258,7 +258,7 @@ class RackResponseTest < BaseRackTest }, headers) parts = [] - body.each { |part| parts << part } + body.each { |part| parts << part.to_s } assert_equal ["0", "1", "2", "3", "4"], parts end end diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index a27e951929..3d1904fee9 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -44,12 +44,12 @@ class SendFileTest < ActionController::TestCase response = nil assert_nothing_raised { response = process('file') } assert_not_nil response - assert_kind_of Proc, response.body + assert_kind_of Proc, response.body_parts require 'stringio' output = StringIO.new output.binmode - assert_nothing_raised { response.body.call(response, output) } + assert_nothing_raised { response.body_parts.call(response, output) } assert_equal file_data, output.string end -- cgit v1.2.3 From 3d260760f035c5aab11ab218881ed36e3046157b Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 00:25:05 -0700 Subject: Introduce flush_output_buffer to append the buffer to the response body then start a new buffer. Useful for pushing custom parts to the response body without disrupting template rendering. --- .../lib/action_view/helpers/capture_helper.rb | 8 +++++ actionpack/test/template/output_buffer_test.rb | 35 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 actionpack/test/template/output_buffer_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index e86ca27f31..9e39536653 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -131,6 +131,14 @@ module ActionView ensure self.output_buffer = old_buffer end + + # Add the output buffer to the response body and start a new one. + def flush_output_buffer #:nodoc: + if output_buffer && output_buffer != '' + response.body_parts << output_buffer + self.output_buffer = '' + end + end end end end diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb new file mode 100644 index 0000000000..6d8eab63dc --- /dev/null +++ b/actionpack/test/template/output_buffer_test.rb @@ -0,0 +1,35 @@ +require 'abstract_unit' + +class OutputBufferTest < ActionController::TestCase + class TestController < ActionController::Base + def index + render :text => 'foo' + end + end + + tests TestController + + def test_flush_output_buffer + # Start with the default body parts + get :index + assert_equal ['foo'], @response.body_parts + assert_nil @response.template.output_buffer + + # Nil output buffer is skipped + @response.template.flush_output_buffer + assert_nil @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Empty output buffer is skipped + @response.template.output_buffer = '' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Flushing appends the output buffer to the body parts + @response.template.output_buffer = 'bar' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo', 'bar'], @response.body_parts + end +end -- cgit v1.2.3 From 79b0b1a0ef926e91388e24bc77d3831f6d50b13d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 02:15:51 -0700 Subject: Extract Response#string_body? --- actionpack/lib/action_controller/response.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb index c69223dd69..febe4ccf29 100644 --- a/actionpack/lib/action_controller/response.rb +++ b/actionpack/lib/action_controller/response.rb @@ -210,7 +210,11 @@ module ActionController # :nodoc: def nonempty_ok_response? ok = !status || status.to_s[0..2] == '200' - ok && !body_parts.respond_to?(:call) && body_parts.any? + ok && string_body? + end + + def string_body? + !body_parts.respond_to?(:call) && body_parts.any? && body_parts.all? { |part| part.is_a?(String) } end def set_conditional_cache_control! @@ -231,7 +235,7 @@ module ActionController # :nodoc: headers.delete('Content-Length') elsif length = headers['Content-Length'] headers['Content-Length'] = length.to_s - elsif !body_parts.respond_to?(:call) && (!status || status.to_s[0..2] != '304') + elsif string_body? && (!status || status.to_s[0..2] != '304') headers["Content-Length"] = Rack::Utils.bytesize(body).to_s end end -- cgit v1.2.3 From 7c1714cbd0b37d1fc5ca2ac3e08980943454d516 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 02:36:00 -0700 Subject: Body parts: future rendering, threaded future, queued future, open-uri example --- actionpack/lib/action_view/base.rb | 10 +- actionpack/lib/action_view/body_parts/future.rb | 26 ++++ actionpack/lib/action_view/body_parts/open_uri.rb | 13 ++ actionpack/lib/action_view/body_parts/queued.rb | 21 ++++ actionpack/lib/action_view/body_parts/threaded.rb | 21 ++++ actionpack/test/template/body_parts_test.rb | 142 ++++++++++++++++++++++ actionpack/test/template/output_buffer_test.rb | 35 ------ 7 files changed, 231 insertions(+), 37 deletions(-) create mode 100644 actionpack/lib/action_view/body_parts/future.rb create mode 100644 actionpack/lib/action_view/body_parts/open_uri.rb create mode 100644 actionpack/lib/action_view/body_parts/queued.rb create mode 100644 actionpack/lib/action_view/body_parts/threaded.rb create mode 100644 actionpack/test/template/body_parts_test.rb delete mode 100644 actionpack/test/template/output_buffer_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index e19acc5c29..3bbd2ca530 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -288,12 +288,12 @@ module ActionView #:nodoc: # Access the current template being rendered. # Returns a ActionView::Template object. def template - @_current_render + Thread.current[:_current_render] end def template=(template) #:nodoc: @_first_render ||= template - @_current_render = template + Thread.current[:_current_render] = template end def with_template(current_template) @@ -303,6 +303,12 @@ module ActionView #:nodoc: self.template = last_template end + def punctuate_body!(part) + flush_output_buffer + response.body_parts << part + nil + end + private # Evaluates the local assigns and controller ivars, pushes them to the view. def _evaluate_assigns_and_ivars #:nodoc: diff --git a/actionpack/lib/action_view/body_parts/future.rb b/actionpack/lib/action_view/body_parts/future.rb new file mode 100644 index 0000000000..a5291c6e8c --- /dev/null +++ b/actionpack/lib/action_view/body_parts/future.rb @@ -0,0 +1,26 @@ +module ActionView + module BodyParts + class Future + def initialize(&block) + @block = block + @parts = [] + end + + def to_s + finish + body + end + + protected + def work + @block.call(@parts) + end + + def body + str = '' + @parts.each { |part| str << part.to_s } + str + end + end + end +end diff --git a/actionpack/lib/action_view/body_parts/open_uri.rb b/actionpack/lib/action_view/body_parts/open_uri.rb new file mode 100644 index 0000000000..8ebd17b4a1 --- /dev/null +++ b/actionpack/lib/action_view/body_parts/open_uri.rb @@ -0,0 +1,13 @@ +require 'action_view/body_parts/threaded' +require 'open-uri' + +module ActionView + module BodyParts + class OpenUri < Threaded + def initialize(url) + url = URI::Generic === url ? url : URI.parse(url) + super(true) { |parts| parts << url.read } + end + end + end +end diff --git a/actionpack/lib/action_view/body_parts/queued.rb b/actionpack/lib/action_view/body_parts/queued.rb new file mode 100644 index 0000000000..f8501f6a85 --- /dev/null +++ b/actionpack/lib/action_view/body_parts/queued.rb @@ -0,0 +1,21 @@ +require 'action_view/body_parts/future' + +module ActionView + module BodyParts + class Queued < Future + def initialize(job, &block) + super(&block) + enqueue(job) + end + + protected + def enqueue(job) + @receipt = submit(job) + end + + def finish + @parts << redeem(@receipt) + end + end + end +end diff --git a/actionpack/lib/action_view/body_parts/threaded.rb b/actionpack/lib/action_view/body_parts/threaded.rb new file mode 100644 index 0000000000..34800bf9c7 --- /dev/null +++ b/actionpack/lib/action_view/body_parts/threaded.rb @@ -0,0 +1,21 @@ +require 'action_view/body_parts/future' + +module ActionView + module BodyParts + class Threaded < Future + def initialize(concurrent = false, &block) + super(&block) + concurrent ? start : work + end + + protected + def start + @worker = Thread.new { work } + end + + def finish + @worker.join if @worker && @worker.alive? + end + end + end +end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb new file mode 100644 index 0000000000..d15c8808d9 --- /dev/null +++ b/actionpack/test/template/body_parts_test.rb @@ -0,0 +1,142 @@ +require 'abstract_unit' +require 'action_view/body_parts/queued' +require 'action_view/body_parts/open_uri' + +class OutputBufferTest < ActionController::TestCase + class TestController < ActionController::Base + def index + render :text => 'foo' + end + end + + tests TestController + + def test_flush_output_buffer + # Start with the default body parts + get :index + assert_equal ['foo'], @response.body_parts + assert_nil @response.template.output_buffer + + # Nil output buffer is skipped + @response.template.flush_output_buffer + assert_nil @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Empty output buffer is skipped + @response.template.output_buffer = '' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Flushing appends the output buffer to the body parts + @response.template.output_buffer = 'bar' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo', 'bar'], @response.body_parts + end +end + +class QueuedPartTest < ActionController::TestCase + class SimpleQueued < ActionView::BodyParts::Queued + protected + def submit(job) + job + end + + def redeem(receipt) + receipt.to_s.reverse + end + end + + class TestController < ActionController::Base + def index + queued_render 'foo' + queued_render 'bar' + queued_render 'baz' + @performed_render = true + end + + def queued_render(job) + response.template.punctuate_body! SimpleQueued.new(job) + end + end + + tests TestController + + def test_queued_parts + get :index + assert_equal 'oofrabzab', @response.body + end +end + +class ThreadedPartTest < ActionController::TestCase + class TestController < ActionController::Base + def index + append_thread_id = lambda do |parts| + parts << Thread.current.object_id + parts << '::' + parts << Time.now.to_i + sleep 1 + end + + future_render &append_thread_id + response.body_parts << '-' + + future_render &append_thread_id + response.body_parts << '-' + + future_render do |parts| + parts << ActionView::BodyParts::Threaded.new(true, &append_thread_id) + parts << '-' + parts << ActionView::BodyParts::Threaded.new(true, &append_thread_id) + end + + @performed_render = true + end + + def future_render(&block) + response.template.punctuate_body! ActionView::BodyParts::Threaded.new(true, &block) + end + end + + tests TestController + + def test_concurrent_threaded_parts + get :index + + before = Time.now.to_i + thread_ids = @response.body.split('-').map { |part| part.split('::').first.to_i } + elapsed = Time.now.to_i - before + + assert_equal thread_ids.size, thread_ids.uniq.size + assert elapsed < 1.1 + end +end + +class OpenUriPartTest < ActionController::TestCase + class TestController < ActionController::Base + def index + render_url 'http://localhost/foo' + render_url 'http://localhost/bar' + render_url 'http://localhost/baz' + @performed_render = true + end + + def render_url(url) + url = URI.parse(url) + def url.read; path end + response.template.punctuate_body! ActionView::BodyParts::OpenUri.new(url) + end + end + + tests TestController + + def test_concurrent_open_uri_parts + get :index + + elapsed = Benchmark.ms do + assert_equal '/foo/bar/baz', @response.body + end + assert elapsed < 1.1 + end +end diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb deleted file mode 100644 index 6d8eab63dc..0000000000 --- a/actionpack/test/template/output_buffer_test.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'abstract_unit' - -class OutputBufferTest < ActionController::TestCase - class TestController < ActionController::Base - def index - render :text => 'foo' - end - end - - tests TestController - - def test_flush_output_buffer - # Start with the default body parts - get :index - assert_equal ['foo'], @response.body_parts - assert_nil @response.template.output_buffer - - # Nil output buffer is skipped - @response.template.flush_output_buffer - assert_nil @response.template.output_buffer - assert_equal ['foo'], @response.body_parts - - # Empty output buffer is skipped - @response.template.output_buffer = '' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer - assert_equal ['foo'], @response.body_parts - - # Flushing appends the output buffer to the body parts - @response.template.output_buffer = 'bar' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer - assert_equal ['foo', 'bar'], @response.body_parts - end -end -- cgit v1.2.3 From 5d76dee329282acc918de50fecde869f1431e2f1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 02:55:24 -0700 Subject: Example using an edge side include body part to fetch queued rendering results --- actionpack/lib/action_view/body_parts/open_uri.rb | 13 -------- actionpack/test/template/body_parts_test.rb | 36 +++++++++++++++++------ 2 files changed, 27 insertions(+), 22 deletions(-) delete mode 100644 actionpack/lib/action_view/body_parts/open_uri.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/body_parts/open_uri.rb b/actionpack/lib/action_view/body_parts/open_uri.rb deleted file mode 100644 index 8ebd17b4a1..0000000000 --- a/actionpack/lib/action_view/body_parts/open_uri.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'action_view/body_parts/threaded' -require 'open-uri' - -module ActionView - module BodyParts - class OpenUri < Threaded - def initialize(url) - url = URI::Generic === url ? url : URI.parse(url) - super(true) { |parts| parts << url.read } - end - end - end -end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index d15c8808d9..88f09af94f 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -36,28 +36,36 @@ class OutputBufferTest < ActionController::TestCase end end + class QueuedPartTest < ActionController::TestCase - class SimpleQueued < ActionView::BodyParts::Queued + class EdgeSideInclude < ActionView::BodyParts::Queued + QUEUE_REDEMPTION_URL = 'http://queue/jobs/%s' + ESI_INCLUDE_TAG = '' + + def self.redemption_tag(receipt) + ESI_INCLUDE_TAG % QUEUE_REDEMPTION_URL % receipt + end + protected def submit(job) - job + job.reverse end def redeem(receipt) - receipt.to_s.reverse + self.class.redemption_tag(receipt) end end class TestController < ActionController::Base def index - queued_render 'foo' - queued_render 'bar' - queued_render 'baz' + edge_side_include 'foo' + edge_side_include 'bar' + edge_side_include 'baz' @performed_render = true end - def queued_render(job) - response.template.punctuate_body! SimpleQueued.new(job) + def edge_side_include(job) + response.template.punctuate_body! EdgeSideInclude.new(job) end end @@ -65,10 +73,12 @@ class QueuedPartTest < ActionController::TestCase def test_queued_parts get :index - assert_equal 'oofrabzab', @response.body + expected = %(oof rab zab).map { |receipt| EdgeSideInclude.redemption_tag(receipt) } + assert_equal expected, @response.body end end + class ThreadedPartTest < ActionController::TestCase class TestController < ActionController::Base def index @@ -113,7 +123,15 @@ class ThreadedPartTest < ActionController::TestCase end end + class OpenUriPartTest < ActionController::TestCase + class OpenUri < ActionView::BodyParts::Threaded + def initialize(url) + url = URI::Generic === url ? url : URI.parse(url) + super(true) { |parts| parts << url.read } + end + end + class TestController < ActionController::Base def index render_url 'http://localhost/foo' -- cgit v1.2.3 From d54d97b07c1b258f42210b1a3fc2e8c56e434ee9 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 03:01:47 -0700 Subject: Fix tests --- actionpack/test/template/body_parts_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 88f09af94f..7418f4a716 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' require 'action_view/body_parts/queued' -require 'action_view/body_parts/open_uri' +require 'action_view/body_parts/threaded' class OutputBufferTest < ActionController::TestCase class TestController < ActionController::Base @@ -73,7 +73,7 @@ class QueuedPartTest < ActionController::TestCase def test_queued_parts get :index - expected = %(oof rab zab).map { |receipt| EdgeSideInclude.redemption_tag(receipt) } + expected = %w(oof rab zab).map { |receipt| EdgeSideInclude.redemption_tag(receipt) }.join assert_equal expected, @response.body end end @@ -125,7 +125,7 @@ end class OpenUriPartTest < ActionController::TestCase - class OpenUri < ActionView::BodyParts::Threaded + class OpenUriPart < ActionView::BodyParts::Threaded def initialize(url) url = URI::Generic === url ? url : URI.parse(url) super(true) { |parts| parts << url.read } @@ -143,7 +143,7 @@ class OpenUriPartTest < ActionController::TestCase def render_url(url) url = URI.parse(url) def url.read; path end - response.template.punctuate_body! ActionView::BodyParts::OpenUri.new(url) + response.template.punctuate_body! OpenUriPart.new(url) end end -- cgit v1.2.3 From b2f98c13a3308e6db618d6f3f9f706cbc19f13fd Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 03:16:14 -0700 Subject: Simplify parts and tests --- actionpack/lib/action_view/body_parts/future.rb | 16 ---------------- actionpack/lib/action_view/body_parts/queued.rb | 13 +++++-------- actionpack/lib/action_view/body_parts/threaded.rb | 13 ++++++++++++- actionpack/test/template/body_parts_test.rb | 17 ++++++++--------- 4 files changed, 25 insertions(+), 34 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/body_parts/future.rb b/actionpack/lib/action_view/body_parts/future.rb index a5291c6e8c..f03c2b395b 100644 --- a/actionpack/lib/action_view/body_parts/future.rb +++ b/actionpack/lib/action_view/body_parts/future.rb @@ -1,26 +1,10 @@ module ActionView module BodyParts class Future - def initialize(&block) - @block = block - @parts = [] - end - def to_s finish body end - - protected - def work - @block.call(@parts) - end - - def body - str = '' - @parts.each { |part| str << part.to_s } - str - end end end end diff --git a/actionpack/lib/action_view/body_parts/queued.rb b/actionpack/lib/action_view/body_parts/queued.rb index f8501f6a85..618999742b 100644 --- a/actionpack/lib/action_view/body_parts/queued.rb +++ b/actionpack/lib/action_view/body_parts/queued.rb @@ -3,18 +3,15 @@ require 'action_view/body_parts/future' module ActionView module BodyParts class Queued < Future - def initialize(job, &block) - super(&block) - enqueue(job) + attr_reader :body + + def initialize(job) + @receipt = enqueue(job) end protected - def enqueue(job) - @receipt = submit(job) - end - def finish - @parts << redeem(@receipt) + @body = redeem(@receipt) end end end diff --git a/actionpack/lib/action_view/body_parts/threaded.rb b/actionpack/lib/action_view/body_parts/threaded.rb index 34800bf9c7..a2347a2f0e 100644 --- a/actionpack/lib/action_view/body_parts/threaded.rb +++ b/actionpack/lib/action_view/body_parts/threaded.rb @@ -4,11 +4,22 @@ module ActionView module BodyParts class Threaded < Future def initialize(concurrent = false, &block) - super(&block) + @block = block + @parts = [] concurrent ? start : work end protected + def work + @block.call(@parts) + end + + def body + str = '' + @parts.each { |part| str << part.to_s } + str + end + def start @worker = Thread.new { work } end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 7418f4a716..4555a6b015 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -47,7 +47,7 @@ class QueuedPartTest < ActionController::TestCase end protected - def submit(job) + def enqueue(job) job.reverse end @@ -114,12 +114,11 @@ class ThreadedPartTest < ActionController::TestCase def test_concurrent_threaded_parts get :index - before = Time.now.to_i - thread_ids = @response.body.split('-').map { |part| part.split('::').first.to_i } - elapsed = Time.now.to_i - before - - assert_equal thread_ids.size, thread_ids.uniq.size - assert elapsed < 1.1 + elapsed = Benchmark.ms do + thread_ids = @response.body.split('-').map { |part| part.split('::').first.to_i } + assert_equal thread_ids.size, thread_ids.uniq.size + end + assert (elapsed - 1000).abs < 100, elapsed end end @@ -142,7 +141,7 @@ class OpenUriPartTest < ActionController::TestCase def render_url(url) url = URI.parse(url) - def url.read; path end + def url.read; sleep 1; path end response.template.punctuate_body! OpenUriPart.new(url) end end @@ -155,6 +154,6 @@ class OpenUriPartTest < ActionController::TestCase elapsed = Benchmark.ms do assert_equal '/foo/bar/baz', @response.body end - assert elapsed < 1.1 + assert (elapsed - 1000).abs < 100, elapsed end end -- cgit v1.2.3 From 2f998fc81fd3525e4f19ba55937ee423c4b71856 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 03:23:13 -0700 Subject: Extract output buffer test --- actionpack/test/template/body_parts_test.rb | 34 ------------------------- actionpack/test/template/output_buffer_test.rb | 35 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 actionpack/test/template/output_buffer_test.rb (limited to 'actionpack') diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 4555a6b015..aece24635c 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -2,40 +2,6 @@ require 'abstract_unit' require 'action_view/body_parts/queued' require 'action_view/body_parts/threaded' -class OutputBufferTest < ActionController::TestCase - class TestController < ActionController::Base - def index - render :text => 'foo' - end - end - - tests TestController - - def test_flush_output_buffer - # Start with the default body parts - get :index - assert_equal ['foo'], @response.body_parts - assert_nil @response.template.output_buffer - - # Nil output buffer is skipped - @response.template.flush_output_buffer - assert_nil @response.template.output_buffer - assert_equal ['foo'], @response.body_parts - - # Empty output buffer is skipped - @response.template.output_buffer = '' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer - assert_equal ['foo'], @response.body_parts - - # Flushing appends the output buffer to the body parts - @response.template.output_buffer = 'bar' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer - assert_equal ['foo', 'bar'], @response.body_parts - end -end - class QueuedPartTest < ActionController::TestCase class EdgeSideInclude < ActionView::BodyParts::Queued diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb new file mode 100644 index 0000000000..6d8eab63dc --- /dev/null +++ b/actionpack/test/template/output_buffer_test.rb @@ -0,0 +1,35 @@ +require 'abstract_unit' + +class OutputBufferTest < ActionController::TestCase + class TestController < ActionController::Base + def index + render :text => 'foo' + end + end + + tests TestController + + def test_flush_output_buffer + # Start with the default body parts + get :index + assert_equal ['foo'], @response.body_parts + assert_nil @response.template.output_buffer + + # Nil output buffer is skipped + @response.template.flush_output_buffer + assert_nil @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Empty output buffer is skipped + @response.template.output_buffer = '' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo'], @response.body_parts + + # Flushing appends the output buffer to the body parts + @response.template.output_buffer = 'bar' + @response.template.flush_output_buffer + assert_equal '', @response.template.output_buffer + assert_equal ['foo', 'bar'], @response.body_parts + end +end -- cgit v1.2.3 From eced3d8c55c1bbae6915d7c6523c341bc682509a Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 13 Mar 2009 17:13:10 -0500 Subject: Update rack to fix multipart uploads with an empty file [#1945 state:resolved] --- .../lib/action_controller/vendor/rack-1.0/rack.rb | 1 + .../vendor/rack-1.0/rack/chunked.rb | 49 ++++++++++++++++++++ .../action_controller/vendor/rack-1.0/rack/file.rb | 2 +- .../vendor/rack-1.0/rack/handler/cgi.rb | 4 ++ .../vendor/rack-1.0/rack/handler/fastcgi.rb | 3 ++ .../vendor/rack-1.0/rack/handler/lsws.rb | 5 +- .../vendor/rack-1.0/rack/handler/mongrel.rb | 4 +- .../vendor/rack-1.0/rack/handler/scgi.rb | 4 +- .../vendor/rack-1.0/rack/handler/thin.rb | 3 ++ .../vendor/rack-1.0/rack/handler/webrick.rb | 3 +- .../action_controller/vendor/rack-1.0/rack/lint.rb | 54 ++++++++-------------- .../vendor/rack-1.0/rack/urlmap.rb | 6 ++- .../vendor/rack-1.0/rack/utils.rb | 2 +- .../request/multipart_params_parsing_test.rb | 2 +- 14 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb index e3e20ed2a3..7fab1a7931 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb @@ -28,6 +28,7 @@ module Rack autoload :Builder, "rack/builder" autoload :Cascade, "rack/cascade" + autoload :Chunked, "rack/chunked" autoload :CommonLogger, "rack/commonlogger" autoload :ConditionalGet, "rack/conditionalget" autoload :ContentLength, "rack/content_length" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb new file mode 100644 index 0000000000..280d89dd65 --- /dev/null +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb @@ -0,0 +1,49 @@ +require 'rack/utils' + +module Rack + + # Middleware that applies chunked transfer encoding to response bodies + # when the response does not include a Content-Length header. + class Chunked + include Rack::Utils + + def initialize(app) + @app = app + end + + def call(env) + status, headers, body = @app.call(env) + headers = HeaderHash.new(headers) + + if env['HTTP_VERSION'] == 'HTTP/1.0' || + STATUS_WITH_NO_ENTITY_BODY.include?(status) || + headers['Content-Length'] || + headers['Transfer-Encoding'] + [status, headers.to_hash, body] + else + dup.chunk(status, headers, body) + end + end + + def chunk(status, headers, body) + @body = body + headers.delete('Content-Length') + headers['Transfer-Encoding'] = 'chunked' + [status, headers.to_hash, self] + end + + def each + term = "\r\n" + @body.each do |chunk| + size = bytesize(chunk) + next if size == 0 + yield [size.to_s(16), term, chunk, term].join + end + yield ["0", term, "", term].join + end + + def close + @body.close if @body.respond_to?(:close) + end + end +end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb index 7869227a36..fe62bd6b86 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb @@ -60,7 +60,7 @@ module Rack body = self else body = [F.read(@path)] - size = body.first.size + size = Utils.bytesize(body.first) end [200, { diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb index f2c976cf46..e38156c7f0 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb @@ -1,3 +1,5 @@ +require 'rack/content_length' + module Rack module Handler class CGI @@ -6,6 +8,8 @@ module Rack end def self.serve(app) + app = ContentLength.new(app) + env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb index f03e1615c9..6324c7d274 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb @@ -1,5 +1,6 @@ require 'fcgi' require 'socket' +require 'rack/content_length' module Rack module Handler @@ -29,6 +30,8 @@ module Rack end def self.serve(request, app) + app = Rack::ContentLength.new(app) + env = request.env env.delete "HTTP_CONTENT_LENGTH" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb index dfc79c204b..c65ba3ec8e 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb @@ -1,5 +1,6 @@ require 'lsapi' -#require 'cgi' +require 'rack/content_length' + module Rack module Handler class LSWS @@ -9,6 +10,8 @@ module Rack end end def self.serve(app) + app = Rack::ContentLength.new(app) + env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb index 178a1a8fe4..f0c0d58330 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb @@ -1,5 +1,7 @@ require 'mongrel' require 'stringio' +require 'rack/content_length' +require 'rack/chunked' module Rack module Handler @@ -33,7 +35,7 @@ module Rack end def initialize(app) - @app = app + @app = Rack::Chunked.new(Rack::ContentLength.new(app)) end def process(request, response) diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb index fd18a8359b..9495c66374 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb @@ -1,5 +1,7 @@ require 'scgi' require 'stringio' +require 'rack/content_length' +require 'rack/chunked' module Rack module Handler @@ -14,7 +16,7 @@ module Rack end def initialize(settings = {}) - @app = settings[:app] + @app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app])) @log = Object.new def @log.info(*args); end def @log.error(*args); end diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb index 7ad088b36a..3d4fedff75 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb @@ -1,9 +1,12 @@ require "thin" +require "rack/content_length" +require "rack/chunked" module Rack module Handler class Thin def self.run(app, options={}) + app = Rack::Chunked.new(Rack::ContentLength.new(app)) server = ::Thin::Server.new(options[:Host] || '0.0.0.0', options[:Port] || 8080, app) diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb index 138aae0ee9..829e7d6bf8 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb @@ -1,5 +1,6 @@ require 'webrick' require 'stringio' +require 'rack/content_length' module Rack module Handler @@ -14,7 +15,7 @@ module Rack def initialize(server, app) super server - @app = app + @app = Rack::ContentLength.new(app) end def service(req, res) diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb index ec4dac96f8..44a33ce36e 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb @@ -374,59 +374,43 @@ module Rack ## === The Content-Length def check_content_length(status, headers, env) - chunked_response = false - headers.each { |key, value| - if key.downcase == 'transfer-encoding' - chunked_response = value.downcase != 'identity' - end - } - headers.each { |key, value| if key.downcase == 'content-length' - ## There must be a Content-Length, except when the - ## +Status+ is 1xx, 204 or 304, in which case there must be none - ## given. + ## There must not be a Content-Length header when the + ## +Status+ is 1xx, 204 or 304. assert("Content-Length header found in #{status} response, not allowed") { not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i } - assert('Content-Length header should not be used if body is chunked') { - not chunked_response - } - bytes = 0 string_body = true - @body.each { |part| - unless part.kind_of?(String) - string_body = false - break - end + if @body.respond_to?(:to_ary) + @body.each { |part| + unless part.kind_of?(String) + string_body = false + break + end - bytes += Rack::Utils.bytesize(part) - } - - if env["REQUEST_METHOD"] == "HEAD" - assert("Response body was given for HEAD request, but should be empty") { - bytes == 0 + bytes += Rack::Utils.bytesize(part) } - else - if string_body - assert("Content-Length header was #{value}, but should be #{bytes}") { - value == bytes.to_s + + if env["REQUEST_METHOD"] == "HEAD" + assert("Response body was given for HEAD request, but should be empty") { + bytes == 0 } + else + if string_body + assert("Content-Length header was #{value}, but should be #{bytes}") { + value == bytes.to_s + } + end end end return end } - - if [ String, Array ].include?(@body.class) && !chunked_response - assert('No Content-Length header found') { - Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - end end ## === The Body diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb index eb1457a850..0ff32df181 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb @@ -12,7 +12,11 @@ module Rack # first, since they are most specific. class URLMap - def initialize(map) + def initialize(map = {}) + remap(map) + end + + def remap(map) @mapping = map.map { |location, app| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb index e86d4ccdcd..0a61bce707 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb @@ -372,7 +372,7 @@ module Rack data = body end - Utils.normalize_params(params, name, data) + Utils.normalize_params(params, name, data) unless data.nil? break if buf.empty? || content_length == -1 } diff --git a/actionpack/test/controller/request/multipart_params_parsing_test.rb b/actionpack/test/controller/request/multipart_params_parsing_test.rb index 054519d0d2..b812072ef4 100644 --- a/actionpack/test/controller/request/multipart_params_parsing_test.rb +++ b/actionpack/test/controller/request/multipart_params_parsing_test.rb @@ -103,7 +103,7 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest test "does not create tempfile if no file has been selected" do params = parse_multipart('none') - assert_equal %w(files submit-name), params.keys.sort + assert_equal %w(submit-name), params.keys.sort assert_equal 'Larry', params['submit-name'] assert_equal nil, params['files'] end -- cgit v1.2.3 From 5b025a1d119eaf09f5376209da212b76725747f8 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 13 Mar 2009 17:13:18 -0500 Subject: Revert 5b7527ca "Failing test for routes with member & requirement" [#2054 state:wontfix] --- actionpack/lib/action_controller/resources.rb | 7 +------ actionpack/test/controller/resources_test.rb | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index 0a89c4b3d5..5f71a105c8 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -670,12 +670,7 @@ module ActionController 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 "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id)) - 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 + else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements) end end end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 35f943737f..91066ea893 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -209,14 +209,6 @@ class ResourcesTest < ActionController::TestCase end end - def test_with_member_action_and_requirement - expected_options = {:controller => 'messages', :action => 'mark', :id => '1.1.1'} - - with_restful_routing(:messages, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}, :member => { :mark => :get }) do - assert_recognizes(expected_options, :path => 'messages/1.1.1/mark', :method => :get) - end - end - def test_member_when_override_paths_for_default_restful_actions_with [:put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method }, :path_names => {:new => 'nuevo'} do -- cgit v1.2.3 From 4a7b11d5d857a0f5ce6eb8af7a6dfcb94f31fcfa Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 13 Mar 2009 18:49:53 -0700 Subject: Less ceremony --- .../lib/action_view/body_parts/concurrent_block.rb | 25 +++++++++ actionpack/lib/action_view/body_parts/future.rb | 10 ---- actionpack/lib/action_view/body_parts/queued.rb | 18 ------- actionpack/lib/action_view/body_parts/threaded.rb | 32 ------------ actionpack/test/template/body_parts_test.rb | 61 ++++++++++++---------- 5 files changed, 59 insertions(+), 87 deletions(-) create mode 100644 actionpack/lib/action_view/body_parts/concurrent_block.rb delete mode 100644 actionpack/lib/action_view/body_parts/future.rb delete mode 100644 actionpack/lib/action_view/body_parts/queued.rb delete mode 100644 actionpack/lib/action_view/body_parts/threaded.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/body_parts/concurrent_block.rb b/actionpack/lib/action_view/body_parts/concurrent_block.rb new file mode 100644 index 0000000000..28a3a3bf4d --- /dev/null +++ b/actionpack/lib/action_view/body_parts/concurrent_block.rb @@ -0,0 +1,25 @@ +module ActionView + module BodyParts + class ConcurrentBlock + def initialize(&block) + @block = block + @body = [] + start + end + + def to_s + finish + @body.join + end + + protected + def start + @worker = Thread.new { @block.call(@body) } + end + + def finish + @worker.join if @worker && @worker.alive? + end + end + end +end diff --git a/actionpack/lib/action_view/body_parts/future.rb b/actionpack/lib/action_view/body_parts/future.rb deleted file mode 100644 index f03c2b395b..0000000000 --- a/actionpack/lib/action_view/body_parts/future.rb +++ /dev/null @@ -1,10 +0,0 @@ -module ActionView - module BodyParts - class Future - def to_s - finish - body - end - end - end -end diff --git a/actionpack/lib/action_view/body_parts/queued.rb b/actionpack/lib/action_view/body_parts/queued.rb deleted file mode 100644 index 618999742b..0000000000 --- a/actionpack/lib/action_view/body_parts/queued.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'action_view/body_parts/future' - -module ActionView - module BodyParts - class Queued < Future - attr_reader :body - - def initialize(job) - @receipt = enqueue(job) - end - - protected - def finish - @body = redeem(@receipt) - end - end - end -end diff --git a/actionpack/lib/action_view/body_parts/threaded.rb b/actionpack/lib/action_view/body_parts/threaded.rb deleted file mode 100644 index a2347a2f0e..0000000000 --- a/actionpack/lib/action_view/body_parts/threaded.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'action_view/body_parts/future' - -module ActionView - module BodyParts - class Threaded < Future - def initialize(concurrent = false, &block) - @block = block - @parts = [] - concurrent ? start : work - end - - protected - def work - @block.call(@parts) - end - - def body - str = '' - @parts.each { |part| str << part.to_s } - str - end - - def start - @worker = Thread.new { work } - end - - def finish - @worker.join if @worker && @worker.alive? - end - end - end -end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index aece24635c..369756cbf5 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -1,37 +1,44 @@ require 'abstract_unit' -require 'action_view/body_parts/queued' -require 'action_view/body_parts/threaded' +require 'action_view/body_parts/concurrent_block' - -class QueuedPartTest < ActionController::TestCase - class EdgeSideInclude < ActionView::BodyParts::Queued - QUEUE_REDEMPTION_URL = 'http://queue/jobs/%s' +class BodyPartTest < ActionController::TestCase + module EdgeSideInclude + QUEUE_REDEMPTION_URL = 'http://render.farm/renderings/%s' ESI_INCLUDE_TAG = '' def self.redemption_tag(receipt) ESI_INCLUDE_TAG % QUEUE_REDEMPTION_URL % receipt end - protected - def enqueue(job) - job.reverse + class BodyPart + def initialize(rendering) + @receipt = enqueue(rendering) end - def redeem(receipt) - self.class.redemption_tag(receipt) + def to_s + EdgeSideInclude.redemption_tag(@receipt) end + + protected + # Pretend we sent this rendering off for processing. + def enqueue(rendering) + rendering.object_id.to_s + end + end end class TestController < ActionController::Base + RENDERINGS = [Object.new, Object.new, Object.new] + def index - edge_side_include 'foo' - edge_side_include 'bar' - edge_side_include 'baz' + RENDERINGS.each do |rendering| + edge_side_include rendering + end @performed_render = true end - def edge_side_include(job) - response.template.punctuate_body! EdgeSideInclude.new(job) + def edge_side_include(rendering) + response.template.punctuate_body! EdgeSideInclude::BodyPart.new(rendering) end end @@ -39,20 +46,20 @@ class QueuedPartTest < ActionController::TestCase def test_queued_parts get :index - expected = %w(oof rab zab).map { |receipt| EdgeSideInclude.redemption_tag(receipt) }.join + expected = TestController::RENDERINGS.map { |rendering| EdgeSideInclude.redemption_tag(rendering.object_id) }.join assert_equal expected, @response.body end end -class ThreadedPartTest < ActionController::TestCase +class ConcurrentBlockPartTest < ActionController::TestCase class TestController < ActionController::Base def index append_thread_id = lambda do |parts| parts << Thread.current.object_id parts << '::' parts << Time.now.to_i - sleep 1 + sleep 0.1 end future_render &append_thread_id @@ -62,16 +69,16 @@ class ThreadedPartTest < ActionController::TestCase response.body_parts << '-' future_render do |parts| - parts << ActionView::BodyParts::Threaded.new(true, &append_thread_id) + parts << ActionView::BodyParts::ConcurrentBlock.new(&append_thread_id) parts << '-' - parts << ActionView::BodyParts::Threaded.new(true, &append_thread_id) + parts << ActionView::BodyParts::ConcurrentBlock.new(&append_thread_id) end @performed_render = true end def future_render(&block) - response.template.punctuate_body! ActionView::BodyParts::Threaded.new(true, &block) + response.template.punctuate_body! ActionView::BodyParts::ConcurrentBlock.new(&block) end end @@ -84,16 +91,16 @@ class ThreadedPartTest < ActionController::TestCase thread_ids = @response.body.split('-').map { |part| part.split('::').first.to_i } assert_equal thread_ids.size, thread_ids.uniq.size end - assert (elapsed - 1000).abs < 100, elapsed + assert (elapsed - 100).abs < 10, elapsed end end class OpenUriPartTest < ActionController::TestCase - class OpenUriPart < ActionView::BodyParts::Threaded + class OpenUriPart < ActionView::BodyParts::ConcurrentBlock def initialize(url) url = URI::Generic === url ? url : URI.parse(url) - super(true) { |parts| parts << url.read } + super() { |body| body << url.read } end end @@ -107,7 +114,7 @@ class OpenUriPartTest < ActionController::TestCase def render_url(url) url = URI.parse(url) - def url.read; sleep 1; path end + def url.read; sleep 0.1; path end response.template.punctuate_body! OpenUriPart.new(url) end end @@ -120,6 +127,6 @@ class OpenUriPartTest < ActionController::TestCase elapsed = Benchmark.ms do assert_equal '/foo/bar/baz', @response.body end - assert (elapsed - 1000).abs < 100, elapsed + assert (elapsed - 100).abs < 10, elapsed end end -- cgit v1.2.3 From 07710fd3e0c5c84521b7929738ba33cea99bc108 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Sat, 14 Mar 2009 10:06:00 -0500 Subject: Fix requirements for additional member/collection routes [#2054 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_controller/resources.rb | 11 ++++++----- actionpack/test/controller/resources_test.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index 5f71a105c8..86abb7b2f4 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -630,7 +630,7 @@ module ActionController action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash) action_path ||= Base.resources_path_names[action] || action - map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m) + map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m, { :force_id => true }) end end end @@ -641,9 +641,9 @@ module ActionController map_resource_routes(map, resource, :destroy, resource.member_path, route_path) end - def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil) + def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil, resource_options = {} ) if resource.has_action?(action) - action_options = action_options_for(action, resource, method) + action_options = action_options_for(action, resource, method, resource_options) formatted_route_path = "#{route_path}.:format" if route_name && @set.named_routes[route_name.to_sym].nil? @@ -660,9 +660,10 @@ module ActionController end end - def action_options_for(action, resource, method = nil) + def action_options_for(action, resource, method = nil, resource_options = {}) default_options = { :action => action.to_s } require_id = !resource.kind_of?(SingletonResource) + force_id = resource_options[:force_id] && !resource.kind_of?(SingletonResource) case default_options[:action] when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements) @@ -670,7 +671,7 @@ module ActionController 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 "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 default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(force_id)) end end end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 91066ea893..c807e71cd7 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -175,6 +175,24 @@ class ResourcesTest < ActionController::TestCase end end + def test_with_collection_actions_and_name_prefix_and_member_action_with_same_name + actions = { 'a' => :get } + + with_restful_routing :messages, :path_prefix => '/threads/:thread_id', :name_prefix => "thread_", :collection => actions, :member => actions do + assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.each do |action, method| + assert_recognizes(options.merge(:action => action), :path => "/threads/1/messages/#{action}", :method => method) + end + end + + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.keys.each do |action| + assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action + end + end + end + end + def test_with_collection_action_and_name_prefix_and_formatted actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } @@ -209,6 +227,14 @@ class ResourcesTest < ActionController::TestCase end end + def test_with_member_action_and_requirement + expected_options = {:controller => 'messages', :action => 'mark', :id => '1.1.1'} + + with_restful_routing(:messages, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}, :member => { :mark => :get }) do + assert_recognizes(expected_options, :path => 'messages/1.1.1/mark', :method => :get) + end + end + def test_member_when_override_paths_for_default_restful_actions_with [:put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method }, :path_names => {:new => 'nuevo'} do -- cgit v1.2.3 From 112056333f6ad2492a37b7eb9d647ecd23980592 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 14 Mar 2009 10:37:20 -0500 Subject: Add Rack version to Rails info --- actionpack/lib/action_controller/vendor/rack-1.0/rack.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb index 7fab1a7931..6c73d64612 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb @@ -3,7 +3,7 @@ # Rack is freely distributable under the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. -$:.unshift(File.expand_path(File.dirname(__FILE__))) +$: << File.expand_path(File.dirname(__FILE__)) # The Rack main module, serving as a namespace for all core Rack @@ -23,7 +23,7 @@ module Rack # Return the Rack release as a dotted string. def self.release - "0.4" + "1.0 bundled" end autoload :Builder, "rack/builder" -- cgit v1.2.3 From 7706b57034e91820cf83445aede57c54ab66ac2d Mon Sep 17 00:00:00 2001 From: misfo Date: Sat, 14 Mar 2009 10:42:02 -0500 Subject: allowed render :file to take Pathnames [#2220 state:resolved] Signed-off-by: Joshua Peek --- actionpack/lib/action_view/template.rb | 2 +- actionpack/test/controller/render_test.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 0dd3a7e619..c339c8a554 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -218,7 +218,7 @@ module ActionView #:nodoc: # Returns file split into an array # [base_path, name, locale, format, extension] def split(file) - if m = file.match(/^(.*\/)?([^\.]+)\.(.*)$/) + if m = file.to_s.match(/^(.*\/)?([^\.]+)\.(.*)$/) base_path = m[1] name = m[2] extensions = m[3] diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index af623395f0..a52931565d 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -157,6 +157,11 @@ class TestController < ActionController::Base render :file => 'test/dot.directory/render_file_with_ivar' end + def render_file_using_pathname + @secret = 'in the sauce' + render :file => Pathname.new(File.dirname(__FILE__)).join('..', 'fixtures', 'test', 'dot.directory', 'render_file_with_ivar.erb') + end + def render_file_from_template @secret = 'in the sauce' @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')) @@ -861,6 +866,11 @@ class RenderTest < ActionController::TestCase assert_equal "The secret is in the sauce\n", @response.body end + def test_render_file_using_pathname + get :render_file_using_pathname + assert_equal "The secret is in the sauce\n", @response.body + end + def test_render_file_with_locals get :render_file_with_locals assert_equal "The secret is in the sauce\n", @response.body -- cgit v1.2.3 From 73fc42cc0b5e94541480032c2941a50edd4080c2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 15 Mar 2009 22:06:50 -0500 Subject: Prepare for final 2.3 release --- actionpack/CHANGELOG | 5 +---- actionpack/Rakefile | 2 +- actionpack/lib/action_pack/version.rb | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 90232d8c2d..8c9486cc63 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,4 +1,4 @@ -*2.3.1 [RC2] (March 5, 2009)* +*2.3.2 [Final] (March 15, 2009)* * Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #") [DHH] @@ -14,9 +14,6 @@ * Added localized rescue template when I18n.locale is set (ex: public/404.da.html) #1835 [José Valim] - -*2.3.0 [RC1] (February 1st, 2009)* - * Make the form_for and fields_for helpers support the new Active Record nested update options. #1202 [Eloy Duran] <% form_for @person do |person_form| %> diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 2c0c28b755..6cacdf3c6e 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -80,7 +80,7 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.requirements << 'none' - s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'action_controller' diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index f03a2a7605..e0aa2a5f2f 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -2,7 +2,7 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 1 + TINY = 2 STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 39ff550fa88da9a22d8c21ca872f5e4d0d83f8d4 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 22:54:26 -0500 Subject: Ensure our bundled version of rack is at the front of the load path --- actionpack/lib/action_controller/vendor/rack-1.0/rack.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb index 6c73d64612..6349b95094 100644 --- a/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb +++ b/actionpack/lib/action_controller/vendor/rack-1.0/rack.rb @@ -3,7 +3,7 @@ # Rack is freely distributable under the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. -$: << File.expand_path(File.dirname(__FILE__)) +$:.unshift(File.expand_path(File.dirname(__FILE__))) # The Rack main module, serving as a namespace for all core Rack -- cgit v1.2.3 From 367049cae69ec535e7105b35f4877167adca1188 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 23:17:31 -0500 Subject: Fix brittle Time.now mock --- .../test/controller/session/cookie_store_test.rb | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/session/cookie_store_test.rb b/actionpack/test/controller/session/cookie_store_test.rb index 9c93ca6539..c406188972 100644 --- a/actionpack/test/controller/session/cookie_store_test.rb +++ b/actionpack/test/controller/session/cookie_store_test.rb @@ -199,29 +199,17 @@ class CookieStoreTest < ActionController::IntegrationTest with_test_route_set do # First request accesses the session - time = Time.local(2008, 4, 24) - Time.stubs(:now).returns(time) - expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT") - cookies[SessionKey] = SignedBar get '/set_session_value' assert_response :success + cookie = headers['Set-Cookie'] - cookie_body = response.body - assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", - headers['Set-Cookie'] - - # Second request does not access the session - time = Time.local(2008, 4, 25) - Time.stubs(:now).returns(time) - expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT") - + # Second request does not access the session so the + # expires header should not be changed get '/no_session_access' assert_response :success - - assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly", - headers['Set-Cookie'] + assert_equal cookie, headers['Set-Cookie'] end end -- cgit v1.2.3 From d0e5417861fad15e9e493a1843f8b54fb7a993ec Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 23:25:12 -0500 Subject: update rack fixture to be ruby 1.9 compat --- actionpack/test/controller/integration_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index b3f40fbe95..43d2307d34 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' class SessionTest < Test::Unit::TestCase StubApp = lambda { |env| - [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, "Hello, World!"] + [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, ["Hello, World!"]] } def setup -- cgit v1.2.3 From 46c12fdcb6fb11ae62786eeafd0d1784343b3daa Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 23:29:00 -0500 Subject: ruby 1.9 compat: Pathname doesn't support =~ --- actionpack/lib/action_view/paths.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 37d96b2f82..8cc3fe291c 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -61,7 +61,7 @@ module ActionView #:nodoc: end end - return Template.new(original_template_path, original_template_path =~ /\A\// ? "" : ".") if File.file?(original_template_path) + return Template.new(original_template_path, original_template_path.to_s =~ /\A\// ? "" : ".") if File.file?(original_template_path) raise MissingTemplate.new(self, original_template_path, format) end -- cgit v1.2.3 From 0706de4301bbf12a4c369bd4776ad58affee9ad4 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 23:41:47 -0500 Subject: Better error message to try to figure out why the CI build is failing --- actionpack/test/controller/session/cookie_store_test.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/session/cookie_store_test.rb b/actionpack/test/controller/session/cookie_store_test.rb index c406188972..48a961ca34 100644 --- a/actionpack/test/controller/session/cookie_store_test.rb +++ b/actionpack/test/controller/session/cookie_store_test.rb @@ -209,7 +209,8 @@ class CookieStoreTest < ActionController::IntegrationTest # expires header should not be changed get '/no_session_access' assert_response :success - assert_equal cookie, headers['Set-Cookie'] + assert_equal cookie, headers['Set-Cookie'], + "#{unmarshal_session(cookie).inspect} expected but was #{unmarshal_session(headers['Set-Cookie']).inspect}" end end @@ -224,4 +225,13 @@ class CookieStoreTest < ActionController::IntegrationTest yield end end + + def unmarshal_session(cookie_string) + session = Rack::Utils.parse_query(cookie_string, ';,').inject({}) {|h,(k,v)| + h[k] = Array === v ? v.first : v + h + }[SessionKey] + verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1') + verifier.verify(session) + end end -- cgit v1.2.3 From 4185a4a5f5e53b55c9ba3757a837d33fb91f4091 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 15 Mar 2009 23:48:07 -0500 Subject: update rack fixture to be ruby 1.9 compat --- actionpack/test/controller/integration_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 43d2307d34..e39a934c24 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -389,9 +389,9 @@ class MetalTest < ActionController::IntegrationTest class Poller def self.call(env) if env["PATH_INFO"] =~ /^\/success/ - [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, "Hello World!"] + [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, ["Hello World!"]] else - [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, ''] + [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] end end end -- cgit v1.2.3 From 18eb80ccc7e932f9a6c00462ceaeea648631b120 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 16 Mar 2009 11:28:36 +0000 Subject: Merge docrails --- actionpack/lib/action_controller/integration.rb | 2 +- actionpack/lib/action_view/helpers/date_helper.rb | 4 ++-- actionpack/lib/action_view/helpers/number_helper.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb index 1c05ab0bf6..26b695570b 100644 --- a/actionpack/lib/action_controller/integration.rb +++ b/actionpack/lib/action_controller/integration.rb @@ -5,7 +5,7 @@ require 'active_support/test_case' module ActionController module Integration #:nodoc: # An integration Session instance represents a set of requests and responses - # performed sequentially by some virtual user. Becase you can instantiate + # performed sequentially by some virtual user. Because you can instantiate # multiple sessions and run them side-by-side, you can also mimic (to some # limited extent) multiple simultaneous users interacting with your system. # diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index b7ef1fb90d..c74909a360 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -876,8 +876,8 @@ module ActionView input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '') end - # Given an ordering of datetime components, create the selection html - # and join them with their appropriate seperators + # Given an ordering of datetime components, create the selection HTML + # and join them with their appropriate separators. def build_selects_from_types(order) select = '' order.reverse.each do |type| diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 539f43c6e3..dea958deaf 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -140,7 +140,7 @@ module ActionView # number_with_delimiter(12345678) # => 12,345,678 # number_with_delimiter(12345678.05) # => 12,345,678.05 # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678 - # number_with_delimiter(12345678, :seperator => ",") # => 12,345,678 + # number_with_delimiter(12345678, :separator => ",") # => 12,345,678 # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",") # # => 98 765 432,98 # -- cgit v1.2.3 From 70e3dfb2e9f94396eb6525d13f9adccd3e845c3d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 16 Mar 2009 12:09:34 -0700 Subject: Pare down unit test --- actionpack/test/template/body_parts_test.rb | 42 +++++------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 369756cbf5..209f6ec1ff 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -1,57 +1,27 @@ require 'abstract_unit' require 'action_view/body_parts/concurrent_block' -class BodyPartTest < ActionController::TestCase - module EdgeSideInclude - QUEUE_REDEMPTION_URL = 'http://render.farm/renderings/%s' - ESI_INCLUDE_TAG = '' - - def self.redemption_tag(receipt) - ESI_INCLUDE_TAG % QUEUE_REDEMPTION_URL % receipt - end - - class BodyPart - def initialize(rendering) - @receipt = enqueue(rendering) - end - - def to_s - EdgeSideInclude.redemption_tag(@receipt) - end - - protected - # Pretend we sent this rendering off for processing. - def enqueue(rendering) - rendering.object_id.to_s - end - end - end +class BodyPartsTest < ActionController::TestCase + RENDERINGS = [Object.new, Object.new, Object.new] class TestController < ActionController::Base - RENDERINGS = [Object.new, Object.new, Object.new] - def index RENDERINGS.each do |rendering| - edge_side_include rendering + response.template.punctuate_body! rendering end @performed_render = true end - - def edge_side_include(rendering) - response.template.punctuate_body! EdgeSideInclude::BodyPart.new(rendering) - end end tests TestController - def test_queued_parts + def test_body_parts get :index - expected = TestController::RENDERINGS.map { |rendering| EdgeSideInclude.redemption_tag(rendering.object_id) }.join - assert_equal expected, @response.body + assert_equal RENDERINGS, @response.body_parts + assert_equal RENDERINGS.join, @response.body end end - class ConcurrentBlockPartTest < ActionController::TestCase class TestController < ActionController::Base def index -- cgit v1.2.3 From d36df5e7a8a2791bb890afa0c11b8f3985293c21 Mon Sep 17 00:00:00 2001 From: Clemens Kofler Date: Tue, 17 Mar 2009 14:46:19 +0100 Subject: Hidden field with check box goes first. --- actionpack/lib/action_view/helpers/form_helper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index a589bcba2a..93b8ae687f 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -657,17 +657,17 @@ module ActionView # ==== Examples # # Let's say that @post.validated? is 1: # check_box("post", "validated") - # # => - # # + # # => + # # # # # Let's say that @puppy.gooddog is "no": # check_box("puppy", "gooddog", {}, "yes", "no") - # # => - # # + # # => + # # # # check_box("eula", "accepted", { :class => 'eula_check' }, "yes", "no") - # # => - # # + # # => + # # # def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") InstanceTag.new(object_name, method, self, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) -- cgit v1.2.3 From a8bf6fa30882cdbb2c84b1840f3bd3f10894af3d Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 17 Mar 2009 18:50:50 +0100 Subject: update explanation of check box generation according to f400209 --- actionpack/lib/action_view/helpers/form_helper.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 93b8ae687f..4e1927a897 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -628,7 +628,7 @@ module ActionView # # The HTML specification says unchecked check boxes are not successful, and # thus web browsers do not send them. Unfortunately this introduces a gotcha: - # if an Invoice model has a +paid+ flag, and in the form that edits a paid + # if an +Invoice+ model has a +paid+ flag, and in the form that edits a paid # invoice the user unchecks its check box, no +paid+ parameter is sent. So, # any mass-assignment idiom like # @@ -636,12 +636,15 @@ module ActionView # # wouldn't update the flag. # - # To prevent this the helper generates a hidden field with the same name as - # the checkbox after the very check box. So, the client either sends only the - # hidden field (representing the check box is unchecked), or both fields. - # Since the HTML specification says key/value pairs have to be sent in the - # same order they appear in the form and Rails parameters extraction always - # gets the first occurrence of any given key, that works in ordinary forms. + # To prevent this the helper generates an auxiliary hidden field before + # the very check box. The hidden field has the same name and its + # attributes mimick an unchecked check box. + # + # This way, the client either sends only the hidden field (representing + # the check box is unchecked), or both fields. Since the HTML specification + # says key/value pairs have to be sent in the same order they appear in the + # form, and parameters extraction gets the last occurrence of any repeated + # key in the query string, that works for ordinary forms. # # Unfortunately that workaround does not work when the check box goes # within an array-like parameter, as in -- cgit v1.2.3 From 168e3958df38b7f6738d60f2510a2e6d1ebcc9fb Mon Sep 17 00:00:00 2001 From: Giles Bowkett Date: Tue, 17 Mar 2009 12:41:15 -0700 Subject: this page referred to an :href_options keyword hash, in fact the correct keyword (the one the code responds to) is :html --- actionpack/lib/action_view/helpers/text_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 48bf4717ad..573b99b96e 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -324,7 +324,7 @@ module ActionView # Turns all URLs and e-mail addresses into clickable links. The :link option # will limit what should be linked. You can add HTML attributes to the links using - # :href_options. Possible values for :link are :all (default), + # :html. Possible values for :link are :all (default), # :email_addresses, and :urls. If a block is given, each URL and # e-mail address is yielded and the result is used as the link text. # @@ -341,7 +341,7 @@ module ActionView # # => "Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com" # # post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com." - # auto_link(post_body, :href_options => { :target => '_blank' }) do |text| + # auto_link(post_body, :html => { :target => '_blank' }) do |text| # truncate(text, 15) # end # # => "Welcome to my new blog at http://www.m.... @@ -359,7 +359,7 @@ module ActionView # auto_link(post_body, :all, :target => "_blank") # => Once upon\na time # # => "Welcome to my new blog at http://www.myblog.com. # Please e-mail me at me@email.com." - def auto_link(text, *args, &block)#link = :all, href_options = {}, &block) + def auto_link(text, *args, &block)#link = :all, html = {}, &block) return '' if text.blank? options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter -- cgit v1.2.3 From e8501a15a84f4c0d894273b0decedf64cce66c76 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 17 Mar 2009 21:01:50 +0100 Subject: clarifies a bit more what's the issue with check boxes and arrays of parameters --- actionpack/lib/action_view/helpers/form_helper.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 4e1927a897..a59829b23f 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -655,7 +655,11 @@ module ActionView # <% end %> # # because parameter name repetition is precisely what Rails seeks to distinguish - # the elements of the array. + # the elements of the array. For each item with a checked check box you + # get an extra ghost item with only that attribute, assigned to "0". + # + # In that case it is preferable to either use +check_box_tag+ or to use + # hashes instead of arrays. # # ==== Examples # # Let's say that @post.validated? is 1: -- cgit v1.2.3 From 0d5b50ee3a6d65471f311980b9b6e49fe4b4a021 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 19 Mar 2009 03:30:01 -0700 Subject: pluginize concurrent block body part --- actionpack/lib/action_view/base.rb | 4 +- .../lib/action_view/body_parts/concurrent_block.rb | 25 ------- actionpack/test/template/body_parts_test.rb | 80 ---------------------- 3 files changed, 2 insertions(+), 107 deletions(-) delete mode 100644 actionpack/lib/action_view/body_parts/concurrent_block.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 3bbd2ca530..9c0134e7f7 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -288,12 +288,12 @@ module ActionView #:nodoc: # Access the current template being rendered. # Returns a ActionView::Template object. def template - Thread.current[:_current_render] + @_current_render end def template=(template) #:nodoc: @_first_render ||= template - Thread.current[:_current_render] = template + @_current_render = template end def with_template(current_template) diff --git a/actionpack/lib/action_view/body_parts/concurrent_block.rb b/actionpack/lib/action_view/body_parts/concurrent_block.rb deleted file mode 100644 index 28a3a3bf4d..0000000000 --- a/actionpack/lib/action_view/body_parts/concurrent_block.rb +++ /dev/null @@ -1,25 +0,0 @@ -module ActionView - module BodyParts - class ConcurrentBlock - def initialize(&block) - @block = block - @body = [] - start - end - - def to_s - finish - @body.join - end - - protected - def start - @worker = Thread.new { @block.call(@body) } - end - - def finish - @worker.join if @worker && @worker.alive? - end - end - end -end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 209f6ec1ff..4c82b75cdc 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'action_view/body_parts/concurrent_block' class BodyPartsTest < ActionController::TestCase RENDERINGS = [Object.new, Object.new, Object.new] @@ -21,82 +20,3 @@ class BodyPartsTest < ActionController::TestCase assert_equal RENDERINGS.join, @response.body end end - -class ConcurrentBlockPartTest < ActionController::TestCase - class TestController < ActionController::Base - def index - append_thread_id = lambda do |parts| - parts << Thread.current.object_id - parts << '::' - parts << Time.now.to_i - sleep 0.1 - end - - future_render &append_thread_id - response.body_parts << '-' - - future_render &append_thread_id - response.body_parts << '-' - - future_render do |parts| - parts << ActionView::BodyParts::ConcurrentBlock.new(&append_thread_id) - parts << '-' - parts << ActionView::BodyParts::ConcurrentBlock.new(&append_thread_id) - end - - @performed_render = true - end - - def future_render(&block) - response.template.punctuate_body! ActionView::BodyParts::ConcurrentBlock.new(&block) - end - end - - tests TestController - - def test_concurrent_threaded_parts - get :index - - elapsed = Benchmark.ms do - thread_ids = @response.body.split('-').map { |part| part.split('::').first.to_i } - assert_equal thread_ids.size, thread_ids.uniq.size - end - assert (elapsed - 100).abs < 10, elapsed - end -end - - -class OpenUriPartTest < ActionController::TestCase - class OpenUriPart < ActionView::BodyParts::ConcurrentBlock - def initialize(url) - url = URI::Generic === url ? url : URI.parse(url) - super() { |body| body << url.read } - end - end - - class TestController < ActionController::Base - def index - render_url 'http://localhost/foo' - render_url 'http://localhost/bar' - render_url 'http://localhost/baz' - @performed_render = true - end - - def render_url(url) - url = URI.parse(url) - def url.read; sleep 0.1; path end - response.template.punctuate_body! OpenUriPart.new(url) - end - end - - tests TestController - - def test_concurrent_open_uri_parts - get :index - - elapsed = Benchmark.ms do - assert_equal '/foo/bar/baz', @response.body - end - assert (elapsed - 100).abs < 10, elapsed - end -end -- cgit v1.2.3 From f15f1ba285416c12a103716c86f87d593dd3f17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 25 Mar 2009 19:22:45 +0100 Subject: remove piece of UrlWriter documentation claiming that you can access named routes as its class methods This never worked: ActionController::UrlWriter.users_path --- actionpack/lib/action_controller/url_rewriter.rb | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/url_rewriter.rb index bb6cb437b7..16720b915b 100644 --- a/actionpack/lib/action_controller/url_rewriter.rb +++ b/actionpack/lib/action_controller/url_rewriter.rb @@ -68,29 +68,17 @@ module ActionController # This generates, among other things, the method users_path. 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 in two ways. - # - # The first way is to include ActionController::UrlWriter in your class: + # you can do that by including ActionController::UrlWriter in your class: # # class User < ActiveRecord::Base - # include ActionController::UrlWriter # !!! + # include ActionController::UrlWriter # - # def name=(value) - # write_attribute('name', value) - # write_attribute('base_uri', users_path) # !!! + # def base_uri + # user_path(self) # end # end # - # The second way is to access them through ActionController::UrlWriter. - # The autogenerated named routes methods are available as class methods: - # - # class User < ActiveRecord::Base - # def name=(value) - # write_attribute('name', value) - # path = ActionController::UrlWriter.users_path # !!! - # write_attribute('base_uri', path) # !!! - # end - # end + # User.find(1).base_uri # => "/users/1" module UrlWriter def self.included(base) #:nodoc: ActionController::Routing::Routes.install_helpers(base) -- cgit v1.2.3 From 4350e7fe2b9f9205a710888dc2bc5129f10ccd9e Mon Sep 17 00:00:00 2001 From: Jeffrey Hardy Date: Fri, 3 Apr 2009 04:02:56 -0400 Subject: Fix typo in comment: hide_actions -> hide_action --- actionpack/lib/action_controller/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index c6dd99e959..b24f0bbc26 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -408,7 +408,7 @@ module ActionController #:nodoc: # Return an array containing the names of public methods that have been marked hidden from the action processor. # By default, all methods defined in ActionController::Base and included modules are hidden. - # More methods can be hidden using hide_actions. + # More methods can be hidden using hide_action. def hidden_actions read_inheritable_attribute(:hidden_actions) || write_inheritable_attribute(:hidden_actions, []) end -- cgit v1.2.3