From 938243feb9ea177b84276821818c9eed66064340 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 19 Nov 2010 16:26:09 -0800 Subject: do not require ruby-debug automatically. please require it if you have declared it as a dependency --- actionpack/test/abstract_unit.rb | 8 -------- 1 file changed, 8 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 92597e40ff..60534a9746 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -36,14 +36,6 @@ require 'active_record' require 'action_controller/caching' require 'action_controller/caching/sweeping' -begin - require 'ruby-debug' - Debugger.settings[:autoeval] = true - Debugger.start -rescue LoadError - # Debugging disabled. `gem install ruby-debug` to enable. -end - require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late module Rails -- cgit v1.2.3 From d3f8765482133df14d355f1763d3df1c883d2689 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 20 Nov 2010 02:28:58 -0200 Subject: Avoid range object creation --- actionpack/lib/abstract_controller/rendering.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index ba31e2b1ea..91b75273fa 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -128,7 +128,7 @@ module AbstractController hash = {} variables = instance_variable_names variables -= protected_instance_variables if respond_to?(:protected_instance_variables) - variables.each { |name| hash[name.to_s[1..-1]] = instance_variable_get(name) } + variables.each { |name| hash[name.to_s[1, name.length]] = instance_variable_get(name) } hash end -- cgit v1.2.3 From 4f3b5b8ec1443f0a6150178ce06b1dc43377540e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 20 Nov 2010 02:46:55 -0200 Subject: Fix indentation --- .../lib/action_controller/metal/rendering.rb | 47 +++++++++++----------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index e524e546ad..14cc547dd0 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -20,36 +20,35 @@ module ActionController private - # Normalize arguments by catching blocks and setting them on :update. - def _normalize_args(action=nil, options={}, &blk) #:nodoc: - options = super - options[:update] = blk if block_given? - options - end - - # Normalize both text and status options. - def _normalize_options(options) #:nodoc: - if options.key?(:text) && options[:text].respond_to?(:to_text) - options[:text] = options[:text].to_text - end + # Normalize arguments by catching blocks and setting them on :update. + def _normalize_args(action=nil, options={}, &blk) #:nodoc: + options = super + options[:update] = blk if block_given? + options + end - if options[:status] - options[:status] = Rack::Utils.status_code(options[:status]) - end + # Normalize both text and status options. + def _normalize_options(options) #:nodoc: + if options.key?(:text) && options[:text].respond_to?(:to_text) + options[:text] = options[:text].to_text + end - super + if options[:status] + options[:status] = Rack::Utils.status_code(options[:status]) end - # Process controller specific options, as status, content-type and location. - def _process_options(options) #:nodoc: - status, content_type, location = options.values_at(:status, :content_type, :location) + super + end - self.status = status if status - self.content_type = content_type if content_type - self.headers["Location"] = url_for(location) if location + # Process controller specific options, as status, content-type and location. + def _process_options(options) #:nodoc: + status, content_type, location = options.values_at(:status, :content_type, :location) - super - end + self.status = status if status + self.content_type = content_type if content_type + self.headers["Location"] = url_for(location) if location + super + end end end -- cgit v1.2.3 From d7db6a88734c3b666f4b85f266d223eff408b294 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 19 Nov 2010 18:29:33 +0100 Subject: class inheritable attributes is used no more! all internal use of class inheritable has been changed to class_attribute. class inheritable attributes has been deprecated. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_controller/test_case.rb | 6 ++++-- .../lib/action_controller/vendor/html-scanner/html/sanitizer.rb | 4 ++-- actionpack/lib/action_view/helpers/form_helper.rb | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 2b2f647d32..0f43527a56 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,6 +1,7 @@ require 'rack/session/abstract/id' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/to_query' +require 'active_support/core_ext/class/attribute' module ActionController module TemplateAssertions @@ -325,11 +326,11 @@ module ActionController def controller_class=(new_class) prepare_controller_class(new_class) if new_class - write_inheritable_attribute(:controller_class, new_class) + self._controller_class = new_class end def controller_class - if current_controller_class = read_inheritable_attribute(:controller_class) + if current_controller_class = self._controller_class current_controller_class else self.controller_class = determine_default_controller_class(name) @@ -442,6 +443,7 @@ module ActionController included do include ActionController::TemplateAssertions include ActionDispatch::Assertions + class_attribute :_controller_class setup :setup_controller_request_and_response end diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb index dceddb9b80..3e5d23b5c1 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb @@ -1,5 +1,5 @@ require 'set' -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' module HTML class Sanitizer @@ -60,7 +60,7 @@ module HTML class WhiteListSanitizer < Sanitizer [:protocol_separator, :uri_attributes, :allowed_attributes, :allowed_tags, :allowed_protocols, :bad_tags, :allowed_css_properties, :allowed_css_keywords, :shorthand_css_properties].each do |attr| - class_inheritable_accessor attr, :instance_writer => false + class_attribute attr, :instance_writer => false end # A regular expression of the valid characters used to separate protocols like diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 8c300ec745..ef5bbd8ae3 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -2,7 +2,7 @@ require 'cgi' require 'action_view/helpers/date_helper' require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' @@ -1117,7 +1117,7 @@ module ActionView class FormBuilder #:nodoc: # The methods which wrap a form helper call. - class_inheritable_accessor :field_helpers + class_attribute :field_helpers self.field_helpers = (FormHelper.instance_method_names - ['form_for']) attr_accessor :object_name, :object, :options -- cgit v1.2.3 From d5779efaf2375466ab557868e586b9dbd942abc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 20 Nov 2010 21:56:08 +0100 Subject: Ensure calling reset session twice does not raise errors. --- actionpack/test/activerecord/active_record_store_test.rb | 12 ++++++++++++ 1 file changed, 12 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 7c595d1b89..f0fb113860 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -23,6 +23,7 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest def call_reset_session session[:foo] reset_session + reset_session if params[:twice] session[:foo] = "baz" head :ok end @@ -94,6 +95,17 @@ class ActiveRecordStoreTest < ActionDispatch::IntegrationTest end end + def test_calling_reset_session_twice_does_not_raise_errors + with_test_route_set do + get '/call_reset_session', :twice => "true" + assert_response :success + + get '/get_session_value' + assert_response :success + assert_equal 'foo: "baz"', response.body + end + end + def test_setting_session_value_after_session_reset with_test_route_set do get '/set_session_value' -- cgit v1.2.3 From e65c23dc3e775be3162de25548f3192939ff3da3 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 21 Nov 2010 01:36:27 +0700 Subject: Mention the case that `render` will return nil if given `:collection` is nil or empty when rendering partial. --- actionpack/lib/action_view/partials.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 844c3e9572..cd3f130dc4 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -75,6 +75,11 @@ module ActionView # # <%= render :partial => "ad", :collection => @advertisements, :spacer_template => "ad_divider" %> # + # If the given :collection is nil or empty, render will return nil. This will allow you + # to specify a text which will displayed instead by using this form: + # + # <%= render(:partial => "ad", :collection => @advertisements) || "There's no ad to be displayed" %> + # # NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also # just keep domain objects, like Active Records, in there. # -- cgit v1.2.3 From 7d5b097357c3bbfb86c95271d1bdbe5148a01069 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sat, 20 Nov 2010 21:00:44 -0500 Subject: use_accept_header is no longer supported --- actionpack/lib/action_dispatch/http/mime_negotiation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index b959aa258e..5bb42cca3a 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -36,7 +36,7 @@ module ActionDispatch # # GET /posts/5.xml | request.format => Mime::XML # GET /posts/5.xhtml | request.format => Mime::HTML - # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of ActionController::Base.use_accept_header + # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first # def format(view_path = []) formats.first -- cgit v1.2.3 From 799a6fa047aa44ab4813dbf9328941b6d620e9b6 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 21 Nov 2010 10:25:23 +0100 Subject: realigns a series of hash arrows --- .../test/controller/new_base/render_template_test.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 9899036fe8..584f2d772c 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -4,16 +4,16 @@ module RenderTemplate class WithoutLayoutController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( - "test/basic.html.erb" => "Hello from basic.html.erb", - "shared.html.erb" => "Elastica", - "locals.html.erb" => "The secret is <%= secret %>", - "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", - "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>", - "with_implicit_raw.html.erb"=> "Hello <%== 'this is also raw' %>", - "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", - "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", - "test/final.json.erb" => "{ final: json }", - "test/with_error.html.erb" => "<%= idontexist %>" + "test/basic.html.erb" => "Hello from basic.html.erb", + "shared.html.erb" => "Elastica", + "locals.html.erb" => "The secret is <%= secret %>", + "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", + "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>", + "with_implicit_raw.html.erb" => "Hello <%== 'this is also raw' %>", + "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", + "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", + "test/final.json.erb" => "{ final: json }", + "test/with_error.html.erb" => "<%= idontexist %>" )] def index -- cgit v1.2.3 From 559c4292bcd132e87b50aa8f0807f2684cf234b8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 22 Nov 2010 14:07:28 -0200 Subject: Remove unneeded metaprogramming and method generation in favor of direct definition --- .../lib/action_controller/metal/renderers.rb | 34 +++++++--------------- 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index f9b226b7c9..41bcae75c9 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -15,30 +15,12 @@ module ActionController end module ClassMethods - def _write_render_options - renderers = _renderers.map do |name, value| - <<-RUBY_EVAL - if options.key?(:#{name}) - _process_options(options) - return _render_option_#{name}(options.delete(:#{name}), options) - end - RUBY_EVAL - end - - class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 - def _handle_render_options(options) - #{renderers.join} - end - RUBY_EVAL - end - def use_renderers(*args) new = _renderers.dup args.each do |key| new[key] = RENDERERS[key] end self._renderers = new.freeze - _write_render_options end alias use_renderer use_renderers end @@ -47,11 +29,20 @@ module ActionController _handle_render_options(options) || super end + def _handle_render_options(options) + _renderers.each do |name, value| + if options.key?(name.to_sym) + _process_options(options) + return send("_render_option_#{name}", options.delete(name.to_sym), options) + end + end + nil + end + RENDERERS = {} def self.add(key, &block) define_method("_render_option_#{key}", &block) RENDERERS[key] = block - All._write_render_options end module All @@ -61,13 +52,8 @@ module ActionController INCLUDED = [] included do self._renderers = RENDERERS - _write_render_options INCLUDED << self end - - def self._write_render_options - INCLUDED.each(&:_write_render_options) - end end add :json do |json, options| -- cgit v1.2.3 From 6e559168dc68a32bdbdf87e26ebfcb464be7e886 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 22 Nov 2010 18:47:47 -0200 Subject: There's no need for ternary op here --- actionpack/lib/action_controller/metal/mime_responds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index f7dd0dcb69..6fe1f4ece5 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -291,7 +291,7 @@ module ActionController #:nodoc: alias :all :any def custom(mime_type, &block) - mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) + mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type) @order << mime_type @responses[mime_type] ||= block end -- cgit v1.2.3 From c937ddb5cec87168c4eb0d6c3030f771e80c2e72 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 22 Nov 2010 19:00:05 -0200 Subject: Remove unused constant --- actionpack/lib/action_controller/metal/renderers.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index 41bcae75c9..67cf08445d 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -49,10 +49,8 @@ module ActionController extend ActiveSupport::Concern include Renderers - INCLUDED = [] included do self._renderers = RENDERERS - INCLUDED << self end end -- cgit v1.2.3 From 61950a4b05ce1b5640ac3f3720f9a3368ce95a29 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 02:21:57 -0500 Subject: current code ignores http header "Accept" if it has ....,*/* . MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible to a device to send request such that */* appear at the beginning of the "Accept" header. This patch ensures that "Accept" header is ignored for such cases too. Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_negotiation.rb | 2 +- actionpack/test/controller/mime_responds_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 5bb42cca3a..afce4d9651 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -48,7 +48,7 @@ module ActionDispatch @env["action_dispatch.request.formats"] ||= if parameters[:format] Array(Mime[parameters[:format]]) - elsif xhr? || (accept && accept !~ /,\s*\*\/\*/) + elsif xhr? || (accept && accept !~ /,\s*\*\/\*|\*\/\*,/) accepts else [Mime::HTML] diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index b6ce9f7d34..c68b3ab13f 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -216,6 +216,12 @@ class RespondToControllerTest < ActionController::TestCase assert_response 406 end + def test_json_or_yaml_with_leading_star_star + @request.accept = "*/*, application/json" + get :json_xml_or_html + assert_equal 'HTML', @response.body + end + def test_json_or_yaml xhr :get, :json_or_yaml assert_equal 'JSON', @response.body -- cgit v1.2.3 From f5fba917f8dbf45fcbf04b4b26cf54eb3b300057 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 08:53:47 -0500 Subject: failing test for #6022 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/controller/mime_responds_test.rb | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'actionpack') diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index c68b3ab13f..2de9b28e68 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -2,6 +2,14 @@ require 'abstract_unit' require 'controller/fake_models' require 'active_support/core_ext/hash/conversions' +class StarStarMimeController < ActionController::Base + layout nil + + def index + render + end +end + class RespondToController < ActionController::Base layout :set_layout @@ -160,6 +168,32 @@ class RespondToController < ActionController::Base end end +class StarStarMimeControllerTest < ActionController::TestCase + tests StarStarMimeController + + def setup; super; end + def teardown; super; end + + def test_javascript_with_format + @request.accept = "text/javascript" + get :index, :format => 'js' + assert_match "function addition(a,b){ return a+b; }", @response.body + end + + def test_javascript_with_no_format + @request.accept = "text/javascript" + get :index + assert_match "function addition(a,b){ return a+b; }", @response.body + end + + def test_javascript_with_no_format_only_star_star + @request.accept = "*/*" + get :index + assert_match "function addition(a,b){ return a+b; }", @response.body + end + +end + class RespondToControllerTest < ActionController::TestCase tests RespondToController -- cgit v1.2.3 From eb6ccc9953a5e952737174995b5230f0b2c56b1f Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 08:58:01 -0500 Subject: do not assume that there is no space between leading */* and comma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_negotiation.rb | 2 +- actionpack/test/controller/mime_responds_test.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index afce4d9651..2b401114f0 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -48,7 +48,7 @@ module ActionDispatch @env["action_dispatch.request.formats"] ||= if parameters[:format] Array(Mime[parameters[:format]]) - elsif xhr? || (accept && accept !~ /,\s*\*\/\*|\*\/\*,/) + elsif xhr? || (accept && accept !~ /,\s*\*\/\*|\*\/\*\s*,/) accepts else [Mime::HTML] diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 2de9b28e68..7a799411db 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -254,6 +254,10 @@ class RespondToControllerTest < ActionController::TestCase @request.accept = "*/*, application/json" get :json_xml_or_html assert_equal 'HTML', @response.body + + @request.accept = "*/* , application/json" + get :json_xml_or_html + assert_equal 'HTML', @response.body end def test_json_or_yaml -- cgit v1.2.3 From cbb2651cc0e102b8f519acc41035adc32a8cc01b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 08:58:49 -0500 Subject: add the fixture file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/fixtures/star_star_mime/index.js.erb | 1 + 1 file changed, 1 insertion(+) create mode 100644 actionpack/test/fixtures/star_star_mime/index.js.erb (limited to 'actionpack') diff --git a/actionpack/test/fixtures/star_star_mime/index.js.erb b/actionpack/test/fixtures/star_star_mime/index.js.erb new file mode 100644 index 0000000000..4da4181f56 --- /dev/null +++ b/actionpack/test/fixtures/star_star_mime/index.js.erb @@ -0,0 +1 @@ +function addition(a,b){ return a+b; } -- cgit v1.2.3 From d04a21b36281a0608cdd72c02e4df3b1136f8887 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 09:07:44 -0500 Subject: declare regex as a constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_negotiation.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 2b401114f0..68ba1a81b5 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -42,13 +42,15 @@ module ActionDispatch formats.first end + BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/ + def formats accept = @env['HTTP_ACCEPT'] @env["action_dispatch.request.formats"] ||= if parameters[:format] Array(Mime[parameters[:format]]) - elsif xhr? || (accept && accept !~ /,\s*\*\/\*|\*\/\*\s*,/) + elsif xhr? || (accept && accept !~ BROWSER_LIKE_ACCEPTS) accepts else [Mime::HTML] -- cgit v1.2.3 From b798a59bd582d8590d4fb8df44885d41cd5299f3 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:27:26 -0500 Subject: test for text/*, application/* and image/* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/dispatch/mime_type_test.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 4c2b95550c..48755e6b5f 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -6,10 +6,36 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse single" do Mime::LOOKUP.keys.each do |mime_type| - assert_equal [Mime::Type.lookup(mime_type)], Mime::Type.parse(mime_type) + unless image_type == 'image/*' + assert_equal [Mime::Type.lookup(mime_type)], Mime::Type.parse(mime_type) + end end end + test "parse text with trailing star star" do + accept = "text/*" + expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS + parsed = Mime::Type.parse(accept) + assert_equal 9, parsed.size + assert_equal expect, parsed + end + + test "parse application with trailing star star" do + accept = "application/*" + expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::R + parsed = Mime::Type.parse(accept) + assert_equal 9, parsed.size + assert_equal expect, parsed + end + + test "parse image with trailing star star" do + accept = "image/*" + parsed = Mime::Type.parse(accept) + assert_equal 2, parsed.size + assert parsed.include?(Mime::PNG) + assert_equal 'image/*', parsed[1].instance_variable_get('@string') + end + test "parse without q" do accept = "text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,application/pdf,*/*" expect = [Mime::HTML, Mime::XML, Mime::YAML, Mime::PNG, Mime::TEXT, Mime::PDF, Mime::ALL] -- cgit v1.2.3 From 6f6e754bac4c78f657feb0ea119447546aa87197 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:34:37 -0500 Subject: implement code that handles text/*, appplication/*, and image/* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_type.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 8f1c9b6691..3b5c1d50f2 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -103,9 +103,14 @@ module Mime ([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last } end + def parse(accept_header) if accept_header !~ /,/ - [Mime::Type.lookup(accept_header)] + if result = Regexp.new('(\w+)\/\*').match(accept_header) + parse_data_with_trailing_star(result[1]) + else + [Mime::Type.lookup(accept_header)] + end else # keep track of creation order to keep the subsequent sort stable list = [] @@ -160,6 +165,16 @@ module Mime list end end + + # input: 'text' + # returend value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + # + # input: 'application' + # returend value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM + def parse_data_with_trailing_star(input) + keys = Mime::LOOKUP.keys.select{|k| Regexp.new(input).match(k)} + Mime::LOOKUP.select {|k,_| keys.include?(k)}.collect{|i| i[1]}.inject([]){|all,e| all.include?(e) ? all : all << e} + end end def initialize(string, symbol = nil, synonyms = []) -- cgit v1.2.3 From 4154c659feee47f246a162e2086bf07ad149ec6d Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:35:24 -0500 Subject: fix test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/dispatch/mime_type_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 48755e6b5f..bea93adc19 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -6,7 +6,7 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse single" do Mime::LOOKUP.keys.each do |mime_type| - unless image_type == 'image/*' + unless mime_type == 'image/*' assert_equal [Mime::Type.lookup(mime_type)], Mime::Type.parse(mime_type) end end @@ -14,7 +14,7 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse text with trailing star star" do accept = "text/*" - expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS + expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] parsed = Mime::Type.parse(accept) assert_equal 9, parsed.size assert_equal expect, parsed @@ -22,7 +22,7 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse application with trailing star star" do accept = "application/*" - expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::R + expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::PDF, Mime::URL_ENCODED_FORM] parsed = Mime::Type.parse(accept) assert_equal 9, parsed.size assert_equal expect, parsed -- cgit v1.2.3 From c9147ebfa06023248b5e738f0928973ddc084da7 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:36:36 -0500 Subject: cleanup Mime::LOOKUP after registering image/gif MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/dispatch/mime_type_test.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index bea93adc19..ab5bbe3a19 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -71,6 +71,7 @@ class MimeTypeTest < ActiveSupport::TestCase end ensure Mime.module_eval { remove_const :GIF if const_defined?(:GIF) } + Mime::LOOKUP.reject!{|key,_| key == 'image/gif'} end end -- cgit v1.2.3 From 23ea19e20d6f7df762635b1c6d83369922d5ad7b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:39:58 -0500 Subject: rename star star to just one star MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/dispatch/mime_type_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index ab5bbe3a19..3a7ab740f4 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -12,7 +12,7 @@ class MimeTypeTest < ActiveSupport::TestCase end end - test "parse text with trailing star star" do + test "parse text with trailing star" do accept = "text/*" expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] parsed = Mime::Type.parse(accept) @@ -20,7 +20,7 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal expect, parsed end - test "parse application with trailing star star" do + test "parse application with trailing star" do accept = "application/*" expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::PDF, Mime::URL_ENCODED_FORM] parsed = Mime::Type.parse(accept) @@ -28,7 +28,7 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal expect, parsed end - test "parse image with trailing star star" do + test "parse image with trailing star" do accept = "image/*" parsed = Mime::Type.parse(accept) assert_equal 2, parsed.size -- cgit v1.2.3 From cdbbf6fd6bef3f286503859c585ada8fe66a3875 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 11:51:43 -0500 Subject: move the mime registration code to setup so that it could be cleaned up on teardown. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the test code test/controller/mime_responds_test.rb impacts test/dispatch/mime_type_test.rb. dispatch/mime_type_test.rb runs independently fine but when run as part of rake breaks because of new mime types registered in controller/mime_responds_test.rb Signed-off-by: José Valim --- actionpack/test/controller/mime_responds_test.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 7a799411db..0da051822a 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -97,7 +97,6 @@ class RespondToController < ActionController::Base end end - Mime::Type.register("text/x-mobile", :mobile) def custom_constant_handling respond_to do |type| @@ -134,7 +133,6 @@ class RespondToController < ActionController::Base end end - Mime::Type.register_alias("text/html", :iphone) def iphone_with_html_response_type request.format = :iphone if request.env["HTTP_ACCEPT"] == "text/iphone" @@ -200,10 +198,16 @@ class RespondToControllerTest < ActionController::TestCase def setup super @request.host = "www.example.com" + Mime::Type.register_alias("text/html", :iphone) + Mime::Type.register("text/x-mobile", :mobile) end def teardown super + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} + Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} end def test_html @@ -616,6 +620,10 @@ class RespondWithControllerTest < ActionController::TestCase def teardown super + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} + Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} end def test_using_resource @@ -996,6 +1004,15 @@ class MimeControllerLayoutsTest < ActionController::TestCase def setup super @request.host = "www.example.com" + Mime::Type.register_alias("text/html", :iphone) + end + + def teardown + super + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} + Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} end def test_missing_layout_renders_properly -- cgit v1.2.3 From 8154f4b816ea1bb2489fba1829ee99cb75fdf696 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 13:32:37 -0500 Subject: Compile regex only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_type.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 3b5c1d50f2..f2ccf1784b 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -80,6 +80,9 @@ module Mime end class << self + + TRAILING_STAR_REGEXP = /(\w+)\/\*/ + def lookup(string) LOOKUP[string] end @@ -103,11 +106,10 @@ module Mime ([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last } end - def parse(accept_header) if accept_header !~ /,/ - if result = Regexp.new('(\w+)\/\*').match(accept_header) - parse_data_with_trailing_star(result[1]) + if accept_header =~ TRAILING_STAR_REGEXP + parse_data_with_trailing_star($1) else [Mime::Type.lookup(accept_header)] end -- cgit v1.2.3 From c5bfc6abe4fd160814f09b02afe68d7f4e25e3d6 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 13:38:36 -0500 Subject: string include method is 10x faster than creating a new regex object every single time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index f2ccf1784b..af7b62b863 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -174,7 +174,7 @@ module Mime # input: 'application' # returend value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM def parse_data_with_trailing_star(input) - keys = Mime::LOOKUP.keys.select{|k| Regexp.new(input).match(k)} + keys = Mime::LOOKUP.keys.select{|k| k.include?(input)} Mime::LOOKUP.select {|k,_| keys.include?(k)}.collect{|i| i[1]}.inject([]){|all,e| all.include?(e) ? all : all << e} end end -- cgit v1.2.3 From 794b34306eea0c7e1e99f5741df16129e8e22b3f Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 13:55:43 -0500 Subject: remove select, collect and then inject with something better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index af7b62b863..2250cfa88a 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -175,7 +175,7 @@ module Mime # returend value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM def parse_data_with_trailing_star(input) keys = Mime::LOOKUP.keys.select{|k| k.include?(input)} - Mime::LOOKUP.select {|k,_| keys.include?(k)}.collect{|i| i[1]}.inject([]){|all,e| all.include?(e) ? all : all << e} + Mime::LOOKUP.values_at(*keys).uniq end end -- cgit v1.2.3 From 21fd93cedda9d96a81b06b96c541120a5da7a71a Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 22 Nov 2010 13:59:46 -0500 Subject: make test more resilient to future changes by not testing the count and not testing the internal value of the registered mime type. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ideally all mime type registration should be cleaned up in teardown. Signed-off-by: José Valim --- actionpack/test/dispatch/mime_type_test.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 3a7ab740f4..28e8d420d5 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -31,9 +31,7 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse image with trailing star" do accept = "image/*" parsed = Mime::Type.parse(accept) - assert_equal 2, parsed.size assert parsed.include?(Mime::PNG) - assert_equal 'image/*', parsed[1].instance_variable_get('@string') end test "parse without q" do -- cgit v1.2.3 From 5c86286dd6f8b58241492004e1fd872e217aca08 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 21 Nov 2010 13:46:25 +0100 Subject: add respond_to? to ActionDispatch::Integration::Runner since Runner uses method_missing to delegate to the integration session it also should define respond_to? accordingly --- actionpack/lib/action_dispatch/testing/integration.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index fee8cad9f5..e0a17130f8 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -363,6 +363,10 @@ module ActionDispatch integration_session.url_options end + def respond_to?(method, include_private = false) + @integration_session.respond_to?(method, include_private) || super + end + # Delegate unhandled messages to the current session instance. def method_missing(sym, *args, &block) reset! unless integration_session -- cgit v1.2.3 From 4395d493c5df5476e9e31df3336fc81c8a3e5d3c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Nov 2010 15:51:29 -0800 Subject: sort lists before comparing them --- actionpack/test/dispatch/mime_type_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 28e8d420d5..43123e68b2 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -14,18 +14,18 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse text with trailing star" do accept = "text/*" - expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT].sort_by(&:to_s) parsed = Mime::Type.parse(accept) assert_equal 9, parsed.size - assert_equal expect, parsed + assert_equal expect, parsed.sort_by(&:to_s) end test "parse application with trailing star" do accept = "application/*" - expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::PDF, Mime::URL_ENCODED_FORM] + expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::PDF, Mime::URL_ENCODED_FORM].sort_by(&:to_s) parsed = Mime::Type.parse(accept) assert_equal 9, parsed.size - assert_equal expect, parsed + assert_equal expect, parsed.sort_by(&:to_s) end test "parse image with trailing star" do -- cgit v1.2.3 From e83d15376d7ca10e20a720727f22cc9cdbbd662c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Nov 2010 15:57:03 -0800 Subject: adding a test for the runner module [#6027 state:resolved] --- actionpack/test/controller/runner_test.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 actionpack/test/controller/runner_test.rb (limited to 'actionpack') diff --git a/actionpack/test/controller/runner_test.rb b/actionpack/test/controller/runner_test.rb new file mode 100644 index 0000000000..24c220dcd5 --- /dev/null +++ b/actionpack/test/controller/runner_test.rb @@ -0,0 +1,22 @@ +require 'abstract_unit' +require 'action_dispatch/testing/integration' + +module ActionDispatch + class RunnerTest < Test::Unit::TestCase + class MyRunner + include Integration::Runner + + def initialize(session) + @integration_session = session + end + + def hi; end + end + + def test_respond_to? + runner = MyRunner.new(Class.new { def x; end }.new) + assert runner.respond_to?(:hi) + assert runner.respond_to?(:x) + end + end +end -- cgit v1.2.3 From 2fe43b694f36ddb2062a91eebe61a035147265b1 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 23 Nov 2010 00:31:03 +0100 Subject: :subdomain, :domain and :tld_length options can now be used in url_for, allowing for easy manipulation of the host during link generation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_controller/metal/url_for.rb | 4 +- actionpack/lib/action_dispatch/http/url.rb | 59 ++++++++++++++-------- .../lib/action_dispatch/routing/route_set.rb | 38 +++++++++++--- actionpack/lib/action_dispatch/routing/url_for.rb | 6 +++ actionpack/test/controller/url_for_test.rb | 23 ++++++++- actionpack/test/dispatch/request_test.rb | 6 +-- 6 files changed, 105 insertions(+), 31 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 333eeaeffb..6fc0cf1fb8 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -6,7 +6,8 @@ module ActionController def url_options @_url_options ||= super.reverse_merge( - :host => request.host_with_port, + :host => request.host, + :port => request.optional_port, :protocol => request.protocol, :_path_segments => request.symbolized_path_parameters ).freeze @@ -20,5 +21,6 @@ module ActionController @_url_options end end + end end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 9c9eed2c6d..1f7633cbea 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -4,6 +4,27 @@ module ActionDispatch mattr_accessor :tld_length self.tld_length = 1 + def self.extract_domain(host, tld_length = @@tld_length) + return nil unless named_host?(host) + + host.split('.').last(1 + tld_length).join('.') + end + + def self.extract_subdomains(host, tld_length = @@tld_length) + return [] unless named_host?(host) + parts = host.split('.') + parts[0..-(tld_length+2)] + end + + def self.extract_subdomain(host, tld_length = @@tld_length) + extract_subdomains(host, tld_length).join('.') + end + + def self.named_host?(host) + !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) + end + + # Returns the complete URL used for this request. def url protocol + host_with_port + fullpath @@ -31,15 +52,18 @@ module ActionDispatch # Returns a \host:\port string for this request, such as "example.com" or # "example.com:8080". def host_with_port - "#{host}#{port_string}" + opt_port = optional_port ? ":#{optional_port}" : nil + "#{host}#{opt_port}" end # Returns the port number of this request as an integer. def port - if raw_host_with_port =~ /:(\d+)$/ - $1.to_i - else - standard_port + @port ||= begin + if raw_host_with_port =~ /:(\d+)$/ + $1.to_i + else + standard_port + end end end @@ -56,10 +80,10 @@ module ActionDispatch port == standard_port end - # Returns a \port suffix like ":8080" if the \port number of this request + # Returns a \port suffix like "8080" if the \port number of this request # is not the default HTTP \port 80 or HTTPS \port 443. - def port_string - port == standard_port ? '' : ":#{port}" + def optional_port + standard_port? ? nil : port end def server_port @@ -69,9 +93,7 @@ module ActionDispatch # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify # a different tld_length, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk". def domain(tld_length = @@tld_length) - return nil unless named_host?(host) - - host.split('.').last(1 + tld_length).join('.') + ActionDispatch::Http::URL.extract_domain(host, tld_length) end # Returns all the \subdomains as an array, so ["dev", "www"] would be @@ -79,20 +101,17 @@ module ActionDispatch # such as 2 to catch ["www"] instead of ["www", "rubyonrails"] # in "www.rubyonrails.co.uk". def subdomains(tld_length = @@tld_length) - return [] unless named_host?(host) - parts = host.split('.') - parts[0..-(tld_length+2)] + ActionDispatch::Http::URL.extract_subdomains(host, tld_length) end + # Returns all the \subdomains as a string, so "dev.www" would be + # returned for "dev.www.rubyonrails.org". You can specify a different tld_length, + # such as 2 to catch ["www"] instead of "www.rubyonrails" + # in "www.rubyonrails.co.uk". def subdomain(tld_length = @@tld_length) - subdomains(tld_length).join('.') + subdomains(tld_length) end - private - - def named_host?(host) - !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) - end end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 32f41934f1..d823fd710e 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -485,7 +485,8 @@ module ActionDispatch Generator.new(options, recall, self, extras).generate end - RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name] + RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length, + :trailing_slash, :script_name, :anchor, :params, :only_path ] def _generate_prefix(options = {}) nil @@ -504,11 +505,8 @@ module ActionDispatch rewritten_url << (options[:protocol] || "http") rewritten_url << "://" unless rewritten_url.match("://") rewritten_url << rewrite_authentication(options) - - raise "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" unless options[:host] - - rewritten_url << options[:host] - rewritten_url << ":#{options.delete(:port)}" if options.key?(:port) + rewritten_url << host_from_options(options) + rewritten_url << ":#{options.delete(:port)}" if options[:port] end script_name = options.delete(:script_name) @@ -562,6 +560,34 @@ module ActionDispatch end private + + def host_from_options(options) + computed_host = subdomain_and_domain(options) || options[:host] + unless computed_host + raise ArgumentError, "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" + end + computed_host + end + + def subdomain_and_domain(options) + tld_length = options[:tld_length] || ActionDispatch::Http::URL.tld_length + + current_domain = ActionDispatch::Http::URL.extract_domain(options[:host], tld_length) + current_subdomain = ActionDispatch::Http::URL.extract_subdomain(options[:host], tld_length) + + domain_parts = if options[:subdomain] && options[:domain] + [options[:subdomain], options[:domain]] + elsif options[:subdomain] + [options[:subdomain], current_domain] + elsif options[:domain] + [current_subdomain, options[:domain]] + else + nil + end + + domain_parts ? domain_parts.join('.') : nil + end + def handle_positional_args(options) return unless args = options.delete(:_positional_args) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index bfdea41f60..6c3fc5126a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -115,6 +115,12 @@ module ActionDispatch # * :host - Specifies the host the link should be targeted at. # If :only_path is false, this option must be # provided either explicitly, or via +default_url_options+. + # * :subdomain - Specifies the subdomain of the link, using the +tld_length+ + # to split the domain from the host. + # * :domain - Specifies the domain of the link, using the +tld_length+ + # to split the subdomain from the host. + # * :tld_length - Optionally specify the tld length (only used if :subdomain + # or :domain are supplied). # * :port - Optionally specify the port to connect to. # * :anchor - An anchor name to be appended to the path. # * :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/" diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index 4c07ca4cc3..1f62d29e80 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -17,7 +17,7 @@ module AbstractController end def test_exception_is_thrown_without_host - assert_raise RuntimeError do + assert_raise ArgumentError do W.new.url_for :controller => 'c', :action => 'a', :id => 'i' end end @@ -60,6 +60,27 @@ module AbstractController ) end + def test_subdomain_may_be_changed + add_host! + assert_equal('http://api.basecamphq.com/c/a/i', + W.new.url_for(:subdomain => 'api', :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_domain_may_be_changed + add_host! + assert_equal('http://www.37signals.com/c/a/i', + W.new.url_for(:domain => '37signals.com', :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_tld_length_may_be_changed + add_host! + assert_equal('http://mobile.www.basecamphq.com/c/a/i', + W.new.url_for(:subdomain => 'mobile', :tld_length => 2, :controller => 'c', :action => 'a', :id => 'i') + ) + end + def test_port add_host! assert_equal('http://www.basecamphq.com:3000/c/a/i', diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 4764a8c2a8..d140ea8358 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -164,12 +164,12 @@ class RequestTest < ActiveSupport::TestCase assert !request.standard_port? end - test "port string" do + test "optional port" do request = stub_request 'HTTP_HOST' => 'www.example.org:80' - assert_equal "", request.port_string + assert_equal nil, request.optional_port request = stub_request 'HTTP_HOST' => 'www.example.org:8080' - assert_equal ":8080", request.port_string + assert_equal 8080, request.optional_port end test "full path" do -- cgit v1.2.3 From 56b12140246303440da18c0c5ea139b3b17b0282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 23 Nov 2010 10:05:47 +0100 Subject: Speed up subdomain and domain calculus. --- actionpack/lib/action_dispatch/routing/route_set.rb | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index d823fd710e..ebced9cabe 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -570,22 +570,14 @@ module ActionDispatch end def subdomain_and_domain(options) + return nil unless options[:subdomain] || options[:domain] tld_length = options[:tld_length] || ActionDispatch::Http::URL.tld_length - current_domain = ActionDispatch::Http::URL.extract_domain(options[:host], tld_length) - current_subdomain = ActionDispatch::Http::URL.extract_subdomain(options[:host], tld_length) - - domain_parts = if options[:subdomain] && options[:domain] - [options[:subdomain], options[:domain]] - elsif options[:subdomain] - [options[:subdomain], current_domain] - elsif options[:domain] - [current_subdomain, options[:domain]] - else - nil - end - - domain_parts ? domain_parts.join('.') : nil + host = "" + host << (options[:subdomain] || ActionDispatch::Http::URL.extract_subdomain(options[:host], tld_length)) + host << "." + host << (options[:domain] || ActionDispatch::Http::URL.extract_domain(options[:host], tld_length)) + host end def handle_positional_args(options) -- cgit v1.2.3 From da583df50c32d50261b682664fe43fd5e2f58f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 23 Nov 2010 10:09:24 +0100 Subject: Remove bazillion warnings from AP suite. --- actionpack/lib/action_dispatch/testing/integration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index e0a17130f8..8fe74c3c80 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -364,7 +364,7 @@ module ActionDispatch end def respond_to?(method, include_private = false) - @integration_session.respond_to?(method, include_private) || super + integration_session.respond_to?(method, include_private) || super end # Delegate unhandled messages to the current session instance. -- cgit v1.2.3 From 0250c3eca40f5f2b3da698b11ff4f01f58db5a69 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 23 Nov 2010 22:51:51 +0100 Subject: copy-edits RDoc of 2fe43b6 --- actionpack/lib/action_dispatch/routing/url_for.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 6c3fc5126a..d4db78a25a 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -119,8 +119,9 @@ module ActionDispatch # to split the domain from the host. # * :domain - Specifies the domain of the link, using the +tld_length+ # to split the subdomain from the host. - # * :tld_length - Optionally specify the tld length (only used if :subdomain - # or :domain are supplied). + # * :tld_length - Number of labels the TLD id composed of, only used if + # :subdomain or :domain are supplied. Defaults to + # ActionDispatch::Http::URL.tld_length, which in turn defaults to 1. # * :port - Optionally specify the port to connect to. # * :anchor - An anchor name to be appended to the path. # * :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/" -- cgit v1.2.3 From 769575300acb778ce812208073952109bc45a9fd Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:19:27 +1100 Subject: Fix formatting issue with rake routes output for the namespace method --- actionpack/lib/action_dispatch/routing/mapper.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 879ccc5791..432a574419 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -588,13 +588,13 @@ module ActionDispatch # # This generates the following routes: # - # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"} - # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"} - # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"} - # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"} - # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"} - # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"} - # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} + # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"} + # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"} + # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"} + # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"} + # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"} + # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"} + # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} # === Supported options # # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ all default to the name of the namespace. -- cgit v1.2.3 From 04af510b5678ea7bd4cd170257e7e3ef4423f834 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:21:25 +1100 Subject: Paths in ActionDispatch::Scoping documentation should be for /admin/posts, not /admin/photos --- actionpack/lib/action_dispatch/routing/mapper.rb | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 432a574419..37d14944d6 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -439,13 +439,13 @@ module ActionDispatch # This will create a number of routes for each of the posts and comments # controller. For Admin::PostsController, Rails will create: # - # GET /admin/photos - # GET /admin/photos/new - # POST /admin/photos - # GET /admin/photos/1 - # GET /admin/photos/1/edit - # PUT /admin/photos/1 - # DELETE /admin/photos/1 + # GET /admin/posts + # GET /admin/posts/new + # POST /admin/posts + # GET /admin/posts/1 + # GET /admin/posts/1/edit + # PUT /admin/posts/1 + # DELETE /admin/posts/1 # # If you want to route /posts (without the prefix /admin) to # Admin::PostsController, you could use @@ -473,13 +473,13 @@ module ActionDispatch # not use scope. In the last case, the following paths map to # PostsController: # - # GET /admin/photos - # GET /admin/photos/new - # POST /admin/photos - # GET /admin/photos/1 - # GET /admin/photos/1/edit - # PUT /admin/photos/1 - # DELETE /admin/photos/1 + # GET /admin/posts + # GET /admin/posts/new + # POST /admin/posts + # GET /admin/posts/1 + # GET /admin/posts/1/edit + # PUT /admin/posts/1 + # DELETE /admin/posts/1 module Scoping def initialize(*args) #:nodoc: @scope = {} -- cgit v1.2.3 From 2974f57aaedd22f44b387ec72ca9f42a2982bb02 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:25:01 +1100 Subject: Remove non-sensical first couple of lines for scope method documentation --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 37d14944d6..8b1578769d 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -486,8 +486,6 @@ module ActionDispatch super end - # Used to route /photos (without the prefix /admin) - # to Admin::PostsController: # === Supported options # [:module] # If you want to route /posts (without the prefix /admin) to -- cgit v1.2.3 From 01af50d8b6be7b167c30f29c7407ce88bdfc9b2a Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:27:12 +1100 Subject: Add :module option documentation for the resources method --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8b1578769d..1f3a831b7f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -967,6 +967,7 @@ module ActionDispatch # GET /photos/:id/edit # PUT /photos/:id # DELETE /photos/:id + # # === Supported options # [:path_names] # Allows you to change the paths of the seven default actions. @@ -975,6 +976,13 @@ module ActionDispatch # resources :posts, :path_names => { :new => "brand_new" } # # The above example will now change /posts/new to /posts/brand_new + # + # [:module] + # Set the module where the controller can be found. Defaults to nothing. + # + # resources :posts, :module => "admin" + # + # All requests to the posts resources will now go to +Admin::PostsController+. def resources(*resources, &block) options = resources.extract_options! -- cgit v1.2.3 From fd47a4bf438e37a20756e0341cd7cd4e472fd3cb Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:28:21 +1100 Subject: Document the :path option for resources :posts --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 1f3a831b7f..f4d31eeff1 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -983,6 +983,14 @@ module ActionDispatch # resources :posts, :module => "admin" # # All requests to the posts resources will now go to +Admin::PostsController+. + # + # [:path] + # + # Set a path prefix for this resource. + # + # resources :posts, :path => "admin" + # + # All actions for this resource will now be at +/admin/posts+. def resources(*resources, &block) options = resources.extract_options! -- cgit v1.2.3 From e4a9af186a7316e2de018ff9306442b9fe0f2400 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Wed, 24 Nov 2010 09:31:29 +1100 Subject: Add mention of nested resource to resources documentation --- actionpack/lib/action_dispatch/routing/mapper.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index f4d31eeff1..fb1f0d3f0c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -968,6 +968,21 @@ module ActionDispatch # PUT /photos/:id # DELETE /photos/:id # + # Resources can also be nested infinitely by using this block syntax: + # + # resources :photos do + # resources :comments + # end + # + # This generates the following comments routes: + # + # GET /photos/:id/comments/new + # POST /photos/:id/comments + # GET /photos/:id/comments/:id + # GET /photos/:id/comments/:id/edit + # PUT /photos/:id/comments/:id + # DELETE /photos/:id/comments/:id + # # === Supported options # [:path_names] # Allows you to change the paths of the seven default actions. -- cgit v1.2.3 From 8882e65ac8cd499f09bacee4bc4f3f4c328fae05 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 24 Nov 2010 05:49:41 +0800 Subject: No need to return anything --- .../lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb index 15f8e10b7f..e52797042f 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb @@ -79,7 +79,6 @@ module ActionView sources.each do |source| asset_file_path!(path_to_asset(source, false)) end - return sources end def collect_asset_files(*path) -- cgit v1.2.3 From e39138478b38d7a5e0a13756b1bdfa8b43226846 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Wed, 24 Nov 2010 10:10:38 +0100 Subject: port_string bought back to life as it is part of the public api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/url.rb | 11 ++++++++--- actionpack/test/dispatch/request_test.rb | 10 +++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 1f7633cbea..1e7054f381 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -52,8 +52,7 @@ module ActionDispatch # Returns a \host:\port string for this request, such as "example.com" or # "example.com:8080". def host_with_port - opt_port = optional_port ? ":#{optional_port}" : nil - "#{host}#{opt_port}" + "#{host}#{port_string}" end # Returns the port number of this request as an integer. @@ -80,12 +79,18 @@ module ActionDispatch port == standard_port end - # Returns a \port suffix like "8080" if the \port number of this request + # Returns a number \port suffix like 8080 if the \port number of this request # is not the default HTTP \port 80 or HTTPS \port 443. def optional_port standard_port? ? nil : port end + # Returns a string \port suffix, including colon, like ":8080" if the \port + # number of this request is not the default HTTP \port 80 or HTTPS \port 443. + def port_string + standard_port? ? '' : ":#{port}" + end + def server_port @env['SERVER_PORT'].to_i end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index d140ea8358..8f672c1149 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -172,6 +172,14 @@ class RequestTest < ActiveSupport::TestCase assert_equal 8080, request.optional_port end + test "port string" do + request = stub_request 'HTTP_HOST' => 'www.example.org:80' + assert_equal '', request.port_string + + request = stub_request 'HTTP_HOST' => 'www.example.org:8080' + assert_equal ':8080', request.port_string + end + test "full path" do request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri', 'QUERY_STRING' => 'mapped=1' assert_equal "/path/of/some/uri?mapped=1", request.fullpath @@ -392,7 +400,7 @@ class RequestTest < ActiveSupport::TestCase mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" } request = nil begin - request = stub_request(mock_rack_env) + request = stub_request(mock_rack_env) request.parameters rescue TypeError => e # rack will raise a TypeError when parsing this query string -- cgit v1.2.3 From 8624065bffd203e1f590ca431d468f9b38e9fb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 24 Nov 2010 12:38:52 +0100 Subject: Allow template handlers to store temp data. --- actionpack/lib/action_view/template.rb | 5 +++++ actionpack/test/template/lookup_context_test.rb | 29 +++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 6c6d659246..831a19654e 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -184,6 +184,11 @@ module ActionView end end + # Used to store template data by template handlers. + def data + @data ||= {} + end + def inspect @inspect ||= if defined?(Rails.root) diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 6d3b26e131..c9dd27cf2a 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -180,6 +180,16 @@ class LookupContextTest < ActiveSupport::TestCase assert_not_equal template, old_template end + + test "data can be stored in cached templates" do + template = @lookup_context.find("hello_world", "test") + template.data["cached"] = "data" + assert_equal "Hello world!", template.source + + template = @lookup_context.find("hello_world", "test") + assert_equal "data", template.data["cached"] + assert_equal "Hello world!", template.source + end end class LookupContextWithFalseCaching < ActiveSupport::TestCase @@ -205,7 +215,7 @@ class LookupContextWithFalseCaching < ActiveSupport::TestCase assert_equal "Bar", template.source end - test "if no template was found in the second lookup, give it higher preference" do + test "if no template was found in the second lookup, with no cache, raise error" do template = @lookup_context.find("foo", "test", true) assert_equal "Foo", template.source @@ -215,7 +225,7 @@ class LookupContextWithFalseCaching < ActiveSupport::TestCase end end - test "if no template was cached in the first lookup, do not use the cache in the second" do + test "if no template was cached in the first lookup, retrieval should work in the second call" do @resolver.hash.clear assert_raise ActionView::MissingTemplate do @lookup_context.find("foo", "test", true) @@ -225,4 +235,19 @@ class LookupContextWithFalseCaching < ActiveSupport::TestCase template = @lookup_context.find("foo", "test", true) assert_equal "Foo", template.source end + + test "data can be stored as long as template was not updated" do + template = @lookup_context.find("foo", "test", true) + template.data["cached"] = "data" + assert_equal "Foo", template.source + + template = @lookup_context.find("foo", "test", true) + assert_equal "data", template.data["cached"] + assert_equal "Foo", template.source + + @resolver.hash["test/_foo.erb"][1] = Time.now.utc + template = @lookup_context.find("foo", "test", true) + assert_nil template.data["cached"] + assert_equal "Foo", template.source + end end \ No newline at end of file -- cgit v1.2.3 From c6030e8562cddcb71898a1dea242affe5f0464f0 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 23 Nov 2010 22:40:41 +0800 Subject: Remove the not needed setup and teardown --- actionpack/test/controller/mime_responds_test.rb | 3 --- 1 file changed, 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 0da051822a..8e7d8056a0 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -169,9 +169,6 @@ end class StarStarMimeControllerTest < ActionController::TestCase tests StarStarMimeController - def setup; super; end - def teardown; super; end - def test_javascript_with_format @request.accept = "text/javascript" get :index, :format => 'js' -- cgit v1.2.3 From e8708836252852d8bae87c80472b865812fa9776 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 23 Nov 2010 23:28:57 +0800 Subject: unregister method implementation and test --- actionpack/lib/action_dispatch/http/mime_type.rb | 12 ++++++++++++ actionpack/test/dispatch/mime_type_test.rb | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 2250cfa88a..2b8395fc09 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -177,6 +177,18 @@ module Mime keys = Mime::LOOKUP.keys.select{|k| k.include?(input)} Mime::LOOKUP.values_at(*keys).uniq end + + # This method is opposite of register method. + # + # Usage: + # + # Mime::Type.unregister("text/x-mobile", :mobile) + def unregister(string, symbol) + EXTENSION_LOOKUP.delete(symbol.to_s) + LOOKUP.delete(string) + symbol = symbol.to_s.upcase.intern + Mime.module_eval { remove_const(symbol) if const_defined?(symbol) } + end end def initialize(string, symbol = nil, synonyms = []) diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 43123e68b2..f2d2799a67 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -12,6 +12,23 @@ class MimeTypeTest < ActiveSupport::TestCase end end + test "unregister" do + begin + Mime::Type.register("text/x-mobile", :mobile) + assert defined?(Mime::MOBILE) + assert_equal Mime::MOBILE, Mime::LOOKUP['text/x-mobile'] + assert_equal Mime::MOBILE, Mime::EXTENSION_LOOKUP['mobile'] + + Mime::Type.unregister("text/x-mobile", :mobile) + assert !defined?(Mime::MOBILE), "Mime::MOBILE should not be defined" + assert !Mime::LOOKUP.has_key?('text/x-mobile'), "Mime::LOOKUP should not have key ['text/x-mobile]" + assert !Mime::EXTENSION_LOOKUP.has_key?('mobile'), "Mime::EXTENSION_LOOKUP should not have key ['mobile]" + ensure + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} + end + end + test "parse text with trailing star" do accept = "text/*" expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT].sort_by(&:to_s) -- cgit v1.2.3 From b52a6ba16914d29785e751011e91d7bb91a2356d Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 23 Nov 2010 23:49:15 +0800 Subject: clean up test by using unregister method --- actionpack/test/controller/mime_responds_test.rb | 18 ++++++------------ actionpack/test/dispatch/mime_type_test.rb | 3 +-- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 8e7d8056a0..8315f90fee 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -201,10 +201,8 @@ class RespondToControllerTest < ActionController::TestCase def teardown super - Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } - Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } - Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} - Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} + Mime::Type.unregister('text/x-mobile', :iphone) + Mime::Type.unregister('text/iphone', :mobile) end def test_html @@ -617,10 +615,8 @@ class RespondWithControllerTest < ActionController::TestCase def teardown super - Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } - Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } - Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} - Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} + Mime::Type.unregister('text/x-mobile', :iphone) + Mime::Type.unregister('text/iphone', :mobile) end def test_using_resource @@ -1006,10 +1002,8 @@ class MimeControllerLayoutsTest < ActionController::TestCase def teardown super - Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } - Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } - Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} - Mime::LOOKUP.reject!{|key,_| key == 'text/iphone'} + Mime::Type.unregister('text/x-mobile', :iphone) + Mime::Type.unregister('text/iphone', :mobile) end def test_missing_layout_renders_properly diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index f2d2799a67..bf44cb95fa 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -85,8 +85,7 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal Mime::GIF, Mime::SET.last end ensure - Mime.module_eval { remove_const :GIF if const_defined?(:GIF) } - Mime::LOOKUP.reject!{|key,_| key == 'image/gif'} + Mime::Type.unregister('image/gif', :gif) end end -- cgit v1.2.3 From 5c9abb6cca4b6de7146c94779a34ae943e4ea4d8 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 25 Nov 2010 01:19:43 +0800 Subject: processing image/* is an odditity because there is a test case which expects image/* to not to be expanded. So I am leaving image/* as it is and process only text/* and application/* --- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- actionpack/test/dispatch/mime_type_test.rb | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 2b8395fc09..5ea49a23c7 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -81,7 +81,7 @@ module Mime class << self - TRAILING_STAR_REGEXP = /(\w+)\/\*/ + TRAILING_STAR_REGEXP = /(text|application)\/\*/ def lookup(string) LOOKUP[string] diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index bf44cb95fa..25e106f519 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -45,12 +45,6 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal expect, parsed.sort_by(&:to_s) end - test "parse image with trailing star" do - accept = "image/*" - parsed = Mime::Type.parse(accept) - assert parsed.include?(Mime::PNG) - end - test "parse without q" do accept = "text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,application/pdf,*/*" expect = [Mime::HTML, Mime::XML, Mime::YAML, Mime::PNG, Mime::TEXT, Mime::PDF, Mime::ALL] -- cgit v1.2.3 From 18adbe9347727dc3eefe46395d52aafa347a0c73 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 25 Nov 2010 01:24:45 +0800 Subject: process text/* if it appears in the middle of HTTP_ACCEPT parameter --- actionpack/lib/action_dispatch/http/mime_type.rb | 6 +++++- actionpack/test/dispatch/mime_type_test.rb | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 5ea49a23c7..08eab5634a 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -120,7 +120,11 @@ module Mime params, q = header.split(/;\s*q=/) if params params.strip! - list << AcceptItem.new(index, params, q) unless params.empty? + if params =~ TRAILING_STAR_REGEXP + parse_data_with_trailing_star($1).each { |m| list << AcceptItem.new(index, m.to_s, q) } + else + list << AcceptItem.new(index, params, q) unless params.empty? + end end end list.sort! diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 25e106f519..9424d88498 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -29,6 +29,26 @@ class MimeTypeTest < ActiveSupport::TestCase end end + test "parse text with trailing star at the beginning" do + accept = "text/*, text/html, application/json, multipart/form-data" + expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::TEXT, Mime::YAML, Mime::JS, Mime::MULTIPART_FORM] + parsed = Mime::Type.parse(accept) + assert_equal expect.size, parsed.size + Range.new(0,expect.size-1).to_a.each do |index| + assert_equal expect[index], parsed[index], "Failed for index number #{index}" + end + end + + test "parse text with trailing star in the end" do + accept = "text/html, application/json, multipart/form-data, text/*" + expect = [Mime::HTML, Mime::JSON, Mime::MULTIPART_FORM, Mime::XML, Mime::ICS, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + parsed = Mime::Type.parse(accept) + assert_equal 10, parsed.size + Range.new(0,expect.size-1).to_a.each do |index| + assert_equal expect[index], parsed[index], "Failed for index number #{index}" + end + end + test "parse text with trailing star" do accept = "text/*" expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT].sort_by(&:to_s) -- cgit v1.2.3 From fa2a5ae0339c90d023a7559e681a588219dc3903 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 15 Nov 2010 17:52:39 -0500 Subject: If a user wants json output then try best to render json output. In such cases prefer kind_of(String) over respond_to?(to_str) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#5841 state:resolved] Signed-off-by: José Valim --- actionpack/lib/action_controller/metal/renderers.rb | 2 +- actionpack/test/controller/mime_responds_test.rb | 18 ++++++++++++++++++ actionpack/test/lib/controller/fake_models.rb | 6 ++++++ 3 files changed, 25 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index 67cf08445d..d6f6ab1855 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -55,7 +55,7 @@ module ActionController end add :json do |json, options| - json = json.to_json(options) unless json.respond_to?(:to_str) + json = json.to_json(options) unless json.kind_of?(String) json = "#{options[:callback]}(#{json})" unless options[:callback].blank? self.content_type ||= Mime::JSON self.response_body = json diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 8315f90fee..82969b2979 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -599,6 +599,17 @@ class InheritedRespondWithController < RespondWithController end end +class RenderJsonRespondWithController < RespondWithController + clear_respond_to + respond_to :json + + def index + respond_with(resource) do |format| + format.json { render :json => RenderJsonTestException.new('boom') } + end + end +end + class EmptyRespondWithController < ActionController::Base def index respond_with(Customer.new("david", 13)) @@ -914,6 +925,13 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal "JSON", @response.body end + def test_render_json_object_responds_to_str_still_produce_json + @controller = RenderJsonRespondWithController.new + @request.accept = "application/json" + get :index, :format => :json + assert_equal %Q{{"message":"boom","error":"RenderJsonTestException"}}, @response.body + end + def test_no_double_render_is_raised @request.accept = "text/html" assert_raise ActionView::MissingTemplate do diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index ae0c38184d..bd18cdc1b8 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -194,3 +194,9 @@ class ArelLike a.each { |i| yield i } end end + +class RenderJsonTestException < Exception + def to_json(options = nil) + return { :error => self.class.name, :message => self.to_str }.to_json + end +end -- cgit v1.2.3 From cb1570936d70d624f72229c8a19ffbe3a10cc5ca Mon Sep 17 00:00:00 2001 From: raggi Date: Thu, 25 Nov 2010 04:03:04 +0800 Subject: Rakefiles are executables, and rake loads rake, not rakefile code --- actionpack/Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 actionpack/Rakefile (limited to 'actionpack') diff --git a/actionpack/Rakefile b/actionpack/Rakefile old mode 100644 new mode 100755 index a6ce08113f..9030db9f7a --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -1,4 +1,4 @@ -require 'rake' +#!/usr/bin/env rake require 'rake/testtask' require 'rake/packagetask' require 'rake/gempackagetask' -- cgit v1.2.3 From 90b0f6149160e6fedb12ea54f713ec3399bebec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 25 Nov 2010 10:44:42 +0100 Subject: #:nodoc: internal methods. --- actionpack/lib/action_dispatch/routing/mapper.rb | 62 ++++++++++++------------ 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 879ccc5791..0b5437bd4f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -707,61 +707,61 @@ module ActionDispatch end private - def scope_options + def scope_options #:nodoc: @scope_options ||= private_methods.grep(/^merge_(.+)_scope$/) { $1.to_sym } end - def merge_path_scope(parent, child) + def merge_path_scope(parent, child) #:nodoc: Mapper.normalize_path("#{parent}/#{child}") end - def merge_shallow_path_scope(parent, child) + def merge_shallow_path_scope(parent, child) #:nodoc: Mapper.normalize_path("#{parent}/#{child}") end - def merge_as_scope(parent, child) + def merge_as_scope(parent, child) #:nodoc: parent ? "#{parent}_#{child}" : child end - def merge_shallow_prefix_scope(parent, child) + def merge_shallow_prefix_scope(parent, child) #:nodoc: parent ? "#{parent}_#{child}" : child end - def merge_module_scope(parent, child) + def merge_module_scope(parent, child) #:nodoc: parent ? "#{parent}/#{child}" : child end - def merge_controller_scope(parent, child) + def merge_controller_scope(parent, child) #:nodoc: child end - def merge_path_names_scope(parent, child) + def merge_path_names_scope(parent, child) #:nodoc: merge_options_scope(parent, child) end - def merge_constraints_scope(parent, child) + def merge_constraints_scope(parent, child) #:nodoc: merge_options_scope(parent, child) end - def merge_defaults_scope(parent, child) + def merge_defaults_scope(parent, child) #:nodoc: merge_options_scope(parent, child) end - def merge_blocks_scope(parent, child) + def merge_blocks_scope(parent, child) #:nodoc: merged = parent ? parent.dup : [] merged << child if child merged end - def merge_options_scope(parent, child) + def merge_options_scope(parent, child) #:nodoc: (parent || {}).except(*override_keys(child)).merge(child) end - def merge_shallow_scope(parent, child) + def merge_shallow_scope(parent, child) #:nodoc: child ? true : false end - def override_keys(child) + def override_keys(child) #:nodoc: child.key?(:only) || child.key?(:except) ? [:only, :except] : [] end end @@ -1167,7 +1167,7 @@ module ActionDispatch @scope[:scope_level_resource] end - def apply_common_behavior_for(method, resources, options, &block) + def apply_common_behavior_for(method, resources, options, &block) #:nodoc: if resources.length > 1 resources.each { |r| send(method, r, options, &block) } return true @@ -1197,23 +1197,23 @@ module ActionDispatch false end - def action_options?(options) + def action_options?(options) #:nodoc: options[:only] || options[:except] end - def scope_action_options? + def scope_action_options? #:nodoc: @scope[:options].is_a?(Hash) && (@scope[:options][:only] || @scope[:options][:except]) end - def scope_action_options + def scope_action_options #:nodoc: @scope[:options].slice(:only, :except) end - def resource_scope? + def resource_scope? #:nodoc: [:resource, :resources].include?(@scope[:scope_level]) end - def resource_method_scope? + def resource_method_scope? #:nodoc: [:collection, :member, :new].include?(@scope[:scope_level]) end @@ -1239,7 +1239,7 @@ module ActionDispatch @scope[:scope_level_resource] = old_resource end - def resource_scope(resource) + def resource_scope(resource) #:nodoc: with_scope_level(resource.is_a?(SingletonResource) ? :resource : :resources, resource) do scope(parent_resource.resource_scope) do yield @@ -1247,30 +1247,30 @@ module ActionDispatch end end - def nested_options + def nested_options #:nodoc: {}.tap do |options| options[:as] = parent_resource.member_name options[:constraints] = { "#{parent_resource.singular}_id".to_sym => id_constraint } if id_constraint? end end - def id_constraint? + def id_constraint? #:nodoc: @scope[:constraints] && @scope[:constraints][:id].is_a?(Regexp) end - def id_constraint + def id_constraint #:nodoc: @scope[:constraints][:id] end - def canonical_action?(action, flag) + def canonical_action?(action, flag) #:nodoc: flag && resource_method_scope? && CANONICAL_ACTIONS.include?(action.to_s) end - def shallow_scoping? + def shallow_scoping? #:nodoc: shallow? && @scope[:scope_level] == :member end - def path_for_action(action, path) + def path_for_action(action, path) #:nodoc: prefix = shallow_scoping? ? "#{@scope[:shallow_path]}/#{parent_resource.path}/:id" : @scope[:path] @@ -1281,11 +1281,11 @@ module ActionDispatch end end - def action_path(name, path = nil) + def action_path(name, path = nil) #:nodoc: path || @scope[:path_names][name.to_sym] || name.to_s end - def prefix_name_for_action(as, action) + def prefix_name_for_action(as, action) #:nodoc: if as as.to_s elsif !canonical_action?(action, @scope[:scope_level]) @@ -1293,7 +1293,7 @@ module ActionDispatch end end - def name_for_action(as, action) + def name_for_action(as, action) #:nodoc: prefix = prefix_name_for_action(as, action) prefix = Mapper.normalize_name(prefix) if prefix name_prefix = @scope[:as] @@ -1323,7 +1323,7 @@ module ActionDispatch end end - module Shorthand + module Shorthand #:nodoc: def match(*args) if args.size == 1 && args.last.is_a?(Hash) options = args.pop -- cgit v1.2.3 From 731ca00b484379661786fac36c17db7e085603c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 25 Nov 2010 11:49:51 +0100 Subject: Dynamically generaeted helpers on collection should not clobber resources url helper [#6028 state:resolved] --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 ++ actionpack/test/dispatch/routing_test.rb | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0b5437bd4f..880862c909 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1299,6 +1299,8 @@ module ActionDispatch name_prefix = @scope[:as] if parent_resource + return nil if as.nil? && action.nil? + collection_name = parent_resource.collection_name member_name = parent_resource.member_name end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 0ac8c249cb..bbd010ea6d 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -155,6 +155,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end resources :replies do + collection do + get 'page/:page' => 'replies#index', :page => %r{\d+} + get ':page' => 'replies#index', :page => %r{\d+} + end + new do post :preview end @@ -1241,6 +1246,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper + with_test_routes do + assert_equal '/replies', replies_path + end + end + def test_scoped_controller_with_namespace_and_action with_test_routes do assert_equal '/account/twitter/callback', account_callback_path("twitter") -- cgit v1.2.3 From 2c08ee97c78b7eb0883f1b0347c69a088c109388 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 26 Nov 2010 00:21:51 +0100 Subject: move the setting up of the mime collector into the collector on init --- actionpack/lib/action_controller/metal/mime_responds.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 6fe1f4ece5..2e58155b7c 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -258,9 +258,8 @@ module ActionController #:nodoc: # nil if :not_acceptable was sent to the client. # def retrieve_response_from_mimes(mimes=nil, &block) - collector = Collector.new { default_render } mimes ||= collect_mimes_from_class_level - mimes.each { |mime| collector.send(mime) } + collector = Collector.new(mimes) { default_render } block.call(collector) if block_given? if format = request.negotiate_mime(collector.order) @@ -277,8 +276,9 @@ module ActionController #:nodoc: include AbstractController::Collector attr_accessor :order - def initialize(&block) + def initialize(mimes, &block) @order, @responses, @default_response = [], {}, block + mimes.each { |mime| self.send(mime) } end def any(*args, &block) -- cgit v1.2.3 From a98d9d65aef31e3e1c95f59cd65ac7e1cbe76f89 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 26 Nov 2010 00:21:51 +0100 Subject: move the setting up of the mime collector into the collector on init Signed-off-by: Santiago Pastorino --- actionpack/lib/action_controller/metal/mime_responds.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 6fe1f4ece5..2e58155b7c 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -258,9 +258,8 @@ module ActionController #:nodoc: # nil if :not_acceptable was sent to the client. # def retrieve_response_from_mimes(mimes=nil, &block) - collector = Collector.new { default_render } mimes ||= collect_mimes_from_class_level - mimes.each { |mime| collector.send(mime) } + collector = Collector.new(mimes) { default_render } block.call(collector) if block_given? if format = request.negotiate_mime(collector.order) @@ -277,8 +276,9 @@ module ActionController #:nodoc: include AbstractController::Collector attr_accessor :order - def initialize(&block) + def initialize(mimes, &block) @order, @responses, @default_response = [], {}, block + mimes.each { |mime| self.send(mime) } end def any(*args, &block) -- cgit v1.2.3 From 74049b57fba3d26a5c9ac220619362ff36893b13 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Nov 2010 21:31:14 -0200 Subject: implicit self here --- actionpack/lib/action_controller/metal/mime_responds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 2e58155b7c..9ba37134b8 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -278,7 +278,7 @@ module ActionController #:nodoc: def initialize(mimes, &block) @order, @responses, @default_response = [], {}, block - mimes.each { |mime| self.send(mime) } + mimes.each { |mime| send(mime) } end def any(*args, &block) -- cgit v1.2.3 From 5b9f6a74db1a58c5557087cd924fd67dd9cf43e0 Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Fri, 26 Nov 2010 16:41:33 +0530 Subject: Resolving LH #5986, cookies doc updates --- actionpack/lib/action_dispatch/middleware/cookies.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index c4c2e1acd7..b0a4e3d949 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -16,17 +16,23 @@ module ActionDispatch # Examples for writing: # # # Sets a simple session cookie. + # # This cookie will be deleted when the user's browser is closed. # cookies[:user_name] = "david" # + # # Assign an array of values to a cookie. + # cookies[:lat_lon] = [47.68, -122.37] + # # # Sets a cookie that expires in 1 hour. # cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now } # # # Sets a signed cookie, which prevents a user from tampering with its value. - # # You must specify a value in ActionController::Base.cookie_verifier_secret. - # cookies.signed[:remember_me] = [current_user.id, current_user.salt] + # # The cookie is signed by your app's config.secret_token value. + # # Rails generates this value by default when you create a new Rails app. + # cookies.signed[:user_id] = current_user.id # # # Sets a "permanent" cookie (which expires in 20 years from now). # cookies.permanent[:login] = "XJ-122" + # # # You can also chain these methods: # cookies.permanent.signed[:login] = "XJ-122" # @@ -34,6 +40,7 @@ module ActionDispatch # # cookies[:user_name] # => "david" # cookies.size # => 2 + # cookies[:lat_lon] # => [47.68, -122.37] # # Example for deleting: # @@ -275,7 +282,7 @@ module ActionDispatch "integrity hash for cookie session data. Use " + "config.secret_token = \"some secret phrase of at " + "least #{SECRET_MIN_LENGTH} characters\"" + - "in config/application.rb" + "in config/initializers/secret_token.rb" end if secret.length < SECRET_MIN_LENGTH -- cgit v1.2.3 From 167964149e76d66742675a1505e1030e1c8f440b Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Sat, 27 Nov 2010 07:56:08 +1100 Subject: Add explicit statement that verify_authenticity_token can be turned off for actions. --- .../lib/action_controller/metal/request_forgery_protection.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 02f577647e..148efbb081 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -53,9 +53,13 @@ module ActionController #:nodoc: # class FooController < ApplicationController # protect_from_forgery :except => :index # - # # you can disable csrf protection on controller-by-controller basis: - # skip_before_filter :verify_authenticity_token - # end + # You can disable csrf protection on controller-by-controller basis: + # + # skip_before_filter :verify_authenticity_token + # + # It can also be disabled for specific controller actions: + # + # skip_before_filter :verify_authenticity_token, :except => [:create] # # Valid Options: # -- cgit v1.2.3 From 927c582acfb9253be493e7ec584c0503555e00fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 27 Nov 2010 08:12:49 -0800 Subject: Update CHANGELOG. --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 74d017cc3d..2ab2ca1542 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* url_for and named url helpers now accept :subdomain and :domain as options [Josh Kalderimis] + * Added config.action_controller.include_all_helpers. By default 'helper :all' is done in ActionController::Base, which includes all the helpers by default. Setting include_all_helpers to false will result in including only application_helper and helper corresponding to controller (like foo_helper for foo_controller). [Piotr Sarnacki] * Added a convenience idiom to generate HTML5 data-* attributes in tag helpers from a :data hash of options: -- cgit v1.2.3 From 1662aa1a15ad3f2218f85e4bd58aea56708a87a1 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Thu, 11 Nov 2010 05:27:40 +0900 Subject: Added a space before "do" keyword --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 92645f5cf9..50f065f03d 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -39,7 +39,7 @@ module ActionView # form_tag('/upload', :multipart => true) # # =>
# - # <%= form_tag('/posts')do -%> + # <%= form_tag('/posts') do -%> #
<%= submit_tag 'Save' %>
# <% end -%> # # =>
-- cgit v1.2.3 From 9bd291407c70daac1b2777f552f599a6fff9f387 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sat, 27 Nov 2010 22:16:51 -0500 Subject: make it clear that recompilation happens only in development mode --- actionpack/lib/action_view/base.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 1beae37af3..15944138f7 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -76,8 +76,8 @@ module ActionView #:nodoc: # # === Template caching # - # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will - # check the file's modification time and recompile it. + # By default, Rails will compile each template to a method in order to render it. When you alter a template, + # Rails will check the file's modification time and recompile it in development mode. # # == Builder # -- cgit v1.2.3 From a4c360e8c7b7c2635de3c1172dafff7b7975ecc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 28 Nov 2010 11:48:39 +0100 Subject: trailing star mimes should respect the order in which mime types are defined. --- actionpack/lib/action_dispatch/http/mime_type.rb | 18 +++++++++++------- actionpack/test/dispatch/mime_type_test.rb | 19 ++++++------------- 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 08eab5634a..3e3478a44e 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -115,15 +115,20 @@ module Mime end else # keep track of creation order to keep the subsequent sort stable - list = [] - accept_header.split(/,/).each_with_index do |header, index| + list, index = [], 0 + accept_header.split(/,/).each do |header| params, q = header.split(/;\s*q=/) - if params + if params.present? params.strip! + if params =~ TRAILING_STAR_REGEXP - parse_data_with_trailing_star($1).each { |m| list << AcceptItem.new(index, m.to_s, q) } + parse_data_with_trailing_star($1).each do |m| + list << AcceptItem.new(index, m.to_s, q) + index += 1 + end else - list << AcceptItem.new(index, params, q) unless params.empty? + list << AcceptItem.new(index, params, q) + index += 1 end end end @@ -178,8 +183,7 @@ module Mime # input: 'application' # returend value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM def parse_data_with_trailing_star(input) - keys = Mime::LOOKUP.keys.select{|k| k.include?(input)} - Mime::LOOKUP.values_at(*keys).uniq + Mime::SET.select { |m| m =~ input } end # This method is opposite of register method. diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 9424d88498..e80d339472 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -31,30 +31,23 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse text with trailing star at the beginning" do accept = "text/*, text/html, application/json, multipart/form-data" - expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::TEXT, Mime::YAML, Mime::JS, Mime::MULTIPART_FORM] + expect = [Mime::HTML, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::XML, Mime::YAML, Mime::JSON, Mime::MULTIPART_FORM] parsed = Mime::Type.parse(accept) - assert_equal expect.size, parsed.size - Range.new(0,expect.size-1).to_a.each do |index| - assert_equal expect[index], parsed[index], "Failed for index number #{index}" - end + assert_equal expect, parsed end test "parse text with trailing star in the end" do accept = "text/html, application/json, multipart/form-data, text/*" - expect = [Mime::HTML, Mime::JSON, Mime::MULTIPART_FORM, Mime::XML, Mime::ICS, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + expect = [Mime::HTML, Mime::JSON, Mime::MULTIPART_FORM, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::XML, Mime::YAML] parsed = Mime::Type.parse(accept) - assert_equal 10, parsed.size - Range.new(0,expect.size-1).to_a.each do |index| - assert_equal expect[index], parsed[index], "Failed for index number #{index}" - end + assert_equal expect, parsed end test "parse text with trailing star" do accept = "text/*" - expect = [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT].sort_by(&:to_s) + expect = [Mime::HTML, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::XML, Mime::YAML, Mime::JSON] parsed = Mime::Type.parse(accept) - assert_equal 9, parsed.size - assert_equal expect, parsed.sort_by(&:to_s) + assert_equal expect, parsed end test "parse application with trailing star" do -- cgit v1.2.3 From 31906eecdf7bffc2203379c5d40f1bb77fb35858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 28 Nov 2010 12:48:50 +0100 Subject: Fix tests on 1.9.2. --- actionpack/lib/action_dispatch/http/mime_type.rb | 15 +++++++++------ actionpack/test/controller/mime_responds_test.rb | 16 +++++++++------- actionpack/test/dispatch/mime_type_test.rb | 9 ++++----- actionpack/test/lib/controller/fake_models.rb | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 3e3478a44e..c1503c7eeb 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -190,12 +190,15 @@ module Mime # # Usage: # - # Mime::Type.unregister("text/x-mobile", :mobile) - def unregister(string, symbol) - EXTENSION_LOOKUP.delete(symbol.to_s) - LOOKUP.delete(string) - symbol = symbol.to_s.upcase.intern - Mime.module_eval { remove_const(symbol) if const_defined?(symbol) } + # Mime::Type.unregister(:mobile) + def unregister(symbol) + symbol = symbol.to_s.upcase + mime = Mime.const_get(symbol) + Mime.instance_eval { remove_const(symbol) } + + SET.delete_if { |v| v.eql?(mime) } + LOOKUP.delete_if { |k,v| v.eql?(mime) } + EXTENSION_LOOKUP.delete_if { |k,v| v.eql?(mime) } end end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 82969b2979..98c9d43b93 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -201,8 +201,8 @@ class RespondToControllerTest < ActionController::TestCase def teardown super - Mime::Type.unregister('text/x-mobile', :iphone) - Mime::Type.unregister('text/iphone', :mobile) + Mime::Type.unregister(:iphone) + Mime::Type.unregister(:mobile) end def test_html @@ -622,12 +622,14 @@ class RespondWithControllerTest < ActionController::TestCase def setup super @request.host = "www.example.com" + Mime::Type.register_alias('text/html', :iphone) + Mime::Type.register('text/x-mobile', :mobile) end def teardown super - Mime::Type.unregister('text/x-mobile', :iphone) - Mime::Type.unregister('text/iphone', :mobile) + Mime::Type.unregister(:iphone) + Mime::Type.unregister(:mobile) end def test_using_resource @@ -929,7 +931,8 @@ class RespondWithControllerTest < ActionController::TestCase @controller = RenderJsonRespondWithController.new @request.accept = "application/json" get :index, :format => :json - assert_equal %Q{{"message":"boom","error":"RenderJsonTestException"}}, @response.body + assert_match(/"message":"boom"/, @response.body) + assert_match(/"error":"RenderJsonTestException"/, @response.body) end def test_no_double_render_is_raised @@ -1020,8 +1023,7 @@ class MimeControllerLayoutsTest < ActionController::TestCase def teardown super - Mime::Type.unregister('text/x-mobile', :iphone) - Mime::Type.unregister('text/iphone', :mobile) + Mime::Type.unregister(:iphone) end def test_missing_layout_renders_properly diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index e80d339472..9782f328fc 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -19,7 +19,7 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal Mime::MOBILE, Mime::LOOKUP['text/x-mobile'] assert_equal Mime::MOBILE, Mime::EXTENSION_LOOKUP['mobile'] - Mime::Type.unregister("text/x-mobile", :mobile) + Mime::Type.unregister(:mobile) assert !defined?(Mime::MOBILE), "Mime::MOBILE should not be defined" assert !Mime::LOOKUP.has_key?('text/x-mobile'), "Mime::LOOKUP should not have key ['text/x-mobile]" assert !Mime::EXTENSION_LOOKUP.has_key?('mobile'), "Mime::EXTENSION_LOOKUP should not have key ['mobile]" @@ -52,10 +52,9 @@ class MimeTypeTest < ActiveSupport::TestCase test "parse application with trailing star" do accept = "application/*" - expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::PDF, Mime::URL_ENCODED_FORM].sort_by(&:to_s) + expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF] parsed = Mime::Type.parse(accept) - assert_equal 9, parsed.size - assert_equal expect, parsed.sort_by(&:to_s) + assert_equal expect, parsed end test "parse without q" do @@ -92,7 +91,7 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal Mime::GIF, Mime::SET.last end ensure - Mime::Type.unregister('image/gif', :gif) + Mime::Type.unregister(:gif) end end diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index bd18cdc1b8..67baf369e2 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -197,6 +197,6 @@ end class RenderJsonTestException < Exception def to_json(options = nil) - return { :error => self.class.name, :message => self.to_str }.to_json + return { :error => self.class.name, :message => self.to_s }.to_json end end -- cgit v1.2.3 From aa9a3227a0151af87e1eb5a6c4b7b0b095fc33c9 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 29 Nov 2010 21:38:37 -0500 Subject: Rewording existing comment --- actionpack/lib/abstract_controller/layouts.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index b68c7d9216..606f7eedec 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -235,13 +235,10 @@ module AbstractController controller_path end - # Takes the specified layout and creates a _layout method to be called - # by _default_layout + # Creates a _layout method to be called by _default_layout . # - # If there is no explicit layout specified: - # If a layout is found in the view paths with the controller's - # name, return that string. Otherwise, use the superclass' - # layout (which might also be implied) + # If a layout is not explicitly mentioned then look for a layout with the controller's name. + # if nothing is found then try same procedure to find super class's layout. def _write_layout_method remove_possible_method(:_layout) -- cgit v1.2.3 From 3c7a33c0510e30a3017b007d8ed8afcae02ef4a6 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 30 Nov 2010 10:00:47 -0500 Subject: Rewording existing comment --- actionpack/lib/abstract_controller/base.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index f83eaded88..c384fd0978 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -31,10 +31,9 @@ module AbstractController # A list of all internal methods for a controller. This finds the first # abstract superclass of a controller, and gets a list of all public # instance methods on that abstract class. Public instance methods of - # a controller would normally be considered action methods, so we - # are removing those methods on classes declared as abstract - # (ActionController::Metal and ActionController::Base are defined - # as abstract) + # a controller would normally be considered action methods, so methods + # declared on abstract classes are being removed. + # (ActionController::Metal and ActionController::Base are defined as abstract) def internal_methods controller = self controller = controller.superclass until controller.abstract? -- cgit v1.2.3 From 0bda6f1ec664fcfd1b312492a6419e3d76d5baa7 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 30 Nov 2010 16:36:01 +0100 Subject: The redirect routing method now allows for a hash of options which only changes the relevant parts of the url, or an object which responds to call can be supplied so common redirect rules can be easily reused. This commit includes a change where url generation from parts has been moved to AD::Http::URL as a class method. --- actionpack/lib/action_dispatch/http/url.rb | 52 ++ actionpack/lib/action_dispatch/routing/mapper.rb | 39 +- .../lib/action_dispatch/routing/redirection.rb | 81 +++ .../lib/action_dispatch/routing/route_set.rb | 62 +-- actionpack/test/controller/routing_test.rb | 581 +++++++++++---------- actionpack/test/dispatch/request_test.rb | 25 + actionpack/test/dispatch/routing_test.rb | 48 ++ 7 files changed, 525 insertions(+), 363 deletions(-) create mode 100644 actionpack/lib/action_dispatch/routing/redirection.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 1e7054f381..51d4766282 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -24,6 +24,58 @@ module ActionDispatch !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) end + def self.url_for(options = {}) + unless options[:host].present? || options[:only_path].present? + raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true' + end + + rewritten_url = "" + + unless options[:only_path] + rewritten_url << (options[:protocol] || "http") + rewritten_url << "://" unless rewritten_url.match("://") + rewritten_url << rewrite_authentication(options) + rewritten_url << host_or_subdomain_and_domain(options) + rewritten_url << ":#{options.delete(:port)}" if options[:port] + end + + path = options.delete(:path) || '' + + params = options[:params] || {} + params.reject! {|k,v| !v } + + rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) + rewritten_url << "?#{params.to_query}" unless params.empty? + rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] + rewritten_url + end + + class << self + private + + def rewrite_authentication(options) + if options[:user] && options[:password] + "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@" + else + "" + end + end + + def host_or_subdomain_and_domain(options) + return options[:host] unless options[:subdomain] || options[:domain] + + tld_length = options[:tld_length] || @@tld_length + + host = "" + host << (options[:subdomain] || extract_subdomain(options[:host], tld_length)) + host << "." + host << (options[:domain] || extract_domain(options[:host], tld_length)) + host + end + + end + + # Returns the complete URL used for this request. def url diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 880862c909..05b7147c70 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -2,6 +2,7 @@ require 'erb' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/object/blank' require 'active_support/inflector' +require 'action_dispatch/routing/redirection' module ActionDispatch module Routing @@ -383,39 +384,6 @@ module ActionDispatch map_method(:delete, *args, &block) end - # Redirect any path to another path: - # - # match "/stories" => redirect("/posts") - def redirect(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - - path = args.shift || Proc.new - path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params) } - status = options[:status] || 301 - - lambda do |env| - req = Request.new(env) - - params = [req.symbolized_path_parameters] - params << req if path_proc.arity > 1 - - uri = URI.parse(path_proc.call(*params)) - uri.scheme ||= req.scheme - uri.host ||= req.host - uri.port ||= req.port unless req.standard_port? - - body = %(You are being redirected.) - - headers = { - 'Location' => uri.to_s, - 'Content-Type' => 'text/html', - 'Content-Length' => body.length.to_s - } - - [ status, headers, [body] ] - end - end - private def map_method(method, *args, &block) options = args.extract_options! @@ -638,7 +606,7 @@ module ActionDispatch :shallow_path => path, :shallow_prefix => path }.merge!(options) scope(options) { yield } end - + # === Parameter Restriction # Allows you to constrain the nested routes based on a set of rules. # For instance, in order to change the routes to allow for a dot character in the +id+ parameter: @@ -649,7 +617,7 @@ module ActionDispatch # # Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be. # The +id+ parameter must match the constraint passed in for this example. - # + # # You may use this to also resrict other parameters: # # resources :posts do @@ -1340,6 +1308,7 @@ module ActionDispatch include Base include HttpHelpers + include Redirection include Scoping include Resources include Shorthand diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb new file mode 100644 index 0000000000..d9c9a400a7 --- /dev/null +++ b/actionpack/lib/action_dispatch/routing/redirection.rb @@ -0,0 +1,81 @@ +require 'action_dispatch/http/request' + +module ActionDispatch + module Routing + module Redirection + + # Redirect any path to another path: + # + # match "/stories" => redirect("/posts") + def redirect(*args, &block) + options = args.last.is_a?(Hash) ? args.pop : {} + status = options.delete(:status) || 301 + + path = args.shift + + path_proc = if path.is_a?(String) + proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params) } + elsif options.any? + options_proc(options) + elsif path.respond_to?(:call) + proc { |params, request| path.call(params, request) } + elsif block + block + else + raise ArgumentError, "redirection argument not supported" + end + + redirection_proc(status, path_proc) + end + + private + + def options_proc(options) + proc do |params, request| + path = if options[:path].nil? + request.path + elsif params.empty? || !options[:path].match(/%\{\w*\}/) + options.delete(:path) + else + (options.delete(:path) % params) + end + + default_options = { + :protocol => request.protocol, + :host => request.host, + :port => request.optional_port, + :path => path, + :params => request.query_parameters + } + + ActionDispatch::Http::URL.url_for(options.reverse_merge(default_options)) + end + end + + def redirection_proc(status, path_proc) + lambda do |env| + req = Request.new(env) + + params = [req.symbolized_path_parameters] + params << req if path_proc.arity > 1 + + uri = URI.parse(path_proc.call(*params)) + uri.scheme ||= req.scheme + uri.host ||= req.host + uri.port ||= req.port unless req.standard_port? + + body = %(You are being redirected.) + + headers = { + 'Location' => uri.to_s, + 'Content-Type' => 'text/html', + 'Content-Length' => body.length.to_s + } + + [ status, headers, [body] ] + end + end + + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index ebced9cabe..03bfe178e5 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -442,12 +442,9 @@ module ActionDispatch raise_routing_error unless path - params.reject! {|k,v| !v } - return [path, params.keys] if @extras - path << "?#{params.to_query}" unless params.empty? - path + [path, params] rescue Rack::Mount::RoutingError raise_routing_error end @@ -486,7 +483,7 @@ module ActionDispatch end RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length, - :trailing_slash, :script_name, :anchor, :params, :only_path ] + :trailing_slash, :anchor, :params, :only_path, :script_name] def _generate_prefix(options = {}) nil @@ -498,29 +495,24 @@ module ActionDispatch handle_positional_args(options) - rewritten_url = "" - - path_segments = options.delete(:_path_segments) - unless options[:only_path] - rewritten_url << (options[:protocol] || "http") - rewritten_url << "://" unless rewritten_url.match("://") - rewritten_url << rewrite_authentication(options) - rewritten_url << host_from_options(options) - rewritten_url << ":#{options.delete(:port)}" if options[:port] - end + user, password = extract_authentication(options) + path_segments = options.delete(:_path_segments) + script_name = options.delete(:script_name) - script_name = options.delete(:script_name) path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? - path << generate(path_options, path_segments || {}) - # ROUTES TODO: This can be called directly, so script_name should probably be set in the routes - rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) - rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] + path_addition, params = generate(path_options, path_segments || {}) + path << path_addition - rewritten_url + ActionDispatch::Http::URL.url_for(options.merge({ + :path => path, + :params => params, + :user => user, + :password => password + })) end def call(env) @@ -561,23 +553,12 @@ module ActionDispatch private - def host_from_options(options) - computed_host = subdomain_and_domain(options) || options[:host] - unless computed_host - raise ArgumentError, "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" + def extract_authentication(options) + if options[:user] && options[:password] + [options.delete(:user), options.delete(:password)] + else + nil end - computed_host - end - - def subdomain_and_domain(options) - return nil unless options[:subdomain] || options[:domain] - tld_length = options[:tld_length] || ActionDispatch::Http::URL.tld_length - - host = "" - host << (options[:subdomain] || ActionDispatch::Http::URL.extract_subdomain(options[:host], tld_length)) - host << "." - host << (options[:domain] || ActionDispatch::Http::URL.extract_domain(options[:host], tld_length)) - host end def handle_positional_args(options) @@ -590,13 +571,6 @@ module ActionDispatch options.merge!(Hash[args.zip(keys).map { |v, k| [k, v] }]) end - def rewrite_authentication(options) - if options[:user] && options[:password] - "#{Rack::Utils.escape(options.delete(:user))}:#{Rack::Utils.escape(options.delete(:password))}@" - else - "" - end - end end end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index cd067b7d18..89f0d03c56 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -12,8 +12,16 @@ end ROUTING = ActionDispatch::Routing +module RoutingTestHelpers + def url_for(set, options, recall = nil) + set.send(:url_for, options.merge(:only_path => true, :_path_segments => recall)) + end +end + # See RFC 3986, section 3.3 for allowed path characters. class UriReservedCharactersRoutingTest < Test::Unit::TestCase + include RoutingTestHelpers + def setup @set = ActionDispatch::Routing::RouteSet.new @set.draw do @@ -28,12 +36,13 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase end def test_route_generation_escapes_unsafe_path_characters - @set.generate(:controller => "content", :action => "act#{@segment}ion", :variable => "variable", :additional => "foo") assert_equal "/content/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2", - @set.generate(:controller => "content", - :action => "act#{@segment}ion", - :variable => "var#{@segment}iable", - :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"]) + url_for(@set, { + :controller => "content", + :action => "act#{@segment}ion", + :variable => "var#{@segment}iable", + :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] + }) end def test_route_recognition_unescapes_path_components @@ -45,10 +54,13 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase end def test_route_generation_allows_passing_non_string_values_to_generated_helper - assert_equal "/content/action/variable/1/2", @set.generate(:controller => "content", - :action => "action", - :variable => "variable", - :additional => [1, 2]) + assert_equal "/content/action/variable/1/2", + url_for(@set, { + :controller => "content", + :action => "action", + :variable => "variable", + :additional => [1, 2] + }) end end @@ -68,6 +80,8 @@ class MockController end class LegacyRouteSetTests < Test::Unit::TestCase + include RoutingTestHelpers + attr_reader :rs def setup @@ -81,18 +95,18 @@ class LegacyRouteSetTests < Test::Unit::TestCase def test_default_setup @rs.draw { match '/:controller(/:action(/:id))' } assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content")) - assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list")) + assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list")) assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10")) assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10")) - assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10) + assert_equal '/admin/user/show/10', url_for(rs, { :controller => 'admin/user', :action => 'show', :id => 10 }) - assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) - assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal '/admin/user/show', url_for(rs, { :action => 'show' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) + assert_equal '/admin/user/list/10', url_for(rs, {}, { :controller => 'admin/user', :action => 'list', :id => '10' }) - assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) - assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal '/admin/stuff', url_for(rs, { :controller => 'stuff' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) + assert_equal '/stuff', url_for(rs, { :controller => '/stuff' }, { :controller => 'admin/user', :action => 'list', :id => '10' }) end def test_ignores_leading_slash @@ -143,11 +157,14 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/ match '/:controller(/:action(/:id))' end + assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"}, rs.recognize_path("/admin/user/foo")) - assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo")) - assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index") - assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo") + assert_equal({:controller => "content", :action => "foo"}, + rs.recognize_path("/content/foo")) + + assert_equal '/admin/user/foo', url_for(rs, { :controller => "admin/user", :admintoken => "foo", :action => "index" }) + assert_equal '/content/foo', url_for(rs, { :controller => "content", :action => "foo" }) end def test_route_with_regexp_and_captures_for_controller @@ -169,17 +186,16 @@ class LegacyRouteSetTests < Test::Unit::TestCase end # Without a file extension assert_equal '/user/download/file', - rs.generate(:controller => "user", :action => "download", :file => "file") - assert_equal( - {:controller => "user", :action => "download", :file => "file"}, + url_for(rs, { :controller => "user", :action => "download", :file => "file" }) + + assert_equal({:controller => "user", :action => "download", :file => "file"}, rs.recognize_path("/user/download/file")) # Now, let's try a file with an extension, really a dot (.) assert_equal '/user/download/file.jpg', - rs.generate( - :controller => "user", :action => "download", :file => "file.jpg") - assert_equal( - {:controller => "user", :action => "download", :file => "file.jpg"}, + url_for(rs, { :controller => "user", :action => "download", :file => "file.jpg" }) + + assert_equal({:controller => "user", :action => "download", :file => "file.jpg"}, rs.recognize_path("/user/download/file.jpg")) end @@ -187,28 +203,25 @@ class LegacyRouteSetTests < Test::Unit::TestCase rs.draw do root :to => 'content#list', :as => 'home' end - x = setup_for_named_route - assert_equal("http://test.host/", - x.send(:home_url)) + assert_equal("http://test.host/", setup_for_named_route.send(:home_url)) end def test_named_route_with_option rs.draw do match 'page/:title' => 'content#show_page', :as => 'page' end - x = setup_for_named_route + assert_equal("http://test.host/page/new%20stuff", - x.send(:page_url, :title => 'new stuff')) + setup_for_named_route.send(:page_url, :title => 'new stuff')) end def test_named_route_with_default rs.draw do match 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page' end - x = setup_for_named_route - assert_equal("http://test.host/page/AboutRails", - x.send(:page_url, :title => "AboutRails")) + assert_equal("http://test.host/page/AboutRails", + setup_for_named_route.send(:page_url, :title => "AboutRails")) end def test_named_route_with_path_prefix @@ -217,9 +230,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase match 'page' => 'content#show_page', :as => 'page' end end - x = setup_for_named_route + assert_equal("http://test.host/my/page", - x.send(:page_url)) + setup_for_named_route.send(:page_url)) end def test_named_route_with_blank_path_prefix @@ -228,27 +241,33 @@ class LegacyRouteSetTests < Test::Unit::TestCase match 'page' => 'content#show_page', :as => 'page' end end - x = setup_for_named_route + assert_equal("http://test.host/page", - x.send(:page_url)) + setup_for_named_route.send(:page_url)) end def test_named_route_with_nested_controller rs.draw do match 'admin/user' => 'admin/user#index', :as => "users" end - x = setup_for_named_route + assert_equal("http://test.host/admin/user", - x.send(:users_url)) + setup_for_named_route.send(:users_url)) end def test_optimised_named_route_with_host rs.draw do match 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' end - x = setup_for_named_route - x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => 'pages').once - x.send(:pages_url) + routes = setup_for_named_route + routes.expects(:url_for).with({ + :host => 'foo.com', + :only_path => false, + :controller => 'content', + :action => 'show_page', + :use_route => 'pages' + }).once + routes.send(:pages_url) end def setup_for_named_route @@ -265,9 +284,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase rs.draw do root :to => "hello#index" end - x = setup_for_named_route - assert_equal("http://test.host/", x.send(:root_url)) - assert_equal("/", x.send(:root_path)) + routes = setup_for_named_route + assert_equal("http://test.host/", routes.send(:root_url)) + assert_equal("/", routes.send(:root_path)) end def test_named_route_with_regexps @@ -276,24 +295,19 @@ class LegacyRouteSetTests < Test::Unit::TestCase :year => /\d+/, :month => /\d+/, :day => /\d+/ match ':controller/:action/:id' end - x = setup_for_named_route - # assert_equal( - # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false}, - # x.send(:article_url, :title => 'hi') - # ) - assert_equal( - "http://test.host/page/2005/6/10/hi", - x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6) - ) + + routes = setup_for_named_route + + assert_equal "http://test.host/page/2005/6/10/hi", + routes.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6) end def test_changing_controller @rs.draw { match ':controller/:action/:id' } - assert_equal '/admin/stuff/show/10', rs.generate( - {:controller => 'stuff', :action => 'show', :id => 10}, - {:controller => 'admin/user', :action => 'index'} - ) + assert_equal '/admin/stuff/show/10', + url_for(rs, {:controller => 'stuff', :action => 'show', :id => 10}, + {:controller => 'admin/user', :action => 'index'}) end def test_paths_escaped @@ -319,8 +333,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase end # No / to %2F in URI, only for query params. - x = setup_for_named_route - assert_equal("/file/hello/world", x.send(:path_path, ['hello', 'world'])) + assert_equal("/file/hello/world", setup_for_named_route.send(:path_path, ['hello', 'world'])) end def test_non_controllers_cannot_be_matched @@ -334,7 +347,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase rs.draw do match 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post' end - assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") } + assert_raise(ActionController::RoutingError) do + url_for(rs, { :controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post" }) + end end def test_dynamic_path_allowed @@ -342,7 +357,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase match '*path' => 'content#show_file' end - assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo)) + assert_equal '/pages/boo', + url_for(rs, { :controller => 'content', :action => 'show_file', :path => %w(pages boo) }) end def test_dynamic_recall_paths_allowed @@ -350,7 +366,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase match '*path' => 'content#show_file' end - assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => %w(pages boo)) + assert_equal '/pages/boo', + url_for(rs, {}, { :controller => 'content', :action => 'show_file', :path => %w(pages boo) }) end def test_backwards @@ -359,9 +376,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller(/:action(/:id))' end - assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'}) - assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show') - assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo') + assert_equal '/page/20', url_for(rs, { :id => 20 }, { :controller => 'pages', :action => 'show' }) + assert_equal '/page/20', url_for(rs, { :controller => 'pages', :id => 20, :action => 'show' }) + assert_equal '/pages/boo', url_for(rs, { :controller => 'pages', :action => 'boo' }) end def test_route_with_fixnum_default @@ -370,10 +387,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller/:action/:id' end - assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page') - assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1) - assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1') - assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10) + assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page' }) + assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page', :id => 1 }) + assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page', :id => '1' }) + assert_equal '/page/10', url_for(rs, { :controller => 'content', :action => 'show_page', :id => 10 }) assert_equal({:controller => "content", :action => 'show_page', :id => 1 }, rs.recognize_path("/page")) assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1")) @@ -387,20 +404,20 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller/:action/:id' end - assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo') - assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo")) + assert_equal '/page/foo', url_for(rs, { :controller => 'content', :action => 'show_page', :id => 'foo' }) + assert_equal({ :controller => "content", :action => 'show_page', :id => 'foo' }, rs.recognize_path("/page/foo")) token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian token.force_encoding(Encoding::BINARY) if token.respond_to?(:force_encoding) escaped_token = CGI::escape(token) - assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token) - assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}")) + assert_equal '/page/' + escaped_token, url_for(rs, { :controller => 'content', :action => 'show_page', :id => token }) + assert_equal({ :controller => "content", :action => 'show_page', :id => token }, rs.recognize_path("/page/#{escaped_token}")) end def test_action_expiry @rs.draw { match ':controller(/:action(/:id))' } - assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'}) + assert_equal '/content', url_for(rs, { :controller => 'content' }, { :controller => 'content', :action => 'show' }) end def test_requirement_should_prevent_optional_id @@ -408,10 +425,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase match 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post' end - assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10) + assert_equal '/post/10', url_for(rs, { :controller => 'post', :action => 'show', :id => 10 }) assert_raise ActionController::RoutingError do - rs.generate(:controller => 'post', :action => 'show') + url_for(rs, { :controller => 'post', :action => 'show' }) end end @@ -424,12 +441,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller/:action/:id' end - assert_equal '/test', rs.generate(:controller => 'post', :action => 'show') - assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil) + assert_equal '/test', url_for(rs, { :controller => 'post', :action => 'show' }) + assert_equal '/test', url_for(rs, { :controller => 'post', :action => 'show', :year => nil }) - x = setup_for_named_route - assert_equal("http://test.host/test", - x.send(:blog_url)) + assert_equal("http://test.host/test", setup_for_named_route.send(:blog_url)) end def test_set_to_nil_forgets @@ -439,20 +454,20 @@ class LegacyRouteSetTests < Test::Unit::TestCase end assert_equal '/pages/2005', - rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005) + url_for(rs, { :controller => 'content', :action => 'list_pages', :year => 2005 }) assert_equal '/pages/2005/6', - rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6) + url_for(rs, { :controller => 'content', :action => 'list_pages', :year => 2005, :month => 6 }) assert_equal '/pages/2005/6/12', - rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12) + url_for(rs, { :controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12 }) assert_equal '/pages/2005/6/4', - rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + url_for(rs, { :day => 4 }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) assert_equal '/pages/2005/6', - rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + url_for(rs, { :day => nil }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) assert_equal '/pages/2005', - rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + url_for(rs, { :day => nil, :month => nil }, { :controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12' }) end def test_root_url_generation_with_controller_and_action @@ -460,8 +475,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase root :to => "content#index" end - assert_equal '/', rs.generate(:controller => 'content', :action => 'index') - assert_equal '/', rs.generate(:controller => 'content') + assert_equal '/', url_for(rs, { :controller => 'content', :action => 'index' }) + assert_equal '/', url_for(rs, { :controller => 'content' }) end def test_named_root_url_generation_with_controller_and_action @@ -469,12 +484,10 @@ class LegacyRouteSetTests < Test::Unit::TestCase root :to => "content#index", :as => 'home' end - assert_equal '/', rs.generate(:controller => 'content', :action => 'index') - assert_equal '/', rs.generate(:controller => 'content') + assert_equal '/', url_for(rs, { :controller => 'content', :action => 'index' }) + assert_equal '/', url_for(rs, { :controller => 'content' }) - x = setup_for_named_route - assert_equal("http://test.host/", - x.send(:home_url)) + assert_equal("http://test.host/", setup_for_named_route.send(:home_url)) end def test_named_route_method @@ -483,8 +496,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller(/:action(/:id))' end - assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories') - assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'}) + assert_equal '/categories', url_for(rs, { :controller => 'content', :action => 'categories' }) + assert_equal '/content/hi', url_for(rs, { :controller => 'content', :action => 'hi' }) end def test_named_routes_array @@ -499,7 +512,12 @@ class LegacyRouteSetTests < Test::Unit::TestCase match ':controller/:action/:id' end - assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil) + assert_equal '/journal', url_for(rs, { + :controller => 'content', + :action => 'list_journal', + :date => nil, + :user_id => nil + }) end def setup_request_method_routes_for(method) @@ -564,9 +582,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase match '/posts/new/:action' => 'subpath_books' end - assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit") - assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete") - assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview") + assert_equal "/books/7/edit", url_for(rs, { :controller => "subpath_books", :id => 7, :action => "edit" }) + assert_equal "/items/15/complete", url_for(rs, { :controller => "subpath_books", :id => 15, :action => "complete" }) + assert_equal "/posts/new/preview", url_for(rs, { :controller => "subpath_books", :action => "preview" }) end def test_failed_constraints_raises_exception_with_violated_constraints @@ -574,9 +592,8 @@ class LegacyRouteSetTests < Test::Unit::TestCase match 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ } end - x = setup_for_named_route assert_raise(ActionController::RoutingError) do - x.send(:foo_with_requirement_url, "I am Against the constraints") + setup_for_named_route.send(:foo_with_requirement_url, "I am Against the constraints") end end @@ -606,11 +623,12 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_not_nil hash assert_equal %w(cc ac), [hash[:controller], hash[:action]] - end end class RouteSetTest < ActiveSupport::TestCase + include RoutingTestHelpers + def set @set ||= ROUTING::RouteSet.new end @@ -657,7 +675,8 @@ class RouteSetTest < ActiveSupport::TestCase match ':controller/:action/:id.:format' match ':controller/:action/:id' end - assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello") + assert_equal "/foo/bar/15?this=hello", + url_for(set, { :controller => "foo", :action => "bar", :id => 15, :this => "hello" }) end def test_extra_keys_not_first @@ -742,7 +761,7 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal "http://test.host/admin/users", controller.send(:users_url) assert_equal '/admin/users', controller.send(:users_path) - assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'}) + assert_equal '/admin/users', url_for(set, controller.send(:hash_for_users_url), { :controller => 'users', :action => 'index' }) end def test_named_route_url_method_with_anchor @@ -813,8 +832,8 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal 1, set.routes.size - assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10) - assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10) + assert_equal '/users/show/10', url_for(set, { :controller => 'users', :action => 'show', :id => 10 }) + assert_equal '/users/index/10', url_for(set, { :controller => 'users', :id => 10 }) assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10')) assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/')) @@ -992,7 +1011,7 @@ class RouteSetTest < ActiveSupport::TestCase match "/people/list", :controller => "people", :action => "list" end - url = set.generate(:controller => "people", :action => "list") + url = url_for(set, { :controller => "people", :action => "list" }) assert_equal "/people/list", url end @@ -1057,8 +1076,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_changes_controller_module set.draw { match ':controller/:action/:id' } current = { :controller => "bling/bloop", :action => "bap", :id => 9 } - url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current) - assert_equal "/foo/bar/baz/7", url + + assert_equal "/foo/bar/baz/7", + url_for(set, { :controller => "foo/bar", :action => "baz", :id => 7 }, current) end def test_id_is_sticky_when_it_ought_to_be @@ -1066,7 +1086,7 @@ class RouteSetTest < ActiveSupport::TestCase match ':controller/:id/:action' end - url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"}) + url = url_for(set, { :action => "destroy" }, { :controller => "people", :action => "show", :id => "7" }) assert_equal "/people/7/destroy", url end @@ -1076,8 +1096,9 @@ class RouteSetTest < ActiveSupport::TestCase match ':controller/:action/:id' end - url = set.generate({:controller => "welcome", :action => "about"}, - {:controller => "welcome", :action => "get", :id => "7"}) + url = url_for(set, { :controller => "welcome", :action => "about" }, + { :controller => "welcome", :action => "get", :id => "7" }) + assert_equal "/about", url end @@ -1085,7 +1106,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw { match ':controller/:action/:id' } args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } - assert_equal "/foo/bar/7?x=y", set.generate(args) + assert_equal "/foo/bar/7?x=y", url_for(set, args) assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args) assert_equal [:x], set.extra_keys(args) end @@ -1098,7 +1119,7 @@ class RouteSetTest < ActiveSupport::TestCase end args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } - assert_equal "/my/foo/bar/7?x=y", set.generate(args) + assert_equal "/my/foo/bar/7?x=y", url_for(set, args) end def test_generate_with_blank_path_prefix @@ -1109,7 +1130,7 @@ class RouteSetTest < ActiveSupport::TestCase end args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } - assert_equal "/foo/bar/7?x=y", set.generate(args) + assert_equal "/foo/bar/7?x=y", url_for(set, args) end def test_named_routes_are_never_relative_to_modules @@ -1119,10 +1140,10 @@ class RouteSetTest < ActiveSupport::TestCase match '/connection' => 'connection#index', :as => 'family_connection' end - url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'}) + url = url_for(set, { :controller => "connection" }, { :controller => 'connection/manage' }) assert_equal "/connection/connection", url - url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'}) + url = url_for(set, { :use_route => :family_connection, :controller => "connection" }, { :controller => 'connection/manage' }) assert_equal "/connection", url end @@ -1130,7 +1151,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do match ':controller(/:action(/:id))' end - assert_equal '/books', set.generate( + assert_equal '/books', url_for(set, {:controller => 'books', :action => 'index'}, {:controller => 'books', :action => 'show', :id => '10'} ) @@ -1141,7 +1162,7 @@ class RouteSetTest < ActiveSupport::TestCase match 'show_weblog/:parameter' => 'weblog#show' match ':controller(/:action(/:id))' end - assert_equal '/weblog/edit?parameter=1', set.generate( + assert_equal '/weblog/edit?parameter=1', url_for(set, {:action => 'edit', :parameter => 1}, {:controller => 'weblog', :action => 'show', :parameter => 1} ) @@ -1152,12 +1173,12 @@ class RouteSetTest < ActiveSupport::TestCase match '/posts(.:format)' => 'posts#index' end - assert_equal '/posts', set.generate( + assert_equal '/posts', url_for(set, {:controller => 'posts'}, {:controller => 'posts', :action => 'index', :format => 'xml'} ) - assert_equal '/posts.xml', set.generate( + assert_equal '/posts.xml', url_for(set, {:controller => 'posts', :format => 'xml'}, {:controller => 'posts', :action => 'index', :format => 'xml'} ) @@ -1165,9 +1186,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_expiry_determination_should_consider_values_with_to_param set.draw { match 'projects/:project_id/:controller/:action' } - assert_equal '/projects/1/weblog/show', set.generate( - {:action => 'show', :project_id => 1}, - {:controller => 'weblog', :action => 'show', :project_id => '1'}) + assert_equal '/projects/1/weblog/show', url_for(set, + { :action => 'show', :project_id => 1 }, + { :controller => 'weblog', :action => 'show', :project_id => '1' }) end def test_named_route_in_nested_resource @@ -1208,7 +1229,7 @@ class RouteSetTest < ActiveSupport::TestCase assert_raise ArgumentError do set.draw do match 'page/:name' => 'pages#show', - :constraints => {:name => /(david|jamis)/m} + :constraints => { :name => /(david|jamis)/m } end end end @@ -1217,18 +1238,18 @@ class RouteSetTest < ActiveSupport::TestCase assert_nothing_raised do set.draw do match 'page/:name' => 'pages#show', - :constraints => {:name => /(david|jamis)/i} + :constraints => { :name => /(david|jamis)/i } end end assert_nothing_raised do set.draw do match 'page/:name' => 'pages#show', - :constraints => {:name => / # Desperately overcommented regexp + :constraints => { :name => / # Desperately overcommented regexp ( #Either david #The Creator | #Or jamis #The Deployer - )/x} + )/x } end end end @@ -1251,12 +1272,12 @@ class RouteSetTest < ActiveSupport::TestCase :constraints => {:name => /(david|jamis)/i} end - url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) + url = url_for(set, { :controller => 'pages', :action => 'show', :name => 'david' }) assert_equal "/page/david", url assert_raise ActionController::RoutingError do - url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) + url_for(set, { :controller => 'pages', :action => 'show', :name => 'davidjamis' }) end - url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) + url = url_for(set, { :controller => 'pages', :action => 'show', :name => 'JAMIS' }) assert_equal "/page/JAMIS", url end @@ -1280,7 +1301,7 @@ class RouteSetTest < ActiveSupport::TestCase end end - def test_route_requirement_generate_with_xi_modifiers + def test_route_requirement_with_xi_modifiers set.draw do match 'page/:name' => 'pages#show', :constraints => {:name => / # Desperately overcommented regexp @@ -1291,21 +1312,11 @@ class RouteSetTest < ActiveSupport::TestCase )/xi} end - url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) - assert_equal "/page/JAMIS", url - end + assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, + set.recognize_path('/page/JAMIS')) - def test_route_requirement_recognize_with_xi_modifiers - set.draw do - match 'page/:name' => 'pages#show', - :constraints => {:name => / # Desperately overcommented regexp - ( #Either - david #The Creator - | #Or - jamis #The Deployer - )/xi} - end - assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS')) + assert_equal "/page/JAMIS", + url_for(set, { :controller => 'pages', :action => 'show', :name => 'JAMIS' }) end def test_routes_with_symbols @@ -1323,8 +1334,8 @@ class RouteSetTest < ActiveSupport::TestCase match '/hello' => 'bar#index' end - assert_equal '/', set.generate(:controller => 'foo') - assert_equal '/hello', set.generate(:controller => 'bar') + assert_equal '/', url_for(set, { :controller => 'foo' }) + assert_equal '/hello', url_for(set, { :controller => 'bar' }) assert_equal({:controller => "foo", :action => "index"}, set.recognize_path('/')) assert_equal({:controller => "bar", :action => "index"}, set.recognize_path('/hello')) @@ -1335,7 +1346,7 @@ class RouteSetTest < ActiveSupport::TestCase match '/cars/:action/:person/:car/', :controller => 'cars' end - assert_equal '/cars/buy/1/2', set.generate(:controller => 'cars', :action => 'buy', :person => '1', :car => '2') + assert_equal '/cars/buy/1/2', url_for(set, { :controller => 'cars', :action => 'buy', :person => '1', :car => '2' }) assert_equal({:controller => "cars", :action => "buy", :person => "1", :car => "2"}, set.recognize_path('/cars/buy/1/2')) end @@ -1345,7 +1356,7 @@ class RouteSetTest < ActiveSupport::TestCase match '/books/:action.rss', :controller => 'books' end - assert_equal '/books/list.rss', set.generate(:controller => 'books', :action => 'list') + assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list' }) assert_equal({:controller => "books", :action => "list"}, set.recognize_path('/books/list.rss')) end @@ -1355,14 +1366,14 @@ class RouteSetTest < ActiveSupport::TestCase match '/books(/:action(.:format))', :controller => 'books' end - assert_equal '/books/list.rss', set.generate(:controller => 'books', :action => 'list', :format => 'rss') - assert_equal '/books/list.xml', set.generate(:controller => 'books', :action => 'list', :format => 'xml') - assert_equal '/books/list', set.generate(:controller => 'books', :action => 'list') - assert_equal '/books', set.generate(:controller => 'books', :action => 'index') + assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list', :format => 'rss' }) + assert_equal '/books/list.xml', url_for(set, { :controller => 'books', :action => 'list', :format => 'xml' }) + assert_equal '/books/list', url_for(set, { :controller => 'books', :action => 'list' }) + assert_equal '/books', url_for(set, { :controller => 'books', :action => 'index' }) assert_equal({:controller => "books", :action => "list", :format => "rss"}, set.recognize_path('/books/list.rss')) assert_equal({:controller => "books", :action => "list", :format => "xml"}, set.recognize_path('/books/list.xml')) - assert_equal({:controller => "books", :action => "list"}, set.recognize_path('/books/list')) + assert_equal({:controller => "books", :action => "list"}, set.recognize_path('/books/list')) assert_equal({:controller => "books", :action => "index"}, set.recognize_path('/books')) end @@ -1370,13 +1381,13 @@ class RouteSetTest < ActiveSupport::TestCase @set = nil set.draw { match("/:controller(/:action(/:id))") } - assert_equal '/content', set.generate(:controller => 'content', :action => 'index') - assert_equal '/content/list', set.generate(:controller => 'content', :action => 'list') - assert_equal '/content/show/1', set.generate(:controller => 'content', :action => 'show', :id => '1') + assert_equal '/content', url_for(set, { :controller => 'content', :action => 'index' }) + assert_equal '/content/list', url_for(set, { :controller => 'content', :action => 'list' }) + assert_equal '/content/show/1', url_for(set, { :controller => 'content', :action => 'show', :id => '1' }) assert_equal({:controller => "content", :action => "index"}, set.recognize_path('/content')) assert_equal({:controller => "content", :action => "index"}, set.recognize_path('/content/index')) - assert_equal({:controller => "content", :action => "list"}, set.recognize_path('/content/list')) + assert_equal({:controller => "content", :action => "list"}, set.recognize_path('/content/list')) assert_equal({:controller => "content", :action => "show", :id => "1"}, set.recognize_path('/content/show/1')) end @@ -1401,54 +1412,54 @@ class RouteSetTest < ActiveSupport::TestCase end def test_default_route_should_omit_default_action - assert_equal '/accounts', default_route_set.generate({:controller => 'accounts', :action => 'index'}) + assert_equal '/accounts', url_for(default_route_set, { :controller => 'accounts', :action => 'index' }) end def test_default_route_should_include_default_action_when_id_present - assert_equal '/accounts/index/20', default_route_set.generate({:controller => 'accounts', :action => 'index', :id => '20'}) + assert_equal '/accounts/index/20', url_for(default_route_set, { :controller => 'accounts', :action => 'index', :id => '20' }) end def test_default_route_should_work_with_action_but_no_id - assert_equal '/accounts/list_all', default_route_set.generate({:controller => 'accounts', :action => 'list_all'}) + assert_equal '/accounts/list_all', url_for(default_route_set, { :controller => 'accounts', :action => 'list_all' }) end def test_default_route_should_uri_escape_pluses expected = { :controller => 'pages', :action => 'show', :id => 'hello world' } assert_equal expected, default_route_set.recognize_path('/pages/show/hello%20world') - assert_equal '/pages/show/hello%20world', default_route_set.generate(expected, expected) + assert_equal '/pages/show/hello%20world', url_for(default_route_set, expected) expected[:id] = 'hello+world' assert_equal expected, default_route_set.recognize_path('/pages/show/hello+world') assert_equal expected, default_route_set.recognize_path('/pages/show/hello%2Bworld') - assert_equal '/pages/show/hello+world', default_route_set.generate(expected, expected) + assert_equal '/pages/show/hello+world', url_for(default_route_set, expected) end def test_build_empty_query_string - assert_uri_equal '/foo', default_route_set.generate({:controller => 'foo'}) + assert_uri_equal '/foo', url_for(default_route_set, { :controller => 'foo' }) end def test_build_query_string_with_nil_value - assert_uri_equal '/foo', default_route_set.generate({:controller => 'foo', :x => nil}) + assert_uri_equal '/foo', url_for(default_route_set, { :controller => 'foo', :x => nil }) end def test_simple_build_query_string - assert_uri_equal '/foo?x=1&y=2', default_route_set.generate({:controller => 'foo', :x => '1', :y => '2'}) + assert_uri_equal '/foo?x=1&y=2', url_for(default_route_set, { :controller => 'foo', :x => '1', :y => '2' }) end def test_convert_ints_build_query_string - assert_uri_equal '/foo?x=1&y=2', default_route_set.generate({:controller => 'foo', :x => 1, :y => 2}) + assert_uri_equal '/foo?x=1&y=2', url_for(default_route_set, { :controller => 'foo', :x => 1, :y => 2 }) end def test_escape_spaces_build_query_string - assert_uri_equal '/foo?x=hello+world&y=goodbye+world', default_route_set.generate({:controller => 'foo', :x => 'hello world', :y => 'goodbye world'}) + assert_uri_equal '/foo?x=hello+world&y=goodbye+world', url_for(default_route_set, { :controller => 'foo', :x => 'hello world', :y => 'goodbye world' }) end def test_expand_array_build_query_string - assert_uri_equal '/foo?x%5B%5D=1&x%5B%5D=2', default_route_set.generate({:controller => 'foo', :x => [1, 2]}) + assert_uri_equal '/foo?x%5B%5D=1&x%5B%5D=2', url_for(default_route_set, { :controller => 'foo', :x => [1, 2] }) end def test_escape_spaces_build_query_string_selected_keys - assert_uri_equal '/foo?x=hello+world', default_route_set.generate({:controller => 'foo', :x => 'hello world'}) + assert_uri_equal '/foo?x=hello+world', url_for(default_route_set, { :controller => 'foo', :x => 'hello world' }) end def test_generate_with_default_params @@ -1462,7 +1473,7 @@ class RouteSetTest < ActiveSupport::TestCase match ':controller/:action/:id' end - assert_equal '/ibocorp', set.generate({:controller => 'ibocorp', :action => "show", :page => 1}) + assert_equal '/ibocorp', url_for(set, { :controller => 'ibocorp', :action => "show", :page => 1 }) end def test_generate_with_optional_params_recalls_last_request @@ -1492,11 +1503,11 @@ class RouteSetTest < ActiveSupport::TestCase last_request = set.recognize_path("/blog/2006/07/28").freeze assert_equal({:controller => "blog", :action => "show_date", :year => "2006", :month => "07", :day => "28"}, last_request) - assert_equal("/blog/2006/07/25", set.generate({:day => 25}, last_request)) - assert_equal("/blog/2005", set.generate({:year => 2005}, last_request)) - assert_equal("/blog/show/123", set.generate({:action => "show" , :id => 123}, last_request)) - assert_equal("/blog/2006", set.generate({:year => 2006}, last_request)) - assert_equal("/blog/2006", set.generate({:year => 2006, :month => nil}, last_request)) + assert_equal("/blog/2006/07/25", url_for(set, { :day => 25 }, last_request)) + assert_equal("/blog/2005", url_for(set, { :year => 2005 }, last_request)) + assert_equal("/blog/show/123", url_for(set, { :action => "show" , :id => 123 }, last_request)) + assert_equal("/blog/2006", url_for(set, { :year => 2006 }, last_request)) + assert_equal("/blog/2006", url_for(set, { :year => 2006, :month => nil }, last_request)) end private @@ -1512,6 +1523,8 @@ class RouteSetTest < ActiveSupport::TestCase end class RackMountIntegrationTests < ActiveSupport::TestCase + include RoutingTestHelpers + Model = Struct.new(:to_param) Mapping = lambda { @@ -1647,111 +1660,111 @@ class RackMountIntegrationTests < ActiveSupport::TestCase end def test_generate - assert_equal '/admin/users', @routes.generate(:use_route => 'admin_users') - assert_equal '/admin/users', @routes.generate(:controller => 'admin/users') - assert_equal '/admin/users', @routes.generate(:controller => 'admin/users', :action => 'index') - assert_equal '/admin/users', @routes.generate({:action => 'index'}, {:controller => 'admin/users'}) - assert_equal '/admin/users', @routes.generate({:controller => 'users', :action => 'index'}, {:controller => 'admin/accounts'}) - assert_equal '/people', @routes.generate({:controller => '/people', :action => 'index'}, {:controller => 'admin/accounts'}) - - assert_equal '/admin/posts', @routes.generate({:controller => 'admin/posts'}) - assert_equal '/admin/posts/new', @routes.generate({:controller => 'admin/posts', :action => 'new'}) - - assert_equal '/blog/2009', @routes.generate(:controller => 'posts', :action => 'show_date', :year => 2009) - assert_equal '/blog/2009/1', @routes.generate(:controller => 'posts', :action => 'show_date', :year => 2009, :month => 1) - assert_equal '/blog/2009/1/1', @routes.generate(:controller => 'posts', :action => 'show_date', :year => 2009, :month => 1, :day => 1) - - assert_equal '/archive/2010', @routes.generate(:controller => 'archive', :action => 'index', :year => '2010') - assert_equal '/archive', @routes.generate(:controller => 'archive', :action => 'index') - assert_equal '/archive?year=january', @routes.generate(:controller => 'archive', :action => 'index', :year => 'january') - - assert_equal '/people', @routes.generate(:controller => 'people', :action => 'index') - assert_equal '/people', @routes.generate({:action => 'index'}, {:controller => 'people'}) - assert_equal '/people', @routes.generate({:action => 'index'}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people', @routes.generate({:controller => 'people', :action => 'index'}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people', @routes.generate({}, {:controller => 'people', :action => 'index'}) - assert_equal '/people/1', @routes.generate({:controller => 'people', :action => 'show'}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people/new', @routes.generate(:use_route => 'new_person') - assert_equal '/people/new', @routes.generate(:controller => 'people', :action => 'new') - assert_equal '/people/1', @routes.generate(:use_route => 'person', :id => '1') - assert_equal '/people/1', @routes.generate(:controller => 'people', :action => 'show', :id => '1') - assert_equal '/people/1.xml', @routes.generate(:controller => 'people', :action => 'show', :id => '1', :format => 'xml') - assert_equal '/people/1', @routes.generate(:controller => 'people', :action => 'show', :id => 1) - assert_equal '/people/1', @routes.generate(:controller => 'people', :action => 'show', :id => Model.new('1')) - assert_equal '/people/1', @routes.generate({:action => 'show', :id => '1'}, {:controller => 'people', :action => 'index'}) - assert_equal '/people/1', @routes.generate({:action => 'show', :id => 1}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people', @routes.generate({:controller => 'people', :action => 'index'}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people/1', @routes.generate({}, {:controller => 'people', :action => 'show', :id => '1'}) - assert_equal '/people/1', @routes.generate({:controller => 'people', :action => 'show'}, {:controller => 'people', :action => 'index', :id => '1'}) - assert_equal '/people/1/edit', @routes.generate(:controller => 'people', :action => 'edit', :id => '1') - assert_equal '/people/1/edit.xml', @routes.generate(:controller => 'people', :action => 'edit', :id => '1', :format => 'xml') - assert_equal '/people/1/edit', @routes.generate(:use_route => 'edit_person', :id => '1') - assert_equal '/people/1?legacy=true', @routes.generate(:controller => 'people', :action => 'show', :id => '1', :legacy => 'true') - assert_equal '/people?legacy=true', @routes.generate(:controller => 'people', :action => 'index', :legacy => 'true') - - assert_equal '/id_default/2', @routes.generate(:controller => 'foo', :action => 'id_default', :id => '2') - assert_equal '/id_default', @routes.generate(:controller => 'foo', :action => 'id_default', :id => '1') - assert_equal '/id_default', @routes.generate(:controller => 'foo', :action => 'id_default', :id => 1) - assert_equal '/id_default', @routes.generate(:controller => 'foo', :action => 'id_default') - assert_equal '/optional/bar', @routes.generate(:controller => 'posts', :action => 'index', :optional => 'bar') - assert_equal '/posts', @routes.generate(:controller => 'posts', :action => 'index') - - assert_equal '/project', @routes.generate({:controller => 'project', :action => 'index'}) - assert_equal '/projects/1', @routes.generate({:controller => 'project', :action => 'index', :project_id => '1'}) - assert_equal '/projects/1', @routes.generate({:controller => 'project', :action => 'index'}, {:project_id => '1'}) - assert_raise(ActionController::RoutingError) { @routes.generate({:use_route => 'project', :controller => 'project', :action => 'index'}) } - assert_equal '/projects/1', @routes.generate({:use_route => 'project', :controller => 'project', :action => 'index', :project_id => '1'}) - assert_equal '/projects/1', @routes.generate({:use_route => 'project', :controller => 'project', :action => 'index'}, {:project_id => '1'}) - - assert_equal '/clients', @routes.generate(:controller => 'projects', :action => 'index') - assert_equal '/clients?project_id=1', @routes.generate(:controller => 'projects', :action => 'index', :project_id => '1') - assert_equal '/clients', @routes.generate({:controller => 'projects', :action => 'index'}, {:project_id => '1'}) - assert_equal '/clients', @routes.generate({:action => 'index'}, {:controller => 'projects', :action => 'index', :project_id => '1'}) - - assert_equal '/comment/20', @routes.generate({:id => 20}, {:controller => 'comments', :action => 'show'}) - assert_equal '/comment/20', @routes.generate(:controller => 'comments', :id => 20, :action => 'show') - assert_equal '/comments/boo', @routes.generate(:controller => 'comments', :action => 'boo') - - assert_equal '/ws/posts/show/1', @routes.generate(:controller => 'posts', :action => 'show', :id => '1', :ws => true) - assert_equal '/ws/posts', @routes.generate(:controller => 'posts', :action => 'index', :ws => true) - - assert_equal '/account', @routes.generate(:controller => 'account', :action => 'subscription') - assert_equal '/account/billing', @routes.generate(:controller => 'account', :action => 'billing') - - assert_equal '/pages/1/notes/show/1', @routes.generate(:page_id => '1', :controller => 'notes', :action => 'show', :id => '1') - assert_equal '/pages/1/notes/list', @routes.generate(:page_id => '1', :controller => 'notes', :action => 'list') - assert_equal '/pages/1/notes', @routes.generate(:page_id => '1', :controller => 'notes', :action => 'index') - assert_equal '/pages/1/notes', @routes.generate(:page_id => '1', :controller => 'notes') - assert_equal '/notes', @routes.generate(:page_id => nil, :controller => 'notes') - assert_equal '/notes', @routes.generate(:controller => 'notes') - assert_equal '/notes/print', @routes.generate(:controller => 'notes', :action => 'print') - assert_equal '/notes/print', @routes.generate({}, {:controller => 'notes', :action => 'print'}) - - assert_equal '/notes/index/1', @routes.generate({:controller => 'notes'}, {:controller => 'notes', :id => '1'}) - assert_equal '/notes/index/1', @routes.generate({:controller => 'notes'}, {:controller => 'notes', :id => '1', :foo => 'bar'}) - assert_equal '/notes/index/1', @routes.generate({:controller => 'notes'}, {:controller => 'notes', :id => '1'}) - assert_equal '/notes/index/1', @routes.generate({:action => 'index'}, {:controller => 'notes', :id => '1'}) - assert_equal '/notes/index/1', @routes.generate({}, {:controller => 'notes', :id => '1'}) - assert_equal '/notes/show/1', @routes.generate({}, {:controller => 'notes', :action => 'show', :id => '1'}) - assert_equal '/notes/index/1', @routes.generate({:controller => 'notes', :id => '1'}, {:foo => 'bar'}) - assert_equal '/posts', @routes.generate({:controller => 'posts'}, {:controller => 'notes', :action => 'show', :id => '1'}) - assert_equal '/notes/list', @routes.generate({:action => 'list'}, {:controller => 'notes', :action => 'show', :id => '1'}) - - assert_equal '/posts/ping', @routes.generate(:controller => 'posts', :action => 'ping') - assert_equal '/posts/show/1', @routes.generate(:controller => 'posts', :action => 'show', :id => '1') - assert_equal '/posts', @routes.generate(:controller => 'posts') - assert_equal '/posts', @routes.generate(:controller => 'posts', :action => 'index') - assert_equal '/posts', @routes.generate({:controller => 'posts'}, {:controller => 'posts', :action => 'index'}) - assert_equal '/posts/create', @routes.generate({:action => 'create'}, {:controller => 'posts'}) - assert_equal '/posts?foo=bar', @routes.generate(:controller => 'posts', :foo => 'bar') - assert_equal '/posts?foo%5B%5D=bar&foo%5B%5D=baz', @routes.generate(:controller => 'posts', :foo => ['bar', 'baz']) - assert_equal '/posts?page=2', @routes.generate(:controller => 'posts', :page => 2) - assert_equal '/posts?q%5Bfoo%5D%5Ba%5D=b', @routes.generate(:controller => 'posts', :q => { :foo => { :a => 'b'}}) - - assert_equal '/news.rss', @routes.generate(:controller => 'news', :action => 'index', :format => 'rss') - - - assert_raise(ActionController::RoutingError) { @routes.generate({:action => 'index'}) } + assert_equal '/admin/users', url_for(@routes, { :use_route => 'admin_users' }) + assert_equal '/admin/users', url_for(@routes, { :controller => 'admin/users' }) + assert_equal '/admin/users', url_for(@routes, { :controller => 'admin/users', :action => 'index' }) + assert_equal '/admin/users', url_for(@routes, { :action => 'index' }, { :controller => 'admin/users' }) + assert_equal '/admin/users', url_for(@routes, { :controller => 'users', :action => 'index' }, { :controller => 'admin/accounts' }) + assert_equal '/people', url_for(@routes, { :controller => '/people', :action => 'index' }, { :controller => 'admin/accounts' }) + + assert_equal '/admin/posts', url_for(@routes, { :controller => 'admin/posts' }) + assert_equal '/admin/posts/new', url_for(@routes, { :controller => 'admin/posts', :action => 'new' }) + + assert_equal '/blog/2009', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009 }) + assert_equal '/blog/2009/1', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1 }) + assert_equal '/blog/2009/1/1', url_for(@routes, { :controller => 'posts', :action => 'show_date', :year => 2009, :month => 1, :day => 1 }) + + assert_equal '/archive/2010', url_for(@routes, { :controller => 'archive', :action => 'index', :year => '2010' }) + assert_equal '/archive', url_for(@routes, { :controller => 'archive', :action => 'index' }) + assert_equal '/archive?year=january', url_for(@routes, { :controller => 'archive', :action => 'index', :year => 'january' }) + + assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }) + assert_equal '/people', url_for(@routes, { :action => 'index' }, { :controller => 'people' }) + assert_equal '/people', url_for(@routes, { :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people', url_for(@routes, {}, { :controller => 'people', :action => 'index' }) + assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people/new', url_for(@routes, { :use_route => 'new_person' }) + assert_equal '/people/new', url_for(@routes, { :controller => 'people', :action => 'new' }) + assert_equal '/people/1', url_for(@routes, { :use_route => 'person', :id => '1' }) + assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people/1.xml', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1', :format => 'xml' }) + assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => 1 }) + assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show', :id => Model.new('1') }) + assert_equal '/people/1', url_for(@routes, { :action => 'show', :id => '1' }, { :controller => 'people', :action => 'index' }) + assert_equal '/people/1', url_for(@routes, { :action => 'show', :id => 1 }, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people', url_for(@routes, { :controller => 'people', :action => 'index' }, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people/1', url_for(@routes, {}, { :controller => 'people', :action => 'show', :id => '1' }) + assert_equal '/people/1', url_for(@routes, { :controller => 'people', :action => 'show' }, { :controller => 'people', :action => 'index', :id => '1' }) + assert_equal '/people/1/edit', url_for(@routes, { :controller => 'people', :action => 'edit', :id => '1' }) + assert_equal '/people/1/edit.xml', url_for(@routes, { :controller => 'people', :action => 'edit', :id => '1', :format => 'xml' }) + assert_equal '/people/1/edit', url_for(@routes, { :use_route => 'edit_person', :id => '1' }) + assert_equal '/people/1?legacy=true', url_for(@routes, { :controller => 'people', :action => 'show', :id => '1', :legacy => 'true' }) + assert_equal '/people?legacy=true', url_for(@routes, { :controller => 'people', :action => 'index', :legacy => 'true' }) + + assert_equal '/id_default/2', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => '2' }) + assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => '1' }) + assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default', :id => 1 }) + assert_equal '/id_default', url_for(@routes, { :controller => 'foo', :action => 'id_default' }) + assert_equal '/optional/bar', url_for(@routes, { :controller => 'posts', :action => 'index', :optional => 'bar' }) + assert_equal '/posts', url_for(@routes, { :controller => 'posts', :action => 'index' }) + + assert_equal '/project', url_for(@routes, { :controller => 'project', :action => 'index' }) + assert_equal '/projects/1', url_for(@routes, { :controller => 'project', :action => 'index', :project_id => '1' }) + assert_equal '/projects/1', url_for(@routes, { :controller => 'project', :action => 'index'}, {:project_id => '1' }) + assert_raise(ActionController::RoutingError) { url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index' }) } + assert_equal '/projects/1', url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index', :project_id => '1' }) + assert_equal '/projects/1', url_for(@routes, { :use_route => 'project', :controller => 'project', :action => 'index' }, { :project_id => '1' }) + + assert_equal '/clients', url_for(@routes, { :controller => 'projects', :action => 'index' }) + assert_equal '/clients?project_id=1', url_for(@routes, { :controller => 'projects', :action => 'index', :project_id => '1' }) + assert_equal '/clients', url_for(@routes, { :controller => 'projects', :action => 'index' }, { :project_id => '1' }) + assert_equal '/clients', url_for(@routes, { :action => 'index' }, { :controller => 'projects', :action => 'index', :project_id => '1' }) + + assert_equal '/comment/20', url_for(@routes, { :id => 20 }, { :controller => 'comments', :action => 'show' }) + assert_equal '/comment/20', url_for(@routes, { :controller => 'comments', :id => 20, :action => 'show' }) + assert_equal '/comments/boo', url_for(@routes, { :controller => 'comments', :action => 'boo' }) + + assert_equal '/ws/posts/show/1', url_for(@routes, { :controller => 'posts', :action => 'show', :id => '1', :ws => true }) + assert_equal '/ws/posts', url_for(@routes, { :controller => 'posts', :action => 'index', :ws => true }) + + assert_equal '/account', url_for(@routes, { :controller => 'account', :action => 'subscription' }) + assert_equal '/account/billing', url_for(@routes, { :controller => 'account', :action => 'billing' }) + + assert_equal '/pages/1/notes/show/1', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'show', :id => '1' }) + assert_equal '/pages/1/notes/list', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'list' }) + assert_equal '/pages/1/notes', url_for(@routes, { :page_id => '1', :controller => 'notes', :action => 'index' }) + assert_equal '/pages/1/notes', url_for(@routes, { :page_id => '1', :controller => 'notes' }) + assert_equal '/notes', url_for(@routes, { :page_id => nil, :controller => 'notes' }) + assert_equal '/notes', url_for(@routes, { :controller => 'notes' }) + assert_equal '/notes/print', url_for(@routes, { :controller => 'notes', :action => 'print' }) + assert_equal '/notes/print', url_for(@routes, {}, { :controller => 'notes', :action => 'print' }) + + assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1' }) + assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1', :foo => 'bar' }) + assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes' }, { :controller => 'notes', :id => '1' }) + assert_equal '/notes/index/1', url_for(@routes, { :action => 'index' }, { :controller => 'notes', :id => '1' }) + assert_equal '/notes/index/1', url_for(@routes, {}, { :controller => 'notes', :id => '1' }) + assert_equal '/notes/show/1', url_for(@routes, {}, { :controller => 'notes', :action => 'show', :id => '1' }) + assert_equal '/notes/index/1', url_for(@routes, { :controller => 'notes', :id => '1' }, { :foo => 'bar' }) + assert_equal '/posts', url_for(@routes, { :controller => 'posts' }, { :controller => 'notes', :action => 'show', :id => '1' }) + assert_equal '/notes/list', url_for(@routes, { :action => 'list' }, { :controller => 'notes', :action => 'show', :id => '1' }) + + assert_equal '/posts/ping', url_for(@routes, { :controller => 'posts', :action => 'ping' }) + assert_equal '/posts/show/1', url_for(@routes, { :controller => 'posts', :action => 'show', :id => '1' }) + assert_equal '/posts', url_for(@routes, { :controller => 'posts' }) + assert_equal '/posts', url_for(@routes, { :controller => 'posts', :action => 'index' }) + assert_equal '/posts', url_for(@routes, { :controller => 'posts' }, { :controller => 'posts', :action => 'index' }) + assert_equal '/posts/create', url_for(@routes, { :action => 'create' }, { :controller => 'posts' }) + assert_equal '/posts?foo=bar', url_for(@routes, { :controller => 'posts', :foo => 'bar' }) + assert_equal '/posts?foo%5B%5D=bar&foo%5B%5D=baz', url_for(@routes, { :controller => 'posts', :foo => ['bar', 'baz'] }) + assert_equal '/posts?page=2', url_for(@routes, { :controller => 'posts', :page => 2 }) + assert_equal '/posts?q%5Bfoo%5D%5Ba%5D=b', url_for(@routes, { :controller => 'posts', :q => { :foo => { :a => 'b'}} }) + + assert_equal '/news.rss', url_for(@routes, { :controller => 'news', :action => 'index', :format => 'rss' }) + + + assert_raise(ActionController::RoutingError) { url_for(@routes, { :action => 'index' }) } end def test_generate_extras diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 8f672c1149..75b674ec1a 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -1,6 +1,31 @@ require 'abstract_unit' class RequestTest < ActiveSupport::TestCase + + def url_for(options = {}) + options.reverse_merge!(:host => 'www.example.com') + ActionDispatch::Http::URL.url_for(options) + end + + test "url_for class method" do + e = assert_raise(ArgumentError) { url_for(:host => nil) } + assert_match(/Please provide the :host parameter/, e.message) + + assert_equal '/books', url_for(:only_path => true, :path => '/books') + + assert_equal 'http://www.example.com', url_for + assert_equal 'http://api.example.com', url_for(:subdomain => 'api') + assert_equal 'http://www.ror.com', url_for(:domain => 'ror.com') + assert_equal 'http://api.ror.co.uk', url_for(:host => 'www.ror.co.uk', :subdomain => 'api', :tld_length => 2) + assert_equal 'http://www.example.com:8080', url_for(:port => 8080) + assert_equal 'https://www.example.com', url_for(:protocol => 'https') + assert_equal 'http://www.example.com/docs', url_for(:path => '/docs') + assert_equal 'http://www.example.com#signup', url_for(:anchor => 'signup') + assert_equal 'http://www.example.com/', url_for(:trailing_slash => true) + assert_equal 'http://dhh:supersecret@www.example.com', url_for(:user => 'dhh', :password => 'supersecret') + assert_equal 'http://www.example.com?search=books', url_for(:params => { :search => 'books' }) + end + test "remote ip" do request = stub_request 'REMOTE_ADDR' => '1.2.3.4' assert_equal '1.2.3.4', request.remote_ip diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index bbd010ea6d..74420317c7 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -13,6 +13,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + class YoutubeFavoritesRedirector + def self.call(params, request) + "http://www.youtube.com/watch?v=#{params[:youtube_id]}" + end + end + stub_controllers do |routes| Routes = routes Routes.draw do @@ -54,6 +60,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest match 'account/login', :to => redirect("/login") match 'secure', :to => redirect("/secure/login") + match 'mobile', :to => redirect(:subdomain => 'mobile') + match 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '') + match 'new_documentation', :to => redirect(:path => '/documentation/new') + match 'super_new_documentation', :to => redirect(:host => 'super-docs.com') + + match 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) + constraints(lambda { |req| true }) do match 'account/overview' end @@ -667,6 +680,41 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_redirect_hash_with_subdomain + with_test_routes do + get '/mobile' + verify_redirect 'http://mobile.example.com/mobile' + end + end + + def test_redirect_hash_with_domain_and_path + with_test_routes do + get '/documentation' + verify_redirect 'http://www.example-documentation.com' + end + end + + def test_redirect_hash_with_path + with_test_routes do + get '/new_documentation' + verify_redirect 'http://www.example.com/documentation/new' + end + end + + def test_redirect_hash_with_host + with_test_routes do + get '/super_new_documentation?section=top' + verify_redirect 'http://super-docs.com/super_new_documentation?section=top' + end + end + + def test_redirect_class + with_test_routes do + get '/youtube_favorites/oHg5SJYRHA0/rick-rolld' + verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0' + end + end + def test_openid with_test_routes do get '/openid/login' -- cgit v1.2.3 From 1e26bda0959c313ce5c1816bf4958b542050e5e2 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 30 Nov 2010 17:55:33 +0100 Subject: Added documentation explaining the new additional supported syntaxes for the routing redirect method, a small changelog note, and two extra tests for path interpolation when using the hash option syntax. --- actionpack/CHANGELOG | 2 ++ .../lib/action_dispatch/routing/redirection.rb | 29 ++++++++++++++++++++++ actionpack/test/dispatch/routing_test.rb | 17 +++++++++++++ 3 files changed, 48 insertions(+) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 74d017cc3d..9b292cca69 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* The redirect route method now also accepts a hash of options which will only change the parts of the url in question, or an object which responds to call, allowing for redirects to be reused (check the documentation for examples). [Josh Kalderimis] + * Added config.action_controller.include_all_helpers. By default 'helper :all' is done in ActionController::Base, which includes all the helpers by default. Setting include_all_helpers to false will result in including only application_helper and helper corresponding to controller (like foo_helper for foo_controller). [Piotr Sarnacki] * Added a convenience idiom to generate HTML5 data-* attributes in tag helpers from a :data hash of options: diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb index d9c9a400a7..804991ad5f 100644 --- a/actionpack/lib/action_dispatch/routing/redirection.rb +++ b/actionpack/lib/action_dispatch/routing/redirection.rb @@ -7,6 +7,35 @@ module ActionDispatch # Redirect any path to another path: # # match "/stories" => redirect("/posts") + # + # You can also use interpolation in the supplied redirect argument: + # + # match 'docs/:article', :to => redirect('/wiki/%{article}') + # + # Alternatively you can use one of the other syntaxes: + # + # The block version of redirect allows for the easy encapsulation of any logic associated with + # the redirect in question. Either the params and request are supplied as arguments, or just + # params, depending of how many arguments your block accepts. A string is required as a + # return value. + # + # match 'jokes/:number', :to => redirect do |params, request| + # path = (params[:number].to_i.even? ? "/wheres-the-beef" : "/i-love-lamp") + # "http://#{request.host_with_port}/#{path}" + # end + # + # The options version of redirect allows you to supply only the parts of the url which need + # to change, it also supports interpolation of the path similar to the first example. + # + # match 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}') + # match 'stores/:name(*all)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{all}') + # + # Finally, an object which responds to call can be supplied to redirect, allowing you to reuse + # common redirect routes. The call method must accept two arguments, params and request, and return + # a string. + # + # match 'accounts/:name' => redirect(SubdomainRedirector.new('api')) + # def redirect(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {} status = options.delete(:status) || 301 diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 74420317c7..4bf7880294 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -65,6 +65,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest match 'new_documentation', :to => redirect(:path => '/documentation/new') match 'super_new_documentation', :to => redirect(:host => 'super-docs.com') + match 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}') + match 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}') + match 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) constraints(lambda { |req| true }) do @@ -708,6 +711,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_redirect_hash_path_substitution + with_test_routes do + get '/stores/iernest' + verify_redirect 'http://stores.example.com/iernest' + end + end + + def test_redirect_hash_path_substitution_with_catch_all + with_test_routes do + get '/stores/iernest/products' + verify_redirect 'http://stores.example.com/iernest/products' + end + end + def test_redirect_class with_test_routes do get '/youtube_favorites/oHg5SJYRHA0/rick-rolld' -- cgit v1.2.3 From 831a2342c69f1d602aca9e894bffa4f6dbf614ed Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 30 Nov 2010 20:04:31 -0800 Subject: just use alias --- actionpack/lib/action_dispatch/testing/integration.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 8fe74c3c80..5c6416a19e 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -235,9 +235,7 @@ module ActionDispatch # Set the host name to use in the next request. # # session.host! "www.example.com" - def host!(name) - @host = name - end + alias :host! :host= private def _mock_session -- cgit v1.2.3 From ba63c0a9b58691adeca645977828ee918107208d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 1 Dec 2010 11:22:48 +0100 Subject: Deprecate handler_class_for_extension as template handlers can be any Ruby object, not necessarily a class. --- actionpack/lib/action_view/renderer/template_renderer.rb | 2 +- actionpack/lib/action_view/template/handlers.rb | 8 +++++++- actionpack/lib/action_view/template/resolver.rb | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index 6912acee31..ece3f621b6 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -45,7 +45,7 @@ module ActionView elsif options.key?(:file) with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } elsif options.key?(:inline) - handler = Template.handler_class_for_extension(options[:type] || "erb") + handler = Template.handler_for_extension(options[:type] || "erb") Template.new(options[:inline], "inline template", handler, :locals => keys) elsif options.key?(:template) options[:template].respond_to?(:render) ? diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index 60347e2a95..4438199497 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -44,7 +44,13 @@ module ActionView #:nodoc: end def handler_class_for_extension(extension) - (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers + ActiveSupport::Deprecation.warn "handler_class_for_extension is deprecated. " << + "Please use handler_for_extension instead", caller + handler_for_extension(extension) + end + + def handler_for_extension(extension) + registered_template_handler(extension) || @@default_template_handlers end end end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 7707dbcf98..9f15661669 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -129,7 +129,7 @@ module ActionView def extract_handler_and_format(path, default_formats) pieces = File.basename(path).split(".") pieces.shift - handler = Template.handler_class_for_extension(pieces.pop) + handler = Template.handler_for_extension(pieces.pop) format = pieces.last && Mime[pieces.last] [handler, format] end -- cgit v1.2.3 From 226ea0e9e817a2e449d989d925c36cf6a4cfd67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 3 Dec 2010 13:27:43 +0100 Subject: Wrap everything in class << self. --- actionpack/lib/action_dispatch/http/url.rb | 79 ++++++++++++++---------------- 1 file changed, 37 insertions(+), 42 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 51d4766282..796cd8c09b 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -4,55 +4,54 @@ module ActionDispatch mattr_accessor :tld_length self.tld_length = 1 - def self.extract_domain(host, tld_length = @@tld_length) - return nil unless named_host?(host) - - host.split('.').last(1 + tld_length).join('.') - end - - def self.extract_subdomains(host, tld_length = @@tld_length) - return [] unless named_host?(host) - parts = host.split('.') - parts[0..-(tld_length+2)] - end - - def self.extract_subdomain(host, tld_length = @@tld_length) - extract_subdomains(host, tld_length).join('.') - end + class << self + def extract_domain(host, tld_length = @@tld_length) + return nil unless named_host?(host) + host.split('.').last(1 + tld_length).join('.') + end - def self.named_host?(host) - !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) - end + def extract_subdomains(host, tld_length = @@tld_length) + return [] unless named_host?(host) + parts = host.split('.') + parts[0..-(tld_length+2)] + end - def self.url_for(options = {}) - unless options[:host].present? || options[:only_path].present? - raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true' + def extract_subdomain(host, tld_length = @@tld_length) + extract_subdomains(host, tld_length).join('.') end - rewritten_url = "" + def url_for(options = {}) + unless options[:host].present? || options[:only_path].present? + raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true' + end - unless options[:only_path] - rewritten_url << (options[:protocol] || "http") - rewritten_url << "://" unless rewritten_url.match("://") - rewritten_url << rewrite_authentication(options) - rewritten_url << host_or_subdomain_and_domain(options) - rewritten_url << ":#{options.delete(:port)}" if options[:port] - end + rewritten_url = "" - path = options.delete(:path) || '' + unless options[:only_path] + rewritten_url << (options[:protocol] || "http") + rewritten_url << "://" unless rewritten_url.match("://") + rewritten_url << rewrite_authentication(options) + rewritten_url << host_or_subdomain_and_domain(options) + rewritten_url << ":#{options.delete(:port)}" if options[:port] + end - params = options[:params] || {} - params.reject! {|k,v| !v } + path = options.delete(:path) || '' - rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) - rewritten_url << "?#{params.to_query}" unless params.empty? - rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] - rewritten_url - end + params = options[:params] || {} + params.reject! {|k,v| !v } + + rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) + rewritten_url << "?#{params.to_query}" unless params.empty? + rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] + rewritten_url + end - class << self private + def named_host?(host) + !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) + end + def rewrite_authentication(options) if options[:user] && options[:password] "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@" @@ -72,11 +71,8 @@ module ActionDispatch host << (options[:domain] || extract_domain(options[:host], tld_length)) host end - end - - # Returns the complete URL used for this request. def url protocol + host_with_port + fullpath @@ -168,7 +164,6 @@ module ActionDispatch def subdomain(tld_length = @@tld_length) subdomains(tld_length) end - end end end -- cgit v1.2.3 From 7ffd5daa7fe1fd805fd071d40dfad1773299c7d1 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 14 Nov 2010 18:30:09 +0100 Subject: bump i18n gem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/actionpack.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 44967631ff..b7d1d8c2af 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |s| s.add_dependency('activemodel', version) s.add_dependency('rack-cache', '~> 0.5.3') s.add_dependency('builder', '~> 3.0.0') - s.add_dependency('i18n', '~> 0.4.2') + s.add_dependency('i18n', '~> 0.5.0') s.add_dependency('rack', '~> 1.2.1') s.add_dependency('rack-test', '~> 0.5.6') s.add_dependency('rack-mount', '~> 0.6.13') -- cgit v1.2.3 From 896e25e994e272a1cb485d9a850501b488992cb2 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 14 Nov 2010 18:46:40 +0100 Subject: Make TranslationHelper#translate use the :rescue_format option in I18n 0.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't catch exceptions here. Instead only declare that we want exceptions to be rescued as :html, but also let users configure reactions to exceptions in I18n. Signed-off-by: José Valim --- .../lib/action_view/helpers/translation_helper.rb | 32 ++++++++--- .../test/fixtures/test/scoped_translation.erb | 1 - actionpack/test/fixtures/test/translation.erb | 1 - .../test/fixtures/translations/templates/array.erb | 1 + .../test/fixtures/translations/templates/found.erb | 1 + .../fixtures/translations/templates/missing.erb | 1 + .../test/template/translation_helper_test.rb | 67 +++++++++++++--------- 7 files changed, 68 insertions(+), 36 deletions(-) delete mode 100644 actionpack/test/fixtures/test/scoped_translation.erb delete mode 100644 actionpack/test/fixtures/test/translation.erb create mode 100644 actionpack/test/fixtures/translations/templates/array.erb create mode 100644 actionpack/test/fixtures/translations/templates/found.erb create mode 100644 actionpack/test/fixtures/translations/templates/missing.erb (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 8574ca6595..e7ec1df2c8 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -1,13 +1,33 @@ require 'action_view/helpers/tag_helper' +require 'i18n/exceptions' + +module I18n + class ExceptionHandler + include Module.new { + def call(exception, locale, key, options) + exception.is_a?(MissingTranslationData) ? super.html_safe : super + end + } + end +end module ActionView # = Action View Translation Helpers module Helpers module TranslationHelper # Delegates to I18n#translate but also performs three additional functions. - # First, it'll catch MissingTranslationData exceptions and turn them into - # inline spans that contains the missing key, such that you can see in a - # view what is missing where. + # + # First, it'll pass the :rescue_format => :html option to I18n so that any caught + # MissingTranslationData exceptions will be turned into inline spans that + # + # * have a "translation-missing" class set, + # * contain the missing key as a title attribute and + # * a titleized version of the last key segment as a text. + # + # E.g. the value returned for a missing translation key :"blog.post.title" will be + # Title. + # This way your views will display rather reasonableful strings but it will still + # be easy to spot missing translations. # # Second, it'll scope the key by the current partial if the key starts # with a period. So if you call translate(".foo") from the @@ -24,15 +44,13 @@ module ActionView # naming convention helps to identify translations that include HTML tags so that # you know what kind of output to expect when you call translate in a template. def translate(key, options = {}) - translation = I18n.translate(scope_key_by_partial(key), options.merge!(:raise => true)) + options.merge!(:rescue_format => :html) unless options.key?(:rescue_format) + translation = I18n.translate(scope_key_by_partial(key), options) if html_safe_translation_key?(key) && translation.respond_to?(:html_safe) translation.html_safe else translation end - rescue I18n::MissingTranslationData => e - keys = I18n.normalize_keys(e.locale, e.key, e.options[:scope]) - content_tag('span', keys.join(', '), :class => 'translation_missing') end alias :t :translate diff --git a/actionpack/test/fixtures/test/scoped_translation.erb b/actionpack/test/fixtures/test/scoped_translation.erb deleted file mode 100644 index 3be63ab3cc..0000000000 --- a/actionpack/test/fixtures/test/scoped_translation.erb +++ /dev/null @@ -1 +0,0 @@ -<%= t('.foo.bar').join %> \ No newline at end of file diff --git a/actionpack/test/fixtures/test/translation.erb b/actionpack/test/fixtures/test/translation.erb deleted file mode 100644 index 81a837d1ff..0000000000 --- a/actionpack/test/fixtures/test/translation.erb +++ /dev/null @@ -1 +0,0 @@ -<%= t('.helper') %> \ No newline at end of file diff --git a/actionpack/test/fixtures/translations/templates/array.erb b/actionpack/test/fixtures/translations/templates/array.erb new file mode 100644 index 0000000000..d86045a172 --- /dev/null +++ b/actionpack/test/fixtures/translations/templates/array.erb @@ -0,0 +1 @@ +<%= t('.foo.bar') %> diff --git a/actionpack/test/fixtures/translations/templates/found.erb b/actionpack/test/fixtures/translations/templates/found.erb new file mode 100644 index 0000000000..080c9c0aee --- /dev/null +++ b/actionpack/test/fixtures/translations/templates/found.erb @@ -0,0 +1 @@ +<%= t('.foo') %> diff --git a/actionpack/test/fixtures/translations/templates/missing.erb b/actionpack/test/fixtures/translations/templates/missing.erb new file mode 100644 index 0000000000..0f3f17f8ef --- /dev/null +++ b/actionpack/test/fixtures/translations/templates/missing.erb @@ -0,0 +1 @@ +<%= t('.missing') %> diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb index 763080550b..67d459136b 100644 --- a/actionpack/test/template/translation_helper_test.rb +++ b/actionpack/test/template/translation_helper_test.rb @@ -4,60 +4,73 @@ class TranslationHelperTest < ActiveSupport::TestCase include ActionView::Helpers::TagHelper include ActionView::Helpers::TranslationHelper - attr_reader :request + attr_reader :request, :view + def setup + I18n.backend.store_translations(:en, + :translations => { + :templates => { + :found => { :foo => 'Foo' }, + :array => { :foo => { :bar => 'Foo Bar' } } + }, + :foo => 'Foo', + :hello => 'Hello World', + :html => 'Hello World', + :hello_html => 'Hello World', + :array_html => %w(foo bar), + :array => %w(foo bar) + } + ) + @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) end - def test_delegates_to_i18n_setting_the_raise_option - I18n.expects(:translate).with(:foo, :locale => 'en', :raise => true).returns("") + def test_delegates_to_i18n_setting_the_rescue_format_option_to_html + I18n.expects(:translate).with(:foo, :locale => 'en', :rescue_format => :html).returns("") translate :foo, :locale => 'en' end + def test_delegates_localize_to_i18n + @time = Time.utc(2008, 7, 8, 12, 18, 38) + I18n.expects(:localize).with(@time) + localize @time + end + def test_returns_missing_translation_message_wrapped_into_span - expected = 'en, foo' - assert_equal expected, translate(:foo) + expected = 'Missing' + assert_equal expected, translate(:"translations.missing") end def test_translation_returning_an_array - I18n.expects(:translate).with(:foo, :raise => true).returns(["foo", "bar"]) - assert_equal ["foo", "bar"], translate(:foo) + expected = %w(foo bar) + assert_equal expected, translate(:"translations.array") end - def test_delegates_localize_to_i18n - @time = Time.utc(2008, 7, 8, 12, 18, 38) - I18n.expects(:localize).with(@time) - localize @time + def test_finds_translation_scoped_by_partial + assert_equal 'Foo', view.render(:file => 'translations/templates/found').strip end - def test_scoping_by_partial - I18n.expects(:translate).with("test.translation.helper", :raise => true).returns("helper") - @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) - assert_equal "helper", @view.render(:file => "test/translation") + def test_finds_array_of_translations_scoped_by_partial + assert_equal 'Foo Bar', @view.render(:file => 'translations/templates/array').strip end - def test_scoping_by_partial_of_an_array - I18n.expects(:translate).with("test.scoped_translation.foo.bar", :raise => true).returns(["foo", "bar"]) - @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) - assert_equal "foobar", @view.render(:file => "test/scoped_translation") + def test_missing_translation_scoped_by_partial + expected = 'Missing' + assert_equal expected, view.render(:file => 'translations/templates/missing').strip end def test_translate_does_not_mark_plain_text_as_safe_html - I18n.expects(:translate).with("hello", :raise => true).returns("Hello World") - assert_equal false, translate("hello").html_safe? + assert_equal false, translate(:'translations.hello').html_safe? end def test_translate_marks_translations_named_html_as_safe_html - I18n.expects(:translate).with("html", :raise => true).returns("Hello World") - assert translate("html").html_safe? + assert translate(:'translations.html').html_safe? end def test_translate_marks_translations_with_a_html_suffix_as_safe_html - I18n.expects(:translate).with("hello_html", :raise => true).returns("Hello World") - assert translate("hello_html").html_safe? + assert translate(:'translations.hello_html').html_safe? end def test_translation_returning_an_array_ignores_html_suffix - I18n.expects(:translate).with(:foo_html, :raise => true).returns(["foo", "bar"]) - assert_equal ["foo", "bar"], translate(:foo_html) + assert_equal ["foo", "bar"], translate(:'translations.array_html') end end -- cgit v1.2.3 From be4551f63bc3dec7e182371d25e7b9ee0e9148c4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 4 Dec 2010 19:01:00 -0200 Subject: Use ||= here --- actionpack/lib/action_view/helpers/translation_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index e7ec1df2c8..76dac20f4b 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -44,7 +44,7 @@ module ActionView # naming convention helps to identify translations that include HTML tags so that # you know what kind of output to expect when you call translate in a template. def translate(key, options = {}) - options.merge!(:rescue_format => :html) unless options.key?(:rescue_format) + options[:rescue_format] ||= :html translation = I18n.translate(scope_key_by_partial(key), options) if html_safe_translation_key?(key) && translation.respond_to?(:html_safe) translation.html_safe -- cgit v1.2.3 From b696dd70db651c6cb4a096dd0d5762416acd9917 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 4 Dec 2010 20:07:54 -0200 Subject: Allow back passing :rescue_format => nil and test added --- actionpack/lib/action_view/helpers/translation_helper.rb | 2 +- actionpack/test/template/translation_helper_test.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 76dac20f4b..e7ec1df2c8 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -44,7 +44,7 @@ module ActionView # naming convention helps to identify translations that include HTML tags so that # you know what kind of output to expect when you call translate in a template. def translate(key, options = {}) - options[:rescue_format] ||= :html + options.merge!(:rescue_format => :html) unless options.key?(:rescue_format) translation = I18n.translate(scope_key_by_partial(key), options) if html_safe_translation_key?(key) && translation.respond_to?(:html_safe) translation.html_safe diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb index 67d459136b..9b5c6d127c 100644 --- a/actionpack/test/template/translation_helper_test.rb +++ b/actionpack/test/template/translation_helper_test.rb @@ -40,6 +40,11 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal expected, translate(:"translations.missing") end + def test_returns_missing_translation_message_using_nil_as_rescue_format + expected = 'translation missing: en.translations.missing' + assert_equal expected, translate(:"translations.missing", :rescue_format => nil) + end + def test_translation_returning_an_array expected = %w(foo bar) assert_equal expected, translate(:"translations.array") -- cgit v1.2.3 From e1d0d5ae81d2b02eebb1afbfb79edf0a2da2d48e Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Sat, 4 Dec 2010 22:40:05 -0200 Subject: Fix mime type doc typos --- actionpack/lib/action_dispatch/http/mime_type.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 08eab5634a..c85aa64572 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -173,10 +173,10 @@ module Mime end # input: 'text' - # returend value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + # returned value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] # # input: 'application' - # returend value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM + # returned value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM] def parse_data_with_trailing_star(input) keys = Mime::LOOKUP.keys.select{|k| k.include?(input)} Mime::LOOKUP.values_at(*keys).uniq -- cgit v1.2.3 From 3ac844deec6070f35634acca0ae9007280b13e5d Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 6 Dec 2010 16:38:47 -0500 Subject: Add to documentation that action caching does handle HTTP_ACCEPT attribute properly and might provide wrong result. Use params[:format] to avoid this issue. --- actionpack/lib/action_controller/caching/actions.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index d69d96b974..cb79e51dbf 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -71,6 +71,11 @@ module ActionController #:nodoc: # If you pass :layout => false, it will only cache your action # content. It is useful when your layout has dynamic information. # + # Note: If action caching is being performed for different MIME types + # and those MIME types are being determined by HTTP_ACCEPT header atttribute + # and noth using params[:format] then both the cached data and the content-type + # of the response could be wrong. The safest way to use action caching is to + # pass non-html attribute as params[:format] . module Actions extend ActiveSupport::Concern -- cgit v1.2.3 From 0aa78826e4857dbaaaf8a0779848d11ab6e0ad5d Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 8 Dec 2010 21:20:53 +0100 Subject: makes a pass to the action caching rdoc --- .../lib/action_controller/caching/actions.rb | 73 ++++++++++++---------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index cb79e51dbf..a4bac3caed 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -4,25 +4,26 @@ module ActionController #:nodoc: module Caching # Action caching is similar to page caching by the fact that the entire # output of the response is cached, but unlike page caching, every - # request still goes through the Action Pack. The key benefit - # of this is that filters are run before the cache is served, which - # allows for authentication and other restrictions on whether someone - # is allowed to see the cache. Example: + # request still goes through Action Pack. The key benefit of this is + # that filters run before the cache is served, which allows for + # authentication and other restrictions on whether someone is allowed + # to execute such action. Example: # # class ListsController < ApplicationController # before_filter :authenticate, :except => :public + # # caches_page :public - # caches_action :index, :show, :feed + # caches_action :index, :show # end # - # In this example, the public action doesn't require authentication, - # so it's possible to use the faster page caching method. But both - # the show and feed action are to be shielded behind the authenticate - # filter, so we need to implement those as action caches. + # In this example, the +public+ action doesn't require authentication + # so it's possible to use the faster page caching. On the other hand + # +index+ and +show+ require authentication. They can still be cached, + # but we need action caching for them. # - # Action caching internally uses the fragment caching and an around - # filter to do the job. The fragment cache is named according to both - # the current host and the path. So a page that is accessed at + # Action caching uses fragment caching internally and an around + # filter to do the job. The fragment cache is named according to + # the host and path of the request. A page that is accessed at # http://david.example.com/lists/show/1 will result in a fragment named # david.example.com/lists/show/1. This allows the cacher to # differentiate between david.example.com/lists/ and @@ -38,19 +39,23 @@ module ActionController #:nodoc: # :action => 'list', :format => :xml. # # You can set modify the default action cache path by passing a - # :cache_path option. This will be passed directly to - # ActionCachePath.path_for. This is handy for actions with multiple - # possible routes that should be cached differently. If a block is - # given, it is called with the current controller instance. + # :cache_path option. This will be passed directly to + # ActionCachePath.path_for. This is handy for actions with + # multiple possible routes that should be cached differently. If a + # block is given, it is called with the current controller instance. + # + # And you can also use :if (or :unless) to pass a + # proc that specifies when the action should be cached. # - # And you can also use :if (or :unless) to pass a Proc that - # specifies when the action should be cached. + # Finally, if you are using memcached, you can also pass :expires_in. # - # Finally, if you are using memcached, you can also pass :expires_in. + # The following example depicts some of the points made above: # # class ListsController < ApplicationController # before_filter :authenticate, :except => :public - # caches_page :public + # + # caches_page :public + # # caches_action :index, :if => proc do |c| # !c.request.format.json? # cache if is not a JSON request # end @@ -58,24 +63,28 @@ module ActionController #:nodoc: # caches_action :show, :cache_path => { :project => 1 }, # :expires_in => 1.hour # - # caches_action :feed, :cache_path => proc do |controller| - # if controller.params[:user_id] - # controller.send(:user_list_url, - # controller.params[:user_id], controller.params[:id]) + # caches_action :feed, :cache_path => proc do |c| + # if c.params[:user_id] + # c.send(:user_list_url, + # c.params[:user_id], c.params[:id]) # else - # controller.send(:list_url, controller.params[:id]) + # c.send(:list_url, c.params[:id]) # end # end # end # - # If you pass :layout => false, it will only cache your action - # content. It is useful when your layout has dynamic information. + # If you pass :layout => false, it will only cache your action + # content. That's useful when your layout has dynamic information. + # + # Warning: If the format of the request is determined by the Accept HTTP + # header the Content-Type of the cached response could be wrong because + # no information about the MIME type is stored in the cache key. So, if + # you first ask for MIME type M in the Accept header, a cache entry is + # created, and then perform a second resquest to the same resource asking + # for a different MIME type, you'd get the content cached for M. # - # Note: If action caching is being performed for different MIME types - # and those MIME types are being determined by HTTP_ACCEPT header atttribute - # and noth using params[:format] then both the cached data and the content-type - # of the response could be wrong. The safest way to use action caching is to - # pass non-html attribute as params[:format] . + # The :format parameter is taken into account though. The safest + # way to cache by MIME type is to pass the format in the route. module Actions extend ActiveSupport::Concern -- cgit v1.2.3 From a47f31c59399204947dacb2b54fccc6987b137ee Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Thu, 9 Dec 2010 20:01:42 +1000 Subject: mapper.rb: add "options" to make the default-to-namespace-name line read better --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 5a38158e9f..11ac8fed20 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -563,7 +563,7 @@ module ActionDispatch # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} # === Supported options # - # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ all default to the name of the namespace. + # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ options all default to the name of the namespace. # # [:path] # The path prefix for the routes. -- cgit v1.2.3 From d2f98e5b556815f7b9cf84d3702d93a0bfb7d433 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Thu, 9 Dec 2010 20:03:14 +1000 Subject: indent code samples for mount doc --- actionpack/lib/action_dispatch/routing/mapper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 11ac8fed20..086366c740 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -269,18 +269,18 @@ module ActionDispatch # Mount a Rack-based application to be used within the application. # - # mount SomeRackApp, :at => "some_route" + # mount SomeRackApp, :at => "some_route" # # Alternatively: # - # mount(SomeRackApp => "some_route") + # mount(SomeRackApp => "some_route") # # All mounted applications come with routing helpers to access them. # These are named after the class specified, so for the above example # the helper is either +some_rack_app_path+ or +some_rack_app_url+. # To customize this helper's name, use the +:as+ option: # - # mount(SomeRackApp => "some_route", :as => "exciting") + # mount(SomeRackApp => "some_route", :as => "exciting") # # This will generate the +exciting_path+ and +exciting_url+ helpers # which can be used to navigate to this mounted app. -- cgit v1.2.3 From fe0e3880e8ce8311882f3856b689c2f79a13ced4 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Thu, 9 Dec 2010 20:21:08 +1000 Subject: root route should go at the *top* of the routes file, because it is the most popular route and should be matched first --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 086366c740..cf95f6fa53 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -247,7 +247,9 @@ module ActionDispatch # # root :to => 'pages#main' # - # You should put the root route at the end of config/routes.rb. + # You should put the root route at the top of config/routes.rb, + # because this means it will be matched first. As this is the most popular route + # of most Rails applications, this is beneficial. def root(options = {}) match '/', options.reverse_merge(:as => :root) end -- cgit v1.2.3 From 28cf77203b0b5af648e441b5d9cfb75863ba2f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 9 Dec 2010 13:15:25 +0100 Subject: Check if the routes object really responds to define_mount_prefix. --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- actionpack/test/dispatch/mount_test.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 5a38158e9f..47de5848fa 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -327,7 +327,7 @@ module ActionDispatch end def define_generate_prefix(app, name) - return unless app.respond_to?(:routes) + return unless app.respond_to?(:routes) && app.routes.respond_to?(:define_mounted_helper) _route = @set.named_routes.routes[name.to_sym] _routes = @set diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb index 0f584af31e..1a032539b9 100644 --- a/actionpack/test/dispatch/mount_test.rb +++ b/actionpack/test/dispatch/mount_test.rb @@ -2,6 +2,17 @@ require 'abstract_unit' class TestRoutingMount < ActionDispatch::IntegrationTest Router = ActionDispatch::Routing::RouteSet.new + + class FakeEngine + def self.routes + Object.new + end + + def self.call(env) + [200, {"Content-Type" => "text/html"}, ["OK"]] + end + end + Router.draw do SprocketsApp = lambda { |env| [200, {"Content-Type" => "text/html"}, ["#{env["SCRIPT_NAME"]} -- #{env["PATH_INFO"]}"]] @@ -10,6 +21,8 @@ class TestRoutingMount < ActionDispatch::IntegrationTest mount SprocketsApp, :at => "/sprockets" mount SprocketsApp => "/shorthand" + mount FakeEngine, :at => "/fakeengine" + scope "/its_a" do mount SprocketsApp, :at => "/sprocket" end @@ -33,4 +46,9 @@ class TestRoutingMount < ActionDispatch::IntegrationTest get "/shorthand/omg" assert_equal "/shorthand -- /omg", response.body end + + def test_with_fake_engine_does_not_call_invalid_method + get "/fakeengine" + assert_equal "OK", response.body + end end \ No newline at end of file -- cgit v1.2.3 From cc70ac9508dff6a4406f446d7a53d05f6c7d9f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 9 Dec 2010 13:15:40 +0100 Subject: Properly check the arity for template handlers. --- actionpack/lib/action_view/template.rb | 2 +- actionpack/test/template/render_test.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 831a19654e..0d8373ef14 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -275,7 +275,7 @@ module ActionView end arity = @handler.respond_to?(:arity) ? @handler.arity : @handler.method(:call).arity - code = arity == 1 ? @handler.call(self) : @handler.call(self, view) + code = arity.abs == 1 ? @handler.call(self) : @handler.call(self, view) # Make sure that the resulting String to be evalled is in the # encoding of the code diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 8087429d62..38bedd2e4e 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -225,6 +225,11 @@ module RenderTestCases %'"#{template.class} #{view.class}"' end + def test_render_inline_with_render_from_to_proc + ActionView::Template.register_template_handler :ruby_handler, :source.to_proc + assert_equal '3', @view.render(:inline => "(1 + 2).to_s", :type => :ruby_handler) + end + def test_render_inline_with_template_handler_with_view ActionView::Template.register_template_handler :with_view, WithViewHandler assert_equal 'ActionView::Template ActionView::Base', @view.render(:inline => "Hello, World!", :type => :with_view) -- cgit v1.2.3 From 8e6d27641cf213a13d51491cecfbfa1d3c8822fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 9 Dec 2010 13:40:45 +0100 Subject: Clean up asset_host and asset_path. --- actionpack/lib/action_controller/railtie.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index c5a661f2b0..f0c29825ba 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -27,8 +27,8 @@ module ActionController options.page_cache_directory ||= paths["public"].first # make sure readers methods get compiled - options.asset_path ||= nil - options.asset_host ||= nil + options.asset_path ||= app.config.asset_path + options.asset_host ||= app.config.asset_host ActiveSupport.on_load(:action_controller) do include app.routes.mounted_helpers -- cgit v1.2.3 From d3f7e565d1a6ee15605971c3f3fea6e756a1ff99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 9 Dec 2010 14:06:44 +0100 Subject: Ensure resolvers backward compatibility. --- actionpack/lib/action_view/lookup_context.rb | 2 +- actionpack/lib/action_view/path_set.rb | 6 ++---- actionpack/lib/action_view/template/resolver.rb | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 27f94a73a6..d524c68450 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -109,7 +109,7 @@ module ActionView def args_for_lookup(name, prefix, partial, keys) #:nodoc: name, prefix = normalize_name(name, prefix) - [name, prefix, partial || false, @details, keys, details_key] + [name, prefix, partial || false, @details, details_key, keys] end # Support legacy foo.erb names even though we now ignore .erb diff --git a/actionpack/lib/action_view/path_set.rb b/actionpack/lib/action_view/path_set.rb index dc26d75ff3..fa35120a0d 100644 --- a/actionpack/lib/action_view/path_set.rb +++ b/actionpack/lib/action_view/path_set.rb @@ -10,10 +10,8 @@ module ActionView #:nodoc: METHOD end - def find(path, prefix = nil, partial = false, details = {}, keys = [], key = nil) - template = find_all(path, prefix, partial, details, keys, key).first - raise MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) unless template - template + def find(*args) + find_all(*args).first || raise(MissingTemplate.new(self, "#{args[1]}/#{args[0]}", args[3], args[2])) end def find_all(*args) diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 9f15661669..a17454da28 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -15,7 +15,7 @@ module ActionView end # Normalizes the arguments and passes it on to find_template. - def find_all(name, prefix=nil, partial=false, details={}, locals=[], key=nil) + def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[]) cached(key, [name, prefix, partial], details, locals) do find_templates(name, prefix, partial, details) end -- cgit v1.2.3 From 0027b654215cd6310d0d17daeaafec8ebbfb38d4 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sat, 4 Dec 2010 17:40:54 -0500 Subject: Ensure that while caching a page rails takes into account the resolved mime type for the request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#6110 state:resolved] Signed-off-by: José Valim --- actionpack/lib/action_controller/caching/pages.rb | 20 +++++++++++++------- actionpack/test/controller/caching_test.rb | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 104157d0b1..3e57d2c236 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -70,9 +70,9 @@ module ActionController #:nodoc: # Manually cache the +content+ in the key determined by +path+. Example: # cache_page "I'm the cached content", "/lists/show" - def cache_page(content, path) + def cache_page(content, path, extension = nil) return unless perform_caching - path = page_cache_path(path) + path = page_cache_path(path, extension) instrument_page_cache :write_page, path do FileUtils.makedirs(File.dirname(path)) @@ -97,14 +97,16 @@ module ActionController #:nodoc: end private - def page_cache_file(path) + def page_cache_file(path, extension) name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/')) - name << page_cache_extension unless (name.split('/').last || name).include? '.' + unless (name.split('/').last || name).include? '.' + name << (extension || self.page_cache_extension) + end return name end - def page_cache_path(path) - page_cache_directory + page_cache_file(path) + def page_cache_path(path, extension = nil) + page_cache_directory + page_cache_file(path, extension) end def instrument_page_cache(name, path) @@ -145,7 +147,11 @@ module ActionController #:nodoc: request.path end - self.class.cache_page(content || response.body, path) + if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present? + extension = ".#{type_symbol}" + end + + self.class.cache_page(content || response.body, path, extension) end end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 914ae56032..c7b54eb0ba 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -16,6 +16,7 @@ end class PageCachingTestController < CachingController caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? } caches_page :found, :not_found + caches_page :about_me def ok @@ -47,6 +48,14 @@ class PageCachingTestController < CachingController def trailing_slash render :text => "Sneak attack" end + + def about_me + respond_to do |format| + format.html {render :text => 'I am html'} + format.xml {render :text => 'I am xml'} + end + end + end class PageCachingTest < ActionController::TestCase @@ -111,6 +120,13 @@ class PageCachingTest < ActionController::TestCase assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html") end + def test_should_obey_http_accept_attribute + @request.env['HTTP_ACCEPT'] = 'text/xml' + get :about_me + assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/about_me.xml") + assert_equal 'I am xml', @response.body + end + def test_should_cache_with_trailing_slash_on_url @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/' assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html") -- cgit v1.2.3 From f0d4b7f2a655ca2fb435af798714fee2de232d1e Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 10 Dec 2010 09:34:40 +1000 Subject: root method options are the same as the match method --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index cf95f6fa53..3039f88f71 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -247,6 +247,8 @@ module ActionDispatch # # root :to => 'pages#main' # + # For options, see the +match+ method's documentation, as +root+ uses it internally. + # # You should put the root route at the top of config/routes.rb, # because this means it will be matched first. As this is the most popular route # of most Rails applications, this is beneficial. -- cgit v1.2.3 From dbf955c03b8d185b7977d90281389cf52d546c5d Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 10 Dec 2010 15:55:46 +1000 Subject: Action Controller Overview: Remove dead link to the API docs for filters --- actionpack/lib/action_dispatch/routing/mapper.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 3039f88f71..494cdbf308 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1089,6 +1089,7 @@ module ActionDispatch end end + # See ActionDispatch::Routing::Mapper::Scoping#namespace def namespace(path, options = {}) if resource_scope? nested { super } -- cgit v1.2.3 From 751733ab963cce8780a71185344d8b31ba93c91d Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Sat, 11 Dec 2010 17:25:28 +1000 Subject: Provide an example for ActionDispatch::Routing::Mapper#scope --- actionpack/lib/action_dispatch/routing/mapper.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 430fcdbe07..45248cf34c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -458,6 +458,18 @@ module ActionDispatch super end + # Used to scope a set of routes to particular constraints. + # + # Take the following route definition as an example: + # + # scope :path => ":account_id", :as => "account" do + # resources :projects + # end + # + # This generates helpers such as +account_projects_path+, just like +resources+ does. + # The difference here being that the routes generated are like /rails/projects/2, + # rather than /accounts/rails/projects/2. + # # === Supported options # [:module] # If you want to route /posts (without the prefix /admin) to -- cgit v1.2.3 From a6bc1f9be48095e2126a3726b5016fb760a8fdb4 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Mon, 13 Dec 2010 07:02:37 +1000 Subject: Remove nodoc from FormBuilder because the methods inside are public API methods --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- 1 file changed, 1 insertion(+), 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 ef5bbd8ae3..6f0e2c99ba 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1115,7 +1115,7 @@ module ActionView include InstanceTagMethods end - class FormBuilder #:nodoc: + class FormBuilder # The methods which wrap a form helper call. class_attribute :field_helpers self.field_helpers = (FormHelper.instance_method_names - ['form_for']) -- cgit v1.2.3 From a81f68e879198cb4e01f3cda2671c93f1ef0bc1a Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Mon, 13 Dec 2010 13:03:41 +1000 Subject: Fix indentation on the namespace method's documentation --- actionpack/lib/action_dispatch/routing/mapper.rb | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 45248cf34c..f65a294eca 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -570,13 +570,13 @@ module ActionDispatch # # This generates the following routes: # - # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"} - # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"} - # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"} - # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"} - # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"} - # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"} - # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} + # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"} + # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"} + # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"} + # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"} + # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"} + # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"} + # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"} # === Supported options # # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ options all default to the name of the namespace. @@ -584,24 +584,24 @@ module ActionDispatch # [:path] # The path prefix for the routes. # - # namespace :admin, :path => "sekret" do - # resources :posts - # end + # namespace :admin, :path => "sekret" do + # resources :posts + # end # # All routes for the above +resources+ will be accessible through +/sekret/posts+, rather than +/admin/posts+ # # [:module] # The namespace for the controllers. # - # namespace :admin, :module => "sekret" do - # resources :posts - # end + # namespace :admin, :module => "sekret" do + # resources :posts + # end # # The +PostsController+ here should go in the +Sekret+ namespace and so it should be defined like this: # - # class Sekret::PostsController < ApplicationController - # # code go here - # end + # class Sekret::PostsController < ApplicationController + # # code go here + # end # # [:as] # Changes the name used in routing helpers for this namespace. -- cgit v1.2.3 From 73dafba6ca484e1772fea8cd25ad27ff65c6c66b Mon Sep 17 00:00:00 2001 From: Ben Mills Date: Sun, 12 Dec 2010 23:20:06 -0700 Subject: Added :placeholder option to ActionView::Helpers::FormTagHelper text_field_tag --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 4 ++++ 1 file changed, 4 insertions(+) (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 50f065f03d..c41271635d 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -112,6 +112,7 @@ module ActionView # * :disabled - If set to true, the user will not be able to use this input. # * :size - The number of visible characters that will fit in the input. # * :maxlength - The maximum number of characters that the browser will allow the user to enter. + # * :placeholder - The text contained in the field by default which is removed when the field receives focus. # * Any other key creates standard HTML attributes for the tag. # # ==== Examples @@ -121,6 +122,9 @@ module ActionView # text_field_tag 'query', 'Enter your search query here' # # => # + # text_field_tag 'search', nil, :placeholder => 'Enter search term...' + # # => + # # text_field_tag 'request', nil, :class => 'special_input' # # => # -- cgit v1.2.3 From 6fc3750471ff9642395c4e0462d5059c2133d9aa Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Wed, 15 Dec 2010 16:13:36 +0530 Subject: eternal confusion! fixed doco to inform correctly --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 c41271635d..9500e85e8b 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -68,7 +68,7 @@ module ActionView # * Any other key creates standard HTML attributes for the tag. # # ==== Examples - # select_tag "people", options_from_collection_for_select(@people, "name", "id") + # select_tag "people", options_from_collection_for_select(@people, "id", "name") # # # # select_tag "people", "" -- cgit v1.2.3 From a462a76bd323ef0087ead0bf0d1792a95655975c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 09:01:18 +0100 Subject: Set proper engine's asset directories when assets are served from engine. When using stylesheet_link_tag(:all) or javascript_include_tag(:all), assets directories are searched for css or js files. When config.serve_static_assets is set to true, those files can be served directly from engine's directories. That's why assets paths should be set individually for controllers inside engine if we want to serve static assets with ActionDispatch::Static --- actionpack/lib/action_controller/railties/paths.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index 699c44c62c..dce3c2fe88 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -16,6 +16,14 @@ module ActionController if klass.superclass == ActionController::Base && ActionController::Base.include_all_helpers klass.helper :all end + + if app.config.serve_static_assets && namespace + paths = namespace._railtie.config.paths + + klass.config.assets_dir = paths["public"].first + klass.config.javascripts_dir = paths["public/javascripts"].first + klass.config.stylesheets_dir = paths["public/stylesheets"].first + end end end end -- cgit v1.2.3 From ebc47465a5865ab91dc7d058d2d8a0cc961510d7 Mon Sep 17 00:00:00 2001 From: brainopia Date: Thu, 9 Dec 2010 18:38:52 +0300 Subject: Fix edge cases for domain :all option on cookie store Dont set explicit domain for cookies if host is not a domain name [#6002 state:committed] Signed-off-by: Santiago Pastorino --- .../lib/action_dispatch/middleware/cookies.rb | 7 +++++-- actionpack/test/dispatch/cookies_test.rb | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index b0a4e3d949..f369d2d3c2 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -131,8 +131,11 @@ module ActionDispatch options[:path] ||= "/" if options[:domain] == :all - @host =~ DOMAIN_REGEXP - options[:domain] = ".#{$1}.#{$2}" + # if host is not ip and matches domain regexp + # (ip confirms to domain regexp so we explicitly check for ip) + options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ DOMAIN_REGEXP) + ".#{$1}.#{$2}" + end end end diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 5ec7f12cc1..e2040401c7 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -295,6 +295,27 @@ class CookiesTest < ActionController::TestCase assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/" end + def test_cookie_with_all_domain_option_using_localhost + @request.host = "localhost" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + + def test_cookie_with_all_domain_option_using_ipv4_address + @request.host = "192.168.1.1" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + + def test_cookie_with_all_domain_option_using_ipv6_address + @request.host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + def test_deleting_cookie_with_all_domain_option get :delete_cookie_with_domain assert_response :success -- cgit v1.2.3 From 96bae30538951367a82235785e7dba3577b50a5a Mon Sep 17 00:00:00 2001 From: Pavel Gorbokon Date: Wed, 24 Nov 2010 10:17:49 +0200 Subject: Replace rudimentary named_scope with scope. [#6052 state:resolved] * rename method names (actually in tests) * rename instance variable @_named_scopes_cache to @_scopes_cache * rename references in doc comments * don't touch CHANGELOG :) --- .../activerecord/render_partial_with_record_identification_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack') diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb index 43c534c111..99f09286ff 100644 --- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb +++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb @@ -11,7 +11,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base render :partial => @topic.replies end - def render_with_named_scope + def render_with_scope render :partial => Reply.base end @@ -62,8 +62,8 @@ class RenderPartialWithRecordIdentificationTest < ActiveRecordTestCase assert_equal 'Birdman is better!', @response.body end - def test_rendering_partial_with_named_scope - get :render_with_named_scope + def test_rendering_partial_with_scope + get :render_with_scope assert_template 'replies/_reply' assert_equal 'Birdman is better!Nuh uh!', @response.body end -- cgit v1.2.3 From e89fff2f6b815529cf729fc8e900a8275c9514e8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 16 Dec 2010 21:37:48 +0100 Subject: Bring back config.action_view.cache_template_loading [#5847 state:resolved] --- actionpack/lib/action_view/base.rb | 8 ++++++++ actionpack/lib/action_view/railtie.rb | 10 +++++++++- actionpack/lib/action_view/template/resolver.rb | 11 ++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 15944138f7..92ff3380b0 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -172,6 +172,14 @@ module ActionView #:nodoc: class << self delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB' delegate :logger, :to => 'ActionController::Base', :allow_nil => true + + def cache_template_loading + ActionView::Resolver.caching? + end + + def cache_template_loading=(value) + ActionView::Resolver.caching = value + end end attr_accessor :_template diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb index 71cd1a788a..501ec07b09 100644 --- a/actionpack/lib/action_view/railtie.rb +++ b/actionpack/lib/action_view/railtie.rb @@ -35,5 +35,13 @@ module ActionView end end end + + initializer "action_view.caching" do |app| + ActiveSupport.on_load(:action_view) do + if app.config.action_view.cache_template_loading.nil? + ActionView::Resolver.caching = app.config.cache_classes + end + end + end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index a17454da28..0dccc99d14 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -5,6 +5,13 @@ require "action_view/template" module ActionView # = Action View Resolver class Resolver + cattr_accessor :caching + self.caching = true + + class << self + alias :caching? :caching + end + def initialize @cached = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2| h2[k2] = Hash.new { |h3,k3| h3[k3] = Hash.new { |h4,k4| h4[k4] = {} } } } } @@ -23,9 +30,7 @@ module ActionView private - def caching? - @caching ||= !defined?(Rails.application) || Rails.application.config.cache_classes - end + delegate :caching?, :to => "self.class" # This is what child classes implement. No defaults are needed # because Resolver guarantees that the arguments are present and -- cgit v1.2.3 From f176b2552ecc06634dae53b82a4562d8e80aeed6 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 16 Dec 2010 22:53:19 +0100 Subject: Changelog and guide entries for config.action_view.cache_template_loading --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index acd9bd5b63..93b29bcc3a 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* brought back config.action_view.cache_template_loading, which allows to decide whether templates should be cached or not [Piotr Sarnacki] + * url_for and named url helpers now accept :subdomain and :domain as options [Josh Kalderimis] * The redirect route method now also accepts a hash of options which will only change the parts of the url in question, or an object which responds to call, allowing for redirects to be reused (check the documentation for examples). [Josh Kalderimis] -- cgit v1.2.3 From 006ec77e60163d57d655479602230672d98e0f10 Mon Sep 17 00:00:00 2001 From: Don Wilson Date: Thu, 16 Dec 2010 11:37:11 -0200 Subject: Fixed number_with_precision rounding error [#6182 state:resolved] --- actionpack/lib/action_view/helpers/number_helper.rb | 5 +++-- actionpack/test/template/number_helper_test.rb | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index a9400c347f..650828052f 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -270,12 +270,13 @@ module ActionView digits, rounded_number = 1, 0 else digits = (Math.log10(number.abs) + 1).floor - rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision) + rounded_number = (BigDecimal.new(number.to_s) / 10 ** (digits - precision)).round.to_f * 10 ** (digits - precision) + digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed end precision -= digits precision = precision > 0 ? precision : 0 #don't let it be negative else - rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision + rounded_number = BigDecimal.new(number.to_s).round(precision).to_f end formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options) if strip_insignificant_zeros diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index ab127521ad..6b234cfbb9 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -100,6 +100,11 @@ class NumberHelperTest < ActionView::TestCase assert_equal("0", number_with_precision(0, :precision => 0)) assert_equal("0.00100", number_with_precision(0.001, :precision => 5)) assert_equal("0.001", number_with_precision(0.00111, :precision => 3)) + assert_equal("10.00", number_with_precision(9.995, :precision => 2)) + assert_equal("11.00", number_with_precision(10.995, :precision => 2)) + assert_equal("10.0", number_with_precision(9.995, :precision => 3, :significant => true)) + assert_equal("9.99", number_with_precision(9.994, :precision => 3, :significant => true)) + assert_equal("11.0", number_with_precision(10.995, :precision => 3, :significant => true)) end def test_number_with_precision_with_custom_delimiter_and_separator -- cgit v1.2.3 From 07567aea5f0c6f14a53f511ab4cc46201b669795 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 17 Dec 2010 16:11:47 +0100 Subject: Revert "Fixed number_with_precision rounding error [#6182 state:resolved]" This reverts commit 006ec77e60163d57d655479602230672d98e0f10. --- actionpack/lib/action_view/helpers/number_helper.rb | 5 ++--- actionpack/test/template/number_helper_test.rb | 5 ----- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 650828052f..a9400c347f 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -270,13 +270,12 @@ module ActionView digits, rounded_number = 1, 0 else digits = (Math.log10(number.abs) + 1).floor - rounded_number = (BigDecimal.new(number.to_s) / 10 ** (digits - precision)).round.to_f * 10 ** (digits - precision) - digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed + rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision) end precision -= digits precision = precision > 0 ? precision : 0 #don't let it be negative else - rounded_number = BigDecimal.new(number.to_s).round(precision).to_f + rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision end formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options) if strip_insignificant_zeros diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 6b234cfbb9..ab127521ad 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -100,11 +100,6 @@ class NumberHelperTest < ActionView::TestCase assert_equal("0", number_with_precision(0, :precision => 0)) assert_equal("0.00100", number_with_precision(0.001, :precision => 5)) assert_equal("0.001", number_with_precision(0.00111, :precision => 3)) - assert_equal("10.00", number_with_precision(9.995, :precision => 2)) - assert_equal("11.00", number_with_precision(10.995, :precision => 2)) - assert_equal("10.0", number_with_precision(9.995, :precision => 3, :significant => true)) - assert_equal("9.99", number_with_precision(9.994, :precision => 3, :significant => true)) - assert_equal("11.0", number_with_precision(10.995, :precision => 3, :significant => true)) end def test_number_with_precision_with_custom_delimiter_and_separator -- cgit v1.2.3 From 5008d33eee4767cd84b1087ceec827f1eaec90d0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 17 Dec 2010 11:31:08 -0800 Subject: dry up case / when statement --- actionpack/lib/action_dispatch/routing/polymorphic_routes.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 49e237f8db..82c4fadb50 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -99,11 +99,9 @@ module ActionDispatch record = extract_record(record_or_hash_or_array) record = record.to_model if record.respond_to?(:to_model) - args = case record_or_hash_or_array - when Hash; [ record_or_hash_or_array ] - when Array; record_or_hash_or_array.dup - else [ record_or_hash_or_array ] - end + args = Array === record_or_hash_or_array ? + record_or_hash_or_array.dup : + [ record_or_hash_or_array ] inflection = if options[:action] && options[:action].to_s == "new" args.pop -- cgit v1.2.3 From f71809f25761440cbec9463bbc082987c90a471b Mon Sep 17 00:00:00 2001 From: Don Wilson Date: Fri, 17 Dec 2010 09:56:03 -0700 Subject: Fixed number_with_precision rounding error [#6182 state:resolved] --- actionpack/lib/action_view/helpers/number_helper.rb | 5 +++-- actionpack/test/template/number_helper_test.rb | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index a9400c347f..26f8dce3c3 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -270,12 +270,13 @@ module ActionView digits, rounded_number = 1, 0 else digits = (Math.log10(number.abs) + 1).floor - rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision) + rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision) + digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed end precision -= digits precision = precision > 0 ? precision : 0 #don't let it be negative else - rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision + rounded_number = BigDecimal.new(number.to_s).round(precision).to_f end formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options) if strip_insignificant_zeros diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index ab127521ad..156b7cb5ff 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -100,6 +100,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal("0", number_with_precision(0, :precision => 0)) assert_equal("0.00100", number_with_precision(0.001, :precision => 5)) assert_equal("0.001", number_with_precision(0.00111, :precision => 3)) + assert_equal("10.00", number_with_precision(9.995, :precision => 2)) + assert_equal("11.00", number_with_precision(10.995, :precision => 2)) end def test_number_with_precision_with_custom_delimiter_and_separator @@ -125,6 +127,9 @@ class NumberHelperTest < ActionView::TestCase assert_equal "0.0001", number_with_precision(0.0001, :precision => 1, :significant => true ) assert_equal "0.000100", number_with_precision(0.0001, :precision => 3, :significant => true ) assert_equal "0.0001", number_with_precision(0.0001111, :precision => 1, :significant => true ) + assert_equal "10.0", number_with_precision(9.995, :precision => 3, :significant => true) + assert_equal "9.99", number_with_precision(9.994, :precision => 3, :significant => true) + assert_equal "11.0", number_with_precision(10.995, :precision => 3, :significant => true) end def test_number_with_precision_with_strip_insignificant_zeros -- cgit v1.2.3 From f249d07c44d2f18e508ac83153c9f9cb8bce340b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 19 Dec 2010 13:53:08 -0200 Subject: Add missing require --- actionpack/lib/action_controller/caching/pages.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 3e57d2c236..f305ed30fa 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -1,4 +1,5 @@ require 'fileutils' +require 'active_support/concern' require 'active_support/core_ext/class/attribute_accessors' module ActionController #:nodoc: -- cgit v1.2.3 From ab2bde45f8140a3ebf8b478e688ef612fc4181fc Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 19 Dec 2010 19:15:26 -0200 Subject: Remove require AS::Concern from places where is already in --- actionpack/lib/action_controller/caching/pages.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index f305ed30fa..3e57d2c236 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -1,5 +1,4 @@ require 'fileutils' -require 'active_support/concern' require 'active_support/core_ext/class/attribute_accessors' module ActionController #:nodoc: -- cgit v1.2.3 From 0f7c970e4f1cf0f3bcc01c22a6a3038cb3e34668 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 23 Nov 2010 18:04:05 -0800 Subject: Introduce ActionDispatch::Reloader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the implementation on the 2-3-stable branch, patches by Hongli Lai , and helpful suggestions from José Valim. Hongli Lai's patches included locking around the request cycle; this is now handled by Rack::Lock (https://github.com/rack/rack/issues/issue/87/). [#2873] Signed-off-by: José Valim --- actionpack/lib/action_dispatch.rb | 1 + .../lib/action_dispatch/middleware/reloader.rb | 82 ++++++++++++ actionpack/test/dispatch/reloader_test.rb | 139 +++++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 actionpack/lib/action_dispatch/middleware/reloader.rb create mode 100644 actionpack/test/dispatch/reloader_test.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 50faf666e6..50d0d191c1 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -53,6 +53,7 @@ module ActionDispatch autoload :Flash autoload :Head autoload :ParamsParser + autoload :Reloader autoload :RemoteIp autoload :Rescue autoload :ShowExceptions diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb new file mode 100644 index 0000000000..b84410fc62 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -0,0 +1,82 @@ +module ActionDispatch + # ActionDispatch::Reloader provides to_prepare and to_cleanup callbacks. + # These are analogs of ActionDispatch::Callback's before and after + # callbacks, with the difference that to_cleanup is not called until the + # request is fully complete -- that is, after #close has been called on + # the request body. This is important for streaming responses such as the + # following: + # + # self.response_body = lambda { |response, output| + # # code here which refers to application models + # } + # + # Cleanup callbacks will not be called until after the response_body lambda + # is evaluated, ensuring that it can refer to application models and other + # classes before they are unloaded. + # + # By default, ActionDispatch::Reloader is included in the middleware stack + # only in the development environment. + # + class Reloader + include ActiveSupport::Callbacks + + define_callbacks :prepare, :scope => :name + define_callbacks :cleanup, :scope => :name + + # Add a preparation callback. Preparation callbacks are run before each + # request. + # + # If a symbol with a block is given, the symbol is used as an identifier. + # That allows to_prepare to be called again with the same identifier to + # replace the existing callback. Passing an identifier is a suggested + # practice if the code adding a preparation block may be reloaded. + def self.to_prepare(*args, &block) + first_arg = args.first + if first_arg.is_a?(Symbol) && block_given? + remove_method :"__#{first_arg}" if method_defined?(:"__#{first_arg}") + define_method :"__#{first_arg}", &block + set_callback(:prepare, :"__#{first_arg}") + else + set_callback(:prepare, *args, &block) + end + end + + # Add a cleanup callback. Cleanup callbacks are run after each request is + # complete (after #close is called on the response body). + def self.to_cleanup(&block) + set_callback(:cleanup, &block) + end + + def self.prepare! + new(nil).send(:_run_prepare_callbacks) + end + + def self.cleanup! + new(nil).send(:_run_cleanup_callbacks) + end + + def self.reload! + prepare! + cleanup! + end + + def initialize(app) + @app = app + end + + module CleanupOnClose + def close + super if defined?(super) + ensure + ActionDispatch::Reloader.cleanup! + end + end + + def call(env) + _run_prepare_callbacks + response = @app.call(env) + response[2].extend(CleanupOnClose) + response + end + end +end diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb new file mode 100644 index 0000000000..58ef346b5c --- /dev/null +++ b/actionpack/test/dispatch/reloader_test.rb @@ -0,0 +1,139 @@ +require 'abstract_unit' + +class ReloaderTest < Test::Unit::TestCase + Reloader = ActionDispatch::Reloader + + def test_prepare_callbacks + a = b = c = nil + Reloader.to_prepare { |*args| a = b = c = 1 } + Reloader.to_prepare { |*args| b = c = 2 } + Reloader.to_prepare { |*args| c = 3 } + + # Ensure to_prepare callbacks are not run when defined + assert_nil a || b || c + + # Run callbacks + call_and_return_body + + assert_equal 1, a + assert_equal 2, b + assert_equal 3, c + end + + def test_to_prepare_with_identifier_replaces + a = b = 0 + Reloader.to_prepare(:unique_id) { |*args| a = b = 1 } + Reloader.to_prepare(:unique_id) { |*args| a = 2 } + + call_and_return_body + assert_equal 2, a + assert_equal 0, b + end + + class MyBody < Array + def initialize(&block) + @on_close = block + end + + def foo + "foo" + end + + def bar + "bar" + end + + def close + @on_close.call if @on_close + end + end + + def test_returned_body_object_always_responds_to_close + body = call_and_return_body + assert body.respond_to?(:close) + end + + def test_returned_body_object_behaves_like_underlying_object + body = call_and_return_body do + b = MyBody.new + b << "hello" + b << "world" + [200, { "Content-Type" => "text/html" }, b] + end + assert_equal 2, body.size + assert_equal "hello", body[0] + assert_equal "world", body[1] + assert_equal "foo", body.foo + assert_equal "bar", body.bar + end + + def test_it_calls_close_on_underlying_object_when_close_is_called_on_body + close_called = false + body = call_and_return_body do + b = MyBody.new do + close_called = true + end + [200, { "Content-Type" => "text/html" }, b] + end + body.close + assert close_called + end + + def test_returned_body_object_responds_to_all_methods_supported_by_underlying_object + body = call_and_return_body do + [200, { "Content-Type" => "text/html" }, MyBody.new] + end + assert body.respond_to?(:size) + assert body.respond_to?(:each) + assert body.respond_to?(:foo) + assert body.respond_to?(:bar) + end + + def test_cleanup_callbacks_are_called_when_body_is_closed + cleaned = false + Reloader.to_cleanup { cleaned = true } + + body = call_and_return_body + assert !cleaned + + body.close + assert cleaned + end + + def test_prepare_callbacks_arent_called_when_body_is_closed + prepared = false + Reloader.to_prepare { prepared = true } + + body = call_and_return_body + prepared = false + + body.close + assert !prepared + end + + def test_manual_reloading + prepared = cleaned = false + Reloader.to_prepare { prepared = true } + Reloader.to_cleanup { cleaned = true } + + Reloader.prepare! + assert prepared + assert !cleaned + + prepared = cleaned = false + Reloader.cleanup! + assert !prepared + assert cleaned + + prepared = cleaned = false + Reloader.reload! + assert prepared + assert cleaned + end + + private + def call_and_return_body(&block) + @reloader ||= Reloader.new(block || proc {[200, {}, 'response']}) + @reloader.call({'rack.input' => StringIO.new('')})[2] + end +end -- cgit v1.2.3 From 435bccda930e4dde3d0fafca958e1c8330b4c3ca Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 19 Dec 2010 15:58:58 -0800 Subject: Replace AD::Callbacks.to_prepare with AD::Reloader.to_prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../lib/action_dispatch/middleware/callbacks.rb | 31 ++-------- actionpack/test/dispatch/callbacks_test.rb | 72 ++++------------------ 2 files changed, 19 insertions(+), 84 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index 0bb950d1cc..5776a7bb27 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -1,32 +1,14 @@ module ActionDispatch # Provide callbacks to be executed before and after the request dispatch. - # - # It also provides a to_prepare callback, which is performed in all requests - # in development by only once in production and notification callback for async - # operations. - # class Callbacks include ActiveSupport::Callbacks define_callbacks :call, :rescuable => true - define_callbacks :prepare, :scope => :name - # Add a preparation callback. Preparation callbacks are run before every - # request in development mode, and before the first request in production mode. - # - # If a symbol with a block is given, the symbol is used as an identifier. - # That allows to_prepare to be called again with the same identifier to - # replace the existing callback. Passing an identifier is a suggested - # practice if the code adding a preparation block may be reloaded. def self.to_prepare(*args, &block) - first_arg = args.first - if first_arg.is_a?(Symbol) && block_given? - remove_method :"__#{first_arg}" if method_defined?(:"__#{first_arg}") - define_method :"__#{first_arg}", &block - set_callback(:prepare, :"__#{first_arg}") - else - set_callback(:prepare, *args, &block) - end + ActiveSupport::Deprecation.warn "ActionDispatch::Callbacks.to_prepare is deprecated. " << + "Please use ActionDispatch::Reloader.to_prepare instead." + ActionDispatch::Reloader.to_prepare(*args, &block) end def self.before(*args, &block) @@ -37,14 +19,13 @@ module ActionDispatch set_callback(:call, :after, *args, &block) end - def initialize(app, prepare_each_request = false) - @app, @prepare_each_request = app, prepare_each_request - _run_prepare_callbacks + def initialize(app, unused = nil) + ActiveSupport::Deprecation.warn "Passing a second argument to ActionDispatch::Callbacks.new is deprecated." unless unused.nil? + @app = app end def call(env) _run_call_callbacks do - _run_prepare_callbacks if @prepare_each_request @app.call(env) end end diff --git a/actionpack/test/dispatch/callbacks_test.rb b/actionpack/test/dispatch/callbacks_test.rb index d3aa55a1ba..5becb621de 100644 --- a/actionpack/test/dispatch/callbacks_test.rb +++ b/actionpack/test/dispatch/callbacks_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class DispatcherTest < Test::Unit::TestCase +class DispatcherTest < ActiveSupport::TestCase class Foo cattr_accessor :a, :b end @@ -13,65 +13,9 @@ class DispatcherTest < Test::Unit::TestCase def setup Foo.a, Foo.b = 0, 0 - ActionDispatch::Callbacks.reset_callbacks(:prepare) ActionDispatch::Callbacks.reset_callbacks(:call) end - def test_prepare_callbacks_with_cache_classes - a = b = c = nil - ActionDispatch::Callbacks.to_prepare { |*args| a = b = c = 1 } - ActionDispatch::Callbacks.to_prepare { |*args| b = c = 2 } - ActionDispatch::Callbacks.to_prepare { |*args| c = 3 } - - # Ensure to_prepare callbacks are not run when defined - assert_nil a || b || c - - # Run callbacks - dispatch - - assert_equal 1, a - assert_equal 2, b - assert_equal 3, c - - # Make sure they are only run once - a = b = c = nil - dispatch - assert_nil a || b || c - end - - def test_prepare_callbacks_without_cache_classes - a = b = c = nil - ActionDispatch::Callbacks.to_prepare { |*args| a = b = c = 1 } - ActionDispatch::Callbacks.to_prepare { |*args| b = c = 2 } - ActionDispatch::Callbacks.to_prepare { |*args| c = 3 } - - # Ensure to_prepare callbacks are not run when defined - assert_nil a || b || c - - # Run callbacks - dispatch(false) - - assert_equal 1, a - assert_equal 2, b - assert_equal 3, c - - # Make sure they are run again - a = b = c = nil - dispatch(false) - assert_equal 1, a - assert_equal 2, b - assert_equal 3, c - end - - def test_to_prepare_with_identifier_replaces - ActionDispatch::Callbacks.to_prepare(:unique_id) { |*args| Foo.a, Foo.b = 1, 1 } - ActionDispatch::Callbacks.to_prepare(:unique_id) { |*args| Foo.a = 2 } - - dispatch - assert_equal 2, Foo.a - assert_equal 0, Foo.b - end - def test_before_and_after_callbacks ActionDispatch::Callbacks.before { |*args| Foo.a += 1; Foo.b += 1 } ActionDispatch::Callbacks.after { |*args| Foo.a += 1; Foo.b += 1 } @@ -85,10 +29,20 @@ class DispatcherTest < Test::Unit::TestCase assert_equal 4, Foo.b end + def test_to_prepare_deprecation + prepared = false + assert_deprecated do + ActionDispatch::Callbacks.to_prepare { prepared = true } + end + + ActionDispatch::Reloader.prepare! + assert prepared + end + private - def dispatch(cache_classes = true, &block) - @dispatcher ||= ActionDispatch::Callbacks.new(block || DummyApp.new, !cache_classes) + def dispatch(&block) + @dispatcher ||= ActionDispatch::Callbacks.new(block || DummyApp.new) @dispatcher.call({'rack.input' => StringIO.new('')}) end -- cgit v1.2.3 From 0cbfd6c28d327304432f7d0c067662b5c1e41a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 20 Dec 2010 12:41:49 +0100 Subject: Small changes on AD::Reloader. --- .../lib/action_dispatch/middleware/reloader.rb | 23 +++----------------- actionpack/test/dispatch/reloader_test.rb | 25 +++++----------------- 2 files changed, 8 insertions(+), 40 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb index b84410fc62..579b5d8a02 100644 --- a/actionpack/lib/action_dispatch/middleware/reloader.rb +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -25,26 +25,14 @@ module ActionDispatch # Add a preparation callback. Preparation callbacks are run before each # request. - # - # If a symbol with a block is given, the symbol is used as an identifier. - # That allows to_prepare to be called again with the same identifier to - # replace the existing callback. Passing an identifier is a suggested - # practice if the code adding a preparation block may be reloaded. def self.to_prepare(*args, &block) - first_arg = args.first - if first_arg.is_a?(Symbol) && block_given? - remove_method :"__#{first_arg}" if method_defined?(:"__#{first_arg}") - define_method :"__#{first_arg}", &block - set_callback(:prepare, :"__#{first_arg}") - else - set_callback(:prepare, *args, &block) - end + set_callback(:prepare, *args, &block) end # Add a cleanup callback. Cleanup callbacks are run after each request is # complete (after #close is called on the response body). - def self.to_cleanup(&block) - set_callback(:cleanup, &block) + def self.to_cleanup(*args, &block) + set_callback(:cleanup, *args, &block) end def self.prepare! @@ -55,11 +43,6 @@ module ActionDispatch new(nil).send(:_run_cleanup_callbacks) end - def self.reload! - prepare! - cleanup! - end - def initialize(app) @app = app end diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb index 58ef346b5c..995b19030c 100644 --- a/actionpack/test/dispatch/reloader_test.rb +++ b/actionpack/test/dispatch/reloader_test.rb @@ -20,16 +20,6 @@ class ReloaderTest < Test::Unit::TestCase assert_equal 3, c end - def test_to_prepare_with_identifier_replaces - a = b = 0 - Reloader.to_prepare(:unique_id) { |*args| a = b = 1 } - Reloader.to_prepare(:unique_id) { |*args| a = 2 } - - call_and_return_body - assert_equal 2, a - assert_equal 0, b - end - class MyBody < Array def initialize(&block) @on_close = block @@ -50,7 +40,7 @@ class ReloaderTest < Test::Unit::TestCase def test_returned_body_object_always_responds_to_close body = call_and_return_body - assert body.respond_to?(:close) + assert_respond_to body, :close end def test_returned_body_object_behaves_like_underlying_object @@ -83,10 +73,10 @@ class ReloaderTest < Test::Unit::TestCase body = call_and_return_body do [200, { "Content-Type" => "text/html" }, MyBody.new] end - assert body.respond_to?(:size) - assert body.respond_to?(:each) - assert body.respond_to?(:foo) - assert body.respond_to?(:bar) + assert_respond_to body, :size + assert_respond_to body, :each + assert_respond_to body, :foo + assert_respond_to body, :bar end def test_cleanup_callbacks_are_called_when_body_is_closed @@ -124,11 +114,6 @@ class ReloaderTest < Test::Unit::TestCase Reloader.cleanup! assert !prepared assert cleaned - - prepared = cleaned = false - Reloader.reload! - assert prepared - assert cleaned end private -- cgit v1.2.3