From 01f3f0dbae3e5ecfd18109a0f2ec37ed0d767a8e Mon Sep 17 00:00:00 2001
From: Xavier Noria
Date: Wed, 16 Jun 2010 22:30:06 +0200
Subject: use RDoc 2.2 to generate the documentation of individual components
---
actionpack/Rakefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'actionpack')
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index f3bd7dfc10..aed5278e38 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -1,4 +1,5 @@
-require 'rubygems'
+gem 'rdoc', '= 2.2'
+require 'rdoc'
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
--
cgit v1.2.3
From a424808df95c5ebe66d02f0d743e741a1864baa7 Mon Sep 17 00:00:00 2001
From: Wincent Colaiuta
Date: Thu, 17 Jun 2010 08:39:13 +0200
Subject: truncate() should not try to produce HTML-safe output
As discussed in Lighthouse ticket #4825 and ticket #4878, the truncate()
method cannot guarantee safe output for all possible inputs/offsets, so
it is best to leave the output unsafe so that it gets escaped when used
in a view.
Signed-off-by: Santiago Pastorino
Signed-off-by: David Heinemeier Hansson
---
actionpack/lib/action_view/helpers/text_helper.rb | 12 ++++--------
actionpack/test/template/text_helper_test.rb | 18 ++++--------------
2 files changed, 8 insertions(+), 22 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 3b37fd6b57..654f3c89f3 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -39,7 +39,10 @@ module ActionView
# for a total length not exceeding :length.
#
# Pass a :separator to truncate +text+ at a natural break.
- # Pass a :safe value as "true" to not to escape the content.
+ #
+ # The result is not marked as HTML-safe, so will be subject to the default escaping when
+ # used in views, unless wrapped by raw(). Care should be taken if +text+ contains HTML tags
+ # or entities, because truncation may produce invalid HTML (such as unbalanced or incomplete tags).
#
# ==== Examples
#
@@ -56,12 +59,6 @@ module ActionView
# # => "And they f... (continued)"
#
# truncate("
Once upon a time in a world far far away
")
- # # => "<p>Once upon a time i..."
- #
- # truncate("
Once upon a time in a world far far away
", :safe => true)
- # # => "
Once upon a time in a wo..."
- #
- # truncate("
Once upon a time in a world far far away
".html_safe)
# # => "
Once upon a time in a wo..."
#
# You can still use truncate with the old API that accepts the
@@ -84,7 +81,6 @@ module ActionView
options.reverse_merge!(:length => 30)
- text = h(text) unless text.html_safe? || options[:safe]
text.truncate(options.delete(:length), options) if text
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index b0a4c2a9cc..1cd6a5941d 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -52,8 +52,8 @@ class TextHelperTest < ActionView::TestCase
assert_equal "
test with safe string
", simple_format(" test with safe string ".html_safe)
end
- def test_truncate_should_be_html_safe
- assert truncate("Hello World!", :length => 12).html_safe?
+ def test_truncate_should_not_be_html_safe
+ assert !truncate("Hello World!", :length => 12).html_safe?
end
def test_truncate
@@ -61,18 +61,8 @@ class TextHelperTest < ActionView::TestCase
assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12)
end
- def test_truncate_should_escape_unsafe_input
- assert_equal "Hello <...", truncate("Hello World!!", :length => 12)
- end
-
- def test_truncate_should_not_escape_input_if_safe_option
- assert_equal "Hello code!World!", :length => 12, :safe => true)
- assert_equal "Hello code!World!!", :length => 12, :safe => true)
- end
-
- def test_truncate_should_not_escape_safe_input
- assert_equal "Hello code!World!".html_safe, :length => 12)
- assert_equal "Hello code!World!!".html_safe, :length => 12)
+ def test_truncate_should_not_escape_input
+ assert_equal "Hello code!World!!", :length => 12)
end
def test_truncate_should_use_default_length_of_30
--
cgit v1.2.3
From 7240a960f2e515316ac4d962482f678b67b83b8c Mon Sep 17 00:00:00 2001
From: Santiago Pastorino
Date: Thu, 17 Jun 2010 07:37:33 -0300
Subject: excerpt shoudn't return safe output test added
[#4878]
Signed-off-by: David Heinemeier Hansson
---
actionpack/test/template/text_helper_test.rb | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'actionpack')
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index 1cd6a5941d..82c81ddf05 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -207,6 +207,10 @@ class TextHelperTest < ActionView::TestCase
assert_nil excerpt("This is a beautiful morning", "day")
end
+ def test_excerpt_should_not_be_html_safe
+ assert !excerpt('This is a beautiful! morning', 'beautiful', 5).html_safe?
+ end
+
def test_excerpt_in_borderline_cases
assert_equal("", excerpt("", "", 0))
assert_equal("a", excerpt("a", "a", 0))
--
cgit v1.2.3
From 6db9558416cf2133adacbe1634f28c25bfe618d6 Mon Sep 17 00:00:00 2001
From: Andrew White
Date: Thu, 10 Jun 2010 18:31:28 +0100
Subject: Add shallow routing option to new router [#3765 status:committed]
Signed-off-by: David Heinemeier Hansson
---
actionpack/CHANGELOG | 10 +
actionpack/lib/action_dispatch/routing/mapper.rb | 404 ++++++++++++++---------
actionpack/test/dispatch/routing_test.rb | 125 +++++++
3 files changed, 383 insertions(+), 156 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 967bd76025..cee79c6c11 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,15 @@
*Rails 3.0.0 [Release Candidate] (unreleased)*
+* Add shallow routes back to the new router [Diego Carrion]
+
+ resources :posts do
+ shallow do
+ resources :comments
+ end
+ end
+
+ You can now use comment_path for /comments/1 instead of post_comment_path for /posts/1/comments/1.
+
* Add support for multi-subdomain session by setting cookie host in session cookie so you can share session between www.example.com, example.com and user.example.com. #4818 [Guillermo Álvarez]
* Removed textilize, textilize_without_paragraph and markdown helpers. [Santiago Pastorino]
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 7b79b6bde3..46304b0336 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -33,7 +33,7 @@ module ActionDispatch
end
class Mapping #:nodoc:
- IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor]
+ IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow]
def initialize(set, scope, args)
@set, @scope = set, scope
@@ -409,11 +409,13 @@ module ActionDispatch
def merge_options_scope(parent, child)
(parent || {}).merge(child)
end
+
+ def merge_shallow_scope(parent, child)
+ child ? true : false
+ end
end
module Resources
- CRUD_ACTIONS = [:index, :show, :create, :update, :destroy] #:nodoc:
-
class Resource #:nodoc:
def self.default_actions
[:index, :create, :new, :show, :update, :destroy, :edit]
@@ -442,15 +444,6 @@ module ActionDispatch
end
end
- def action_type(action)
- case action
- when :index, :create
- :collection
- when :show, :update, :destroy
- :member
- end
- end
-
def name
options[:as] || @name
end
@@ -463,34 +456,19 @@ module ActionDispatch
name.to_s.singularize
end
- def member_prefix
- ':id'
- end
-
def member_name
singular
end
+ alias_method :nested_name, :member_name
+
# Checks for uncountable plurals, and appends "_index" if they're.
def collection_name
- uncountable? ? "#{plural}_index" : plural
- end
-
- def uncountable?
- singular == plural
- end
-
- def name_for_action(action)
- case action_type(action)
- when :collection
- collection_name
- when :member
- member_name
- end
+ singular == plural ? "#{plural}_index" : plural
end
- def id_segment
- ":#{singular}_id"
+ def shallow?
+ options[:shallow] ? true : false
end
def constraints
@@ -506,21 +484,43 @@ module ActionDispatch
end
def collection_options
- (options || {}).dup.tap do |options|
- options.delete(:id)
- options[:constraints] = options[:constraints].dup if options[:constraints]
- options[:constraints].delete(:id) if options[:constraints].is_a?(Hash)
+ (options || {}).dup.tap do |opts|
+ opts.delete(:id)
+ opts[:constraints] = options[:constraints].dup if options[:constraints]
+ opts[:constraints].delete(:id) if options[:constraints].is_a?(Hash)
end
end
- def nested_prefix
- id_segment
+ def nested_path
+ "#{path}/:#{singular}_id"
end
def nested_options
- options = { :name_prefix => member_name }
- options["#{singular}_id".to_sym] = id_constraint if id_constraint?
- options
+ {}.tap do |opts|
+ opts[:name_prefix] = member_name
+ opts["#{singular}_id".to_sym] = id_constraint if id_constraint?
+ opts[:options] = { :shallow => shallow? } unless options[:shallow].nil?
+ end
+ end
+
+ def resource_scope
+ [{ :controller => controller }]
+ end
+
+ def collection_scope
+ [path, collection_options]
+ end
+
+ def member_scope
+ ["#{path}/:id", options]
+ end
+
+ def new_scope
+ [path]
+ end
+
+ def nested_scope
+ [nested_path, nested_options]
end
end
@@ -533,27 +533,27 @@ module ActionDispatch
super
end
- def action_type(action)
- case action
- when :show, :create, :update, :destroy
- :member
- end
+ def member_name
+ name
end
- def member_prefix
- ''
+ def nested_path
+ path
end
- def member_name
- name
+ def nested_options
+ {}.tap do |opts|
+ opts[:name_prefix] = member_name
+ opts[:options] = { :shallow => shallow? } unless @options[:shallow].nil?
+ end
end
- def nested_prefix
- ''
+ def shallow?
+ false
end
- def nested_options
- { :name_prefix => member_name }
+ def member_scope
+ [path, options]
end
end
@@ -565,28 +565,25 @@ module ActionDispatch
def resource(*resources, &block)
options = resources.extract_options!
options = (@scope[:options] || {}).merge(options)
+ options[:shallow] = true if @scope[:shallow] && !options.has_key?(:shallow)
if apply_common_behavior_for(:resource, resources, options, &block)
return self
end
- resource = SingletonResource.new(resources.pop, options)
-
- scope(:path => resource.path, :controller => resource.controller) do
- with_scope_level(:resource, resource) do
+ resource_scope(SingletonResource.new(resources.pop, options)) do
+ yield if block_given?
- yield if block_given?
+ collection_scope do
+ post :create if parent_resource.actions.include?(:create)
+ get :new if parent_resource.actions.include?(:new)
+ end
- with_scope_level(:member) do
- scope(resource.options) do
- get :show if resource.actions.include?(:show)
- post :create if resource.actions.include?(:create)
- put :update if resource.actions.include?(:update)
- delete :destroy if resource.actions.include?(:destroy)
- get :new, :as => resource.name if resource.actions.include?(:new)
- get :edit, :as => resource.name if resource.actions.include?(:edit)
- end
- end
+ member_scope do
+ get :show if parent_resource.actions.include?(:show)
+ put :update if parent_resource.actions.include?(:update)
+ delete :destroy if parent_resource.actions.include?(:destroy)
+ get :edit if parent_resource.actions.include?(:edit)
end
end
@@ -596,35 +593,26 @@ module ActionDispatch
def resources(*resources, &block)
options = resources.extract_options!
options = (@scope[:options] || {}).merge(options)
+ options[:shallow] = true if @scope[:shallow] && !options.has_key?(:shallow)
if apply_common_behavior_for(:resources, resources, options, &block)
return self
end
- resource = Resource.new(resources.pop, options)
-
- scope(:path => resource.path, :controller => resource.controller) do
- with_scope_level(:resources, resource) do
- yield if block_given?
+ resource_scope(Resource.new(resources.pop, options)) do
+ yield if block_given?
- with_scope_level(:collection) do
- scope(resource.collection_options) do
- get :index if resource.actions.include?(:index)
- post :create if resource.actions.include?(:create)
- get :new, :as => resource.singular if resource.actions.include?(:new)
- end
- end
+ collection_scope do
+ get :index if parent_resource.actions.include?(:index)
+ post :create if parent_resource.actions.include?(:create)
+ get :new if parent_resource.actions.include?(:new)
+ end
- with_scope_level(:member) do
- scope(':id') do
- scope(resource.options) do
- get :show if resource.actions.include?(:show)
- put :update if resource.actions.include?(:update)
- delete :destroy if resource.actions.include?(:destroy)
- get :edit, :as => resource.singular if resource.actions.include?(:edit)
- end
- end
- end
+ member_scope do
+ get :show if parent_resource.actions.include?(:show)
+ put :update if parent_resource.actions.include?(:update)
+ delete :destroy if parent_resource.actions.include?(:destroy)
+ get :edit if parent_resource.actions.include?(:edit)
end
end
@@ -636,10 +624,8 @@ module ActionDispatch
raise ArgumentError, "can't use collection outside resources scope"
end
- with_scope_level(:collection) do
- scope(:name_prefix => parent_resource.collection_name, :as => "") do
- yield
- end
+ collection_scope do
+ yield
end
end
@@ -648,10 +634,8 @@ module ActionDispatch
raise ArgumentError, "can't use member outside resource(s) scope"
end
- with_scope_level(:member) do
- scope(parent_resource.member_prefix, :name_prefix => parent_resource.member_name, :as => "") do
- yield
- end
+ member_scope do
+ yield
end
end
@@ -659,9 +643,9 @@ module ActionDispatch
unless resource_scope?
raise ArgumentError, "can't use new outside resource(s) scope"
end
-
+
with_scope_level(:new) do
- scope(new_scope_prefix, :name_prefix => parent_resource.member_name, :as => "") do
+ scope(*parent_resource.new_scope) do
yield
end
end
@@ -673,8 +657,18 @@ module ActionDispatch
end
with_scope_level(:nested) do
- scope(parent_resource.nested_prefix, parent_resource.nested_options) do
- yield
+ if parent_resource.shallow?
+ with_exclusive_scope do
+ if @scope[:module].blank?
+ scope(*parent_resource.nested_scope) { yield }
+ else
+ scope(@scope[:module], :name_prefix => @scope[:module].tr('/', '_')) do
+ scope(*parent_resource.nested_scope) { yield }
+ end
+ end
+ end
+ else
+ scope(*parent_resource.nested_scope) { yield }
end
end
end
@@ -687,63 +681,69 @@ module ActionDispatch
end
end
+ def shallow
+ scope(:shallow => true) do
+ yield
+ end
+ end
+
def match(*args)
options = args.extract_options!
options[:anchor] = true unless options.key?(:anchor)
if args.length > 1
- args.each { |path| match(path, options) }
+ args.each { |path| match(path, options.dup) }
return self
end
- path_names = options.delete(:path_names)
+ if [:collection, :member, :new].include?(options[:on])
+ args.push(options)
- if args.first.is_a?(Symbol)
- action = args.first
- if CRUD_ACTIONS.include?(action)
- begin
- old_path = @scope[:path]
- @scope[:path] = "#{@scope[:path]}(.:format)"
- return match(options.reverse_merge(
- :to => action,
- :as => parent_resource.name_for_action(action)
- ))
- ensure
- @scope[:path] = old_path
- end
- else
- with_exclusive_name_prefix(action_name_prefix(action, options)) do
- return match("#{action_path(action, path_names)}(.:format)", options.reverse_merge(:to => action))
- end
+ case options.delete(:on)
+ when :collection
+ return collection { match(*args) }
+ when :member
+ return member { match(*args) }
+ when :new
+ return new { match(*args) }
end
end
- args.push(options)
-
- case options.delete(:on)
- when :collection
- return collection { match(*args) }
- when :member
+ if @scope[:scope_level] == :resource
+ args.push(options)
return member { match(*args) }
- when :new
- return new { match(*args) }
end
- if @scope[:scope_level] == :resource
- return member { match(*args) }
+ path_names = options.delete(:path_names)
+
+ if args.first.is_a?(Symbol)
+ path = path_for_action(args.first, path_names)
+ options = options_for_action(args.first, options)
+
+ with_exclusive_scope do
+ return match(path, options)
+ end
end
if resource_scope?
raise ArgumentError, "can't define route directly in resource(s) scope"
end
+ args.push(options)
super
end
def root(options={})
- options[:on] ||= :collection if @scope[:scope_level] == :resources
- super(options)
+ if @scope[:scope_level] == :resources
+ with_scope_level(:collection) do
+ scope(parent_resource.path, :name_prefix => parent_resource.collection_name) do
+ super(options)
+ end
+ end
+ else
+ super(options)
+ end
end
protected
@@ -752,15 +752,6 @@ module ActionDispatch
end
private
- def action_path(name, path_names = nil)
- path_names ||= @scope[:path_names]
- path_names[name.to_sym] || name.to_s
- end
-
- def action_name_prefix(action, options = {})
- (options[:on] == :new || @scope[:scope_level] == :new) ? "#{action}_new" : action
- end
-
def apply_common_behavior_for(method, resources, options, &block)
if resources.length > 1
resources.each { |r| send(method, r, options, &block) }
@@ -784,27 +775,18 @@ module ActionDispatch
false
end
- def new_scope_prefix
- @scope[:path_names][:new] || 'new'
- end
-
def resource_scope?
[:resource, :resources].include?(@scope[:scope_level])
end
- def with_exclusive_name_prefix(prefix)
+ def with_exclusive_scope
begin
- old_name_prefix = @scope[:name_prefix]
-
- if !old_name_prefix.blank?
- @scope[:name_prefix] = "#{prefix}_#{@scope[:name_prefix]}"
- else
- @scope[:name_prefix] = prefix.to_s
- end
+ old_name_prefix, old_path = @scope[:name_prefix], @scope[:path]
+ @scope[:name_prefix], @scope[:path] = nil, nil
yield
ensure
- @scope[:name_prefix] = old_name_prefix
+ @scope[:name_prefix], @scope[:path] = old_name_prefix, old_path
end
end
@@ -816,6 +798,116 @@ module ActionDispatch
@scope[:scope_level] = old
@scope[:scope_level_resource] = old_resource
end
+
+ def resource_scope(resource)
+ with_scope_level(resource.is_a?(SingletonResource) ? :resource : :resources, resource) do
+ scope(*parent_resource.resource_scope) do
+ yield
+ end
+ end
+ end
+
+ def collection_scope
+ with_scope_level(:collection) do
+ scope(*parent_resource.collection_scope) do
+ yield
+ end
+ end
+ end
+
+ def member_scope
+ with_scope_level(:member) do
+ scope(*parent_resource.member_scope) do
+ yield
+ end
+ end
+ end
+
+ def path_for_action(action, path_names)
+ case action
+ when :index, :create
+ "#{@scope[:path]}(.:format)"
+ when :show, :update, :destroy
+ if parent_resource.shallow?
+ "#{@scope[:module]}/#{parent_resource.path}/:id(.:format)"
+ else
+ "#{@scope[:path]}(.:format)"
+ end
+ when :new
+ "#{@scope[:path]}/#{action_path(:new)}(.:format)"
+ when :edit
+ if parent_resource.shallow?
+ "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(:edit)}(.:format)"
+ else
+ "#{@scope[:path]}/#{action_path(:edit)}(.:format)"
+ end
+ else
+ case @scope[:scope_level]
+ when :collection
+ "#{@scope[:path]}/#{action_path(action)}(.:format)"
+ when :new
+ "#{@scope[:path]}/#{action_path(:new)}/#{action_path(action)}(.:format)"
+ else
+ if parent_resource.shallow?
+ "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)"
+ else
+ "#{@scope[:path]}/#{action_path(action)}(.:format)"
+ end
+ end
+ end
+ end
+
+ def action_path(name, path_names = nil)
+ path_names ||= @scope[:path_names]
+ path_names[name.to_sym] || name.to_s
+ end
+
+ def options_for_action(action, options)
+ options.reverse_merge(
+ :to => action,
+ :as => name_for_action(action)
+ )
+ end
+
+ def name_for_action(action)
+ name_prefix = @scope[:name_prefix].blank? ? "" : "#{@scope[:name_prefix]}_"
+ shallow_prefix = @scope[:module].blank? ? "" : "#{@scope[:module].tr('/', '_')}_"
+
+ case action
+ when :index
+ "#{name_prefix}#{parent_resource.collection_name}"
+ when :show
+ if parent_resource.shallow?
+ "#{shallow_prefix}#{parent_resource.member_name}"
+ else
+ "#{name_prefix}#{parent_resource.member_name}"
+ end
+ when :edit
+ if parent_resource.shallow?
+ "edit_#{shallow_prefix}#{parent_resource.member_name}"
+ else
+ "edit_#{name_prefix}#{parent_resource.member_name}"
+ end
+ when :new
+ "new_#{name_prefix}#{parent_resource.member_name}"
+ when :update, :create, :destroy
+ nil
+ else
+ case @scope[:scope_level]
+ when :collection
+ "#{action}_#{name_prefix}#{parent_resource.collection_name}"
+ when :new
+ "#{action}_new_#{name_prefix}#{parent_resource.member_name}"
+ else
+ if parent_resource.shallow?
+ "#{action}_#{shallow_prefix}#{parent_resource.member_name}"
+ else
+ "#{action}_#{name_prefix}#{parent_resource.member_name}"
+ end
+ end
+ end
+ end
+
end
include Base
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index e13960e0dc..e294703e72 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -142,6 +142,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resources :comments, :except => :destroy
end
+ shallow do
+ namespace :api do
+ resources :teams do
+ resources :players
+ resource :captain
+ end
+ end
+ end
+
+ resources :threads, :shallow => true do
+ resource :owner
+ resources :messages do
+ resources :comments do
+ member do
+ post :preview
+ end
+ end
+ end
+ end
+
resources :sheep
resources :clients do
@@ -1132,6 +1152,111 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_shallow_nested_resources
+ with_test_routes do
+
+ get '/api/teams'
+ assert_equal 'api/teams#index', @response.body
+ assert_equal '/api/teams', api_teams_path
+
+ get '/api/teams/new'
+ assert_equal 'api/teams#new', @response.body
+ assert_equal '/api/teams/new', new_api_team_path
+
+ get '/api/teams/1'
+ assert_equal 'api/teams#show', @response.body
+ assert_equal '/api/teams/1', api_team_path(:id => '1')
+
+ get '/api/teams/1/edit'
+ assert_equal 'api/teams#edit', @response.body
+ assert_equal '/api/teams/1/edit', edit_api_team_path(:id => '1')
+
+ get '/api/teams/1/players'
+ assert_equal 'api/players#index', @response.body
+ assert_equal '/api/teams/1/players', api_team_players_path(:team_id => '1')
+
+ get '/api/teams/1/players/new'
+ assert_equal 'api/players#new', @response.body
+ assert_equal '/api/teams/1/players/new', new_api_team_player_path(:team_id => '1')
+
+ get '/api/players/2'
+ assert_equal 'api/players#show', @response.body
+ assert_equal '/api/players/2', api_player_path(:id => '2')
+
+ get '/api/players/2/edit'
+ assert_equal 'api/players#edit', @response.body
+ assert_equal '/api/players/2/edit', edit_api_player_path(:id => '2')
+
+ get '/api/teams/1/captain'
+ assert_equal 'api/captains#show', @response.body
+ assert_equal '/api/teams/1/captain', api_team_captain_path(:team_id => '1')
+
+ get '/api/teams/1/captain/new'
+ assert_equal 'api/captains#new', @response.body
+ assert_equal '/api/teams/1/captain/new', new_api_team_captain_path(:team_id => '1')
+
+ get '/api/teams/1/captain/edit'
+ assert_equal 'api/captains#edit', @response.body
+ assert_equal '/api/teams/1/captain/edit', edit_api_team_captain_path(:team_id => '1')
+
+ get '/threads'
+ assert_equal 'threads#index', @response.body
+ assert_equal '/threads', threads_path
+
+ get '/threads/new'
+ assert_equal 'threads#new', @response.body
+ assert_equal '/threads/new', new_thread_path
+
+ get '/threads/1'
+ assert_equal 'threads#show', @response.body
+ assert_equal '/threads/1', thread_path(:id => '1')
+
+ get '/threads/1/edit'
+ assert_equal 'threads#edit', @response.body
+ assert_equal '/threads/1/edit', edit_thread_path(:id => '1')
+
+ get '/threads/1/owner'
+ assert_equal 'owners#show', @response.body
+ assert_equal '/threads/1/owner', thread_owner_path(:thread_id => '1')
+
+ get '/threads/1/messages'
+ assert_equal 'messages#index', @response.body
+ assert_equal '/threads/1/messages', thread_messages_path(:thread_id => '1')
+
+ get '/threads/1/messages/new'
+ assert_equal 'messages#new', @response.body
+ assert_equal '/threads/1/messages/new', new_thread_message_path(:thread_id => '1')
+
+ get '/messages/2'
+ assert_equal 'messages#show', @response.body
+ assert_equal '/messages/2', message_path(:id => '2')
+
+ get '/messages/2/edit'
+ assert_equal 'messages#edit', @response.body
+ assert_equal '/messages/2/edit', edit_message_path(:id => '2')
+
+ get '/messages/2/comments'
+ assert_equal 'comments#index', @response.body
+ assert_equal '/messages/2/comments', message_comments_path(:message_id => '2')
+
+ get '/messages/2/comments/new'
+ assert_equal 'comments#new', @response.body
+ assert_equal '/messages/2/comments/new', new_message_comment_path(:message_id => '2')
+
+ get '/comments/3'
+ assert_equal 'comments#show', @response.body
+ assert_equal '/comments/3', comment_path(:id => '3')
+
+ get '/comments/3/edit'
+ assert_equal 'comments#edit', @response.body
+ assert_equal '/comments/3/edit', edit_comment_path(:id => '3')
+
+ post '/comments/3/preview'
+ assert_equal 'comments#preview', @response.body
+ assert_equal '/comments/3/preview', preview_comment_path(:id => '3')
+ end
+ end
+
private
def with_test_routes
yield
--
cgit v1.2.3
From 84d387bc0f3f3f6641b08d0ce40e924f09105c19 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino
Date: Thu, 17 Jun 2010 12:56:15 -0300
Subject: Make text_helpers methods which return valid html to return it as
safe and sanitize the input always unless :sanitize => false is set
[#4825 state:committed]
Signed-off-by: David Heinemeier Hansson
---
actionpack/lib/action_view/helpers/text_helper.rb | 20 +++++--
actionpack/test/template/text_helper_test.rb | 68 ++++++++++-------------
2 files changed, 42 insertions(+), 46 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 654f3c89f3..c7f96597b9 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -112,13 +112,13 @@ module ActionView
end
options.reverse_merge!(:highlighter => '\1')
- text = h(text) unless text.html_safe? || options[:safe]
+ text = sanitize(text) unless options[:sanitize] == false
if text.blank? || phrases.blank?
text
else
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
text.gsub(/(#{match})(?!(?:[^<]*?)(?:["'])[^<>]*>)/i, options[:highlighter])
- end
+ end.html_safe
end
# Extracts an excerpt from +text+ that matches the first instance of +phrase+.
@@ -248,9 +248,9 @@ module ActionView
# simple_format("Look ma! A class!", :class => 'description')
# # => "
Look ma! A class!
"
def simple_format(text, html_options={}, options={})
- text = '' if text.nil?
+ text = ''.html_safe if text.nil?
start_tag = tag('p', html_options, true)
- text = h(text) unless text.html_safe? || options[:safe]
+ text = sanitize(text) unless options[:sanitize] == false
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
text.gsub!(/\n\n+/, "
\n\n#{start_tag}") # 2+ newline -> paragraph
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1 ') # 1 newline -> br
@@ -494,7 +494,11 @@ module ActionView
link_text = block_given?? yield(href) : href
href = 'http://' + href unless scheme
- content_tag(:a, link_text, link_attributes.merge('href' => href), !(options[:safe] || text.html_safe?)) + punctuation.reverse.join('')
+ unless options[:sanitize] == false
+ link_text = sanitize(link_text)
+ href = sanitize(href)
+ end
+ content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
end
end.html_safe
end
@@ -509,7 +513,11 @@ module ActionView
text.html_safe
else
display_text = (block_given?) ? yield(text) : text
- display_text = h(display_text) unless options[:safe]
+
+ unless options[:sanitize] == false
+ text = sanitize(text)
+ display_text = sanitize(display_text) unless text == display_text
+ end
mail_to text, display_text, html_options
end
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index 82c81ddf05..d173c5be0a 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -19,6 +19,10 @@ class TextHelperTest < ActionView::TestCase
assert_equal 'foobar', output_buffer
end
+ def test_simple_format_should_be_html_safe
+ assert simple_format(" test with html tags ").html_safe?
+ end
+
def test_simple_format
assert_equal "", simple_format(nil)
@@ -36,26 +40,18 @@ class TextHelperTest < ActionView::TestCase
assert_equal %Q(
para 1
\n\n
para 2
), simple_format("para 1\n\npara 2", :class => 'test')
end
- def test_simple_format_should_be_html_safe
- assert simple_format(" test with html tags ").html_safe?
+ def test_simple_format_should_sanitize_input_when_sanitize_option_is_not_false
+ assert_equal "
test with unsafe string
", simple_format(" test with unsafe string ")
end
- def test_simple_format_should_escape_unsafe_input
- assert_equal "
<b> test with unsafe string </b><script>code!</script>
", simple_format(" test with unsafe string ")
- end
-
- def test_simple_format_should_not_escape_input_if_safe_option
- assert_equal "
test with unsafe string
", simple_format(" test with unsafe string ", {}, :safe => true)
- end
-
- def test_simple_format_should_not_escape_safe_input
- assert_equal "
test with safe string
", simple_format(" test with safe string ".html_safe)
+ def test_simple_format_should_not_sanitize_input_when_sanitize_option_is_false
+ assert_equal "
test with unsafe string
", simple_format(" test with unsafe string ", {}, :sanitize => false)
end
def test_truncate_should_not_be_html_safe
assert !truncate("Hello World!", :length => 12).html_safe?
end
-
+
def test_truncate
assert_equal "Hello World!", truncate("Hello World!", :length => 12)
assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12)
@@ -128,24 +124,17 @@ class TextHelperTest < ActionView::TestCase
assert_equal ' ', highlight(' ', 'blank text is returned verbatim')
end
- def test_highlight_should_escape_unsafe_input
+ def test_highlight_should_sanitize_input
assert_equal(
- "This is a beautiful morning<script>code!</script>",
+ "This is a beautiful morning",
highlight("This is a beautiful morning", "beautiful")
)
end
- def test_highlight_should_not_escape_input_if_safe_option
+ def test_highlight_should_not_sanitize_if_sanitize_option_if_false
assert_equal(
"This is a beautiful morning",
- highlight("This is a beautiful morning", "beautiful", :safe => true)
- )
- end
-
- def test_highlight_should_not_escape_safe_input
- assert_equal(
- "This is a beautiful morning",
- highlight("This is a beautiful morning".html_safe, "beautiful")
+ highlight("This is a beautiful morning", "beautiful", :sanitize => false)
)
end
@@ -179,23 +168,23 @@ class TextHelperTest < ActionView::TestCase
def test_highlight_with_html
assert_equal(
- "<p>This is a beautiful morning, but also a beautiful day</p>",
+ "
This is a beautiful morning, but also a beautiful day
",
highlight("
This is a beautiful morning, but also a beautiful day
", "beautiful")
)
assert_equal(
- "<p>This is a <em>beautiful</em> morning, but also a beautiful day</p>",
+ "
This is a beautiful morning, but also a beautiful day
",
highlight("
This is a beautiful morning, but also a beautiful day
", "beautiful")
)
assert_equal(
- "<p>This is a <em class="error">beautiful</em> morning, but also a beautiful <span class="last">day</span></p>",
+ "
This is a beautiful morning, but also a beautifulday
",
highlight("
This is a beautiful morning, but also a beautiful day
", "beautiful")
)
assert_equal(
- "<p class="beautiful">This is a beautiful morning, but also a beautiful day</p>",
+ "
This is a beautiful morning, but also a beautiful day
",
highlight("
This is a beautiful morning, but also a beautiful day
", "beautiful")
)
assert_equal(
- "<p>This is a beautiful <a href="http://example.com/beautiful#top?what=beautiful%20morning&when=now+then">morning</a>, but also a beautiful day</p>",
+ "
This is a beautifulmorning, but also a beautiful day
",
highlight("
This is a beautiful morning, but also a beautiful day
", "beautiful")
)
end
@@ -317,9 +306,13 @@ class TextHelperTest < ActionView::TestCase
end
end
- def generate_result(link_text, href = nil)
+ def generate_result(link_text, href = nil, escape = false)
href ||= link_text
- %{#{CGI::escapeHTML link_text}}
+ if escape
+ %{#{CGI::escapeHTML link_text}}
+ else
+ %{#{link_text}}
+ end
end
def test_auto_link_should_be_html_safe
@@ -424,19 +417,14 @@ class TextHelperTest < ActionView::TestCase
assert_equal %(
#{link10_result} Link
), auto_link("
#{link10_raw} Link
")
end
- def test_auto_link_should_sanitize_unsafe_input
- link_raw = %{http://www.rubyonrails.com?id=1&num=2}
- assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw)
- end
-
- def test_auto_link_should_sanitize_unsafe_input
+ def test_auto_link_should_sanitize_input_when_sanitize_option_is_not_false
link_raw = %{http://www.rubyonrails.com?id=1&num=2}
- assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw, :safe => true)
+ assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw)
end
- def test_auto_link_should_not_sanitize_safe_input
+ def test_auto_link_should_not_sanitize_input_when_sanitize_option_is_false
link_raw = %{http://www.rubyonrails.com?id=1&num=2}
- assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw.html_safe)
+ assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw, :sanitize => false)
end
def test_auto_link_other_protocols
--
cgit v1.2.3
From a55d83292f9dbc34368e3cb91d99eb5b4aa4fa78 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 17 Jun 2010 22:18:09 -0700
Subject: Credit for the heavy lifting!
---
actionpack/CHANGELOG | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'actionpack')
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index cee79c6c11..a00f63dcd4 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,6 +1,6 @@
*Rails 3.0.0 [Release Candidate] (unreleased)*
-* Add shallow routes back to the new router [Diego Carrion]
+* Add shallow routes back to the new router [Diego Carrion, Andrew White]
resources :posts do
shallow do
--
cgit v1.2.3
From 9d3eeb905341aaad942ceb0e47bd04cced34d031 Mon Sep 17 00:00:00 2001
From: Josh Kalderimis
Date: Fri, 18 Jun 2010 18:25:07 +0200
Subject: fix for :shallow in router not generating helpers for create, update,
and destroy actions when :only or :except are used
[#4900 state:committed]
Signed-off-by: Jeremy Kemper
---
actionpack/lib/action_dispatch/routing/mapper.rb | 7 ++---
actionpack/test/dispatch/routing_test.rb | 40 +++++++++++++++++++++++-
2 files changed, 42 insertions(+), 5 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 46304b0336..95e56566a3 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -536,6 +536,7 @@ module ActionDispatch
def member_name
name
end
+ alias_method :collection_name, :member_name
def nested_path
path
@@ -874,9 +875,9 @@ module ActionDispatch
shallow_prefix = @scope[:module].blank? ? "" : "#{@scope[:module].tr('/', '_')}_"
case action
- when :index
+ when :index, :create
"#{name_prefix}#{parent_resource.collection_name}"
- when :show
+ when :show, :update, :destroy
if parent_resource.shallow?
"#{shallow_prefix}#{parent_resource.member_name}"
else
@@ -890,8 +891,6 @@ module ActionDispatch
end
when :new
"new_#{name_prefix}#{parent_resource.member_name}"
- when :update, :create, :destroy
- nil
else
case @scope[:scope_level]
when :collection
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index e294703e72..0b3bbcc86b 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -142,6 +142,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resources :comments, :except => :destroy
end
+ resource :past, :only => :destroy
+ resource :present, :only => :update
+ resource :future, :only => :create
+ resources :relationships, :only => [:create, :destroy]
+ resources :friendships, :only => [:update]
+
shallow do
namespace :api do
resources :teams do
@@ -729,6 +735,38 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_resource_routes_only_create_update_destroy
+ with_test_routes do
+ delete '/past'
+ assert_equal 'pasts#destroy', @response.body
+ assert_equal '/past', past_path
+
+ put '/present'
+ assert_equal 'presents#update', @response.body
+ assert_equal '/present', present_path
+
+ post '/future'
+ assert_equal 'futures#create', @response.body
+ assert_equal '/future', future_path
+ end
+ end
+
+ def test_resources_routes_only_create_update_destroy
+ with_test_routes do
+ post '/relationships'
+ assert_equal 'relationships#create', @response.body
+ assert_equal '/relationships', relationships_path
+
+ delete '/relationships/1'
+ assert_equal 'relationships#destroy', @response.body
+ assert_equal '/relationships/1', relationship_path(1)
+
+ put '/friendships/1'
+ assert_equal 'friendships#update', @response.body
+ assert_equal '/friendships/1', friendship_path(1)
+ end
+ end
+
def test_resource_with_slugs_in_ids
with_test_routes do
get '/posts/rails-rocks'
@@ -843,7 +881,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal '/account/admin/subscription', account_admin_subscription_path
end
end
-
+
def test_namespace_nested_in_resources
with_test_routes do
get '/clients/1/google/account'
--
cgit v1.2.3
From a186431414de8a0f0db9f60254f421a3536cee12 Mon Sep 17 00:00:00 2001
From: David Genord II
Date: Fri, 18 Jun 2010 15:40:20 -0400
Subject: form_for without :html and with :remote should not error
[#4902 state:committed]
Signed-off-by: Jeremy Kemper
---
actionpack/lib/action_view/helpers/form_helper.rb | 2 +-
actionpack/test/template/form_helper_test.rb | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index b3db3151d3..a49daab98b 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -302,7 +302,7 @@ module ActionView
args.unshift object
end
- options[:html][:remote] = true if options.delete(:remote)
+ (options[:html] ||= {})[:remote] = true if options.delete(:remote)
output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
output << fields_for(object_name, *(args << options), &proc)
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 2f3869994c..8de1e782c0 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -644,6 +644,26 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_form_for_with_remote_without_html
+ assert_deprecated do
+ form_for(:post, @post, :remote => true) do |f|
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
+ end
+ end
+
+ expected =
+ ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
def test_form_for_without_object
form_for(:post, :html => { :id => 'create-post' }) do |f|
concat f.text_field(:title)
--
cgit v1.2.3
From bf59717b43fc7c186f9acebac27ba9ac7d59dd93 Mon Sep 17 00:00:00 2001
From: Andrew White
Date: Sat, 19 Jun 2010 07:23:57 +0100
Subject: Custom resource routes should be scoped
[#3765]
Signed-off-by: Jeremy Kemper
---
actionpack/lib/action_dispatch/routing/mapper.rb | 43 ++++++++++++++++++----
actionpack/test/dispatch/routing_test.rb | 47 ++++++++++++++++++++++++
2 files changed, 83 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 95e56566a3..0018b6485b 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -647,7 +647,9 @@ module ActionDispatch
with_scope_level(:new) do
scope(*parent_resource.new_scope) do
- yield
+ scope(action_path(:new)) do
+ yield
+ end
end
end
end
@@ -723,7 +725,17 @@ module ActionDispatch
options = options_for_action(args.first, options)
with_exclusive_scope do
- return match(path, options)
+ return super(path, options)
+ end
+ elsif resource_method_scope?
+ path = path_for_custom_action
+ options[:as] = name_for_action(options[:as]) if options[:as]
+ args.push(options)
+
+ with_exclusive_scope do
+ scope(path) do
+ return super
+ end
end
end
@@ -737,7 +749,7 @@ module ActionDispatch
def root(options={})
if @scope[:scope_level] == :resources
- with_scope_level(:collection) do
+ with_scope_level(:nested) do
scope(parent_resource.path, :name_prefix => parent_resource.collection_name) do
super(options)
end
@@ -780,12 +792,18 @@ module ActionDispatch
[:resource, :resources].include?(@scope[:scope_level])
end
+ def resource_method_scope?
+ [:collection, :member, :new].include?(@scope[:scope_level])
+ end
+
def with_exclusive_scope
begin
old_name_prefix, old_path = @scope[:name_prefix], @scope[:path]
@scope[:name_prefix], @scope[:path] = nil, nil
- yield
+ with_scope_level(:exclusive) do
+ yield
+ end
ensure
@scope[:name_prefix], @scope[:path] = old_name_prefix, old_path
end
@@ -844,10 +862,8 @@ module ActionDispatch
end
else
case @scope[:scope_level]
- when :collection
+ when :collection, :new
"#{@scope[:path]}/#{action_path(action)}(.:format)"
- when :new
- "#{@scope[:path]}/#{action_path(:new)}/#{action_path(action)}(.:format)"
else
if parent_resource.shallow?
"#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)"
@@ -858,6 +874,19 @@ module ActionDispatch
end
end
+ def path_for_custom_action
+ case @scope[:scope_level]
+ when :collection, :new
+ @scope[:path]
+ else
+ if parent_resource.shallow?
+ "#{@scope[:module]}/#{parent_resource.path}/:id"
+ else
+ @scope[:path]
+ end
+ end
+ end
+
def action_path(name, path_names = nil)
path_names ||= @scope[:path_names]
path_names[name.to_sym] || name.to_s
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 0b3bbcc86b..899990c69d 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -180,6 +180,33 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ resources :customers do
+ get "recent" => "customers#recent", :as => :recent, :on => :collection
+ get "profile" => "customers#profile", :as => :profile, :on => :member
+ post "preview" => "customers#preview", :as => :preview, :on => :new
+ resource :avatar do
+ get "thumbnail(.:format)" => "avatars#thumbnail", :as => :thumbnail, :on => :member
+ end
+ resources :invoices do
+ get "outstanding" => "invoices#outstanding", :as => :outstanding, :on => :collection
+ get "overdue", :to => :overdue, :on => :collection
+ get "print" => "invoices#print", :as => :print, :on => :member
+ post "preview" => "invoices#preview", :as => :preview, :on => :new
+ end
+ resources :notes, :shallow => true do
+ get "preview" => "notes#preview", :as => :preview, :on => :new
+ get "print" => "notes#print", :as => :print, :on => :member
+ end
+ end
+
+ namespace :api do
+ resources :customers do
+ get "recent" => "customers#recent", :as => :recent, :on => :collection
+ get "profile" => "customers#profile", :as => :profile, :on => :member
+ post "preview" => "customers#preview", :as => :preview, :on => :new
+ end
+ end
+
match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
match 'people/:id/update', :to => 'people#update', :as => :update_person
@@ -1295,6 +1322,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_custom_resource_routes_are_scoped
+ with_test_routes do
+ assert_equal '/customers/recent', recent_customers_path
+ assert_equal '/customers/1/profile', profile_customer_path(:id => '1')
+ assert_equal '/customers/new/preview', preview_new_customer_path
+ assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg)
+ assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1')
+ assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2')
+ assert_equal '/customers/1/invoices/new/preview', preview_new_customer_invoice_path(:customer_id => '1')
+ assert_equal '/customers/1/notes/new/preview', preview_new_customer_note_path(:customer_id => '1')
+ assert_equal '/notes/1/print', print_note_path(:id => '1')
+ assert_equal '/api/customers/recent', recent_api_customers_path
+ assert_equal '/api/customers/1/profile', profile_api_customer_path(:id => '1')
+ assert_equal '/api/customers/new/preview', preview_new_api_customer_path
+
+ get '/customers/1/invoices/overdue'
+ assert_equal 'invoices#overdue', @response.body
+ end
+ end
+
private
def with_test_routes
yield
--
cgit v1.2.3
From 033e0a041f10ef4d4aa8ebb576560df20b971026 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?=
Date: Sat, 19 Jun 2010 17:15:21 +0200
Subject: ActiveRecord and ActionPack now use the new descendants
implementation.
---
actionpack/lib/abstract_controller/base.rb | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index e1027840ef..8a8337858b 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -1,4 +1,5 @@
require 'active_support/configurable'
+require 'active_support/descendants_tracker'
require 'active_support/core_ext/module/anonymous'
module AbstractController
@@ -10,6 +11,7 @@ module AbstractController
attr_internal :action_name
include ActiveSupport::Configurable
+ extend ActiveSupport::DescendantsTracker
class << self
attr_reader :abstract
@@ -21,17 +23,6 @@ module AbstractController
@abstract = true
end
- def inherited(klass)
- ::AbstractController::Base.descendants << klass.to_s
- super
- end
-
- # A list of all descendents of AbstractController::Base. This is
- # useful for initializers which need to add behavior to all controllers.
- def descendants
- @descendants ||= []
- end
-
# 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
--
cgit v1.2.3
From f368b21cb6e45268359c0f0b8beda175e3b40eae Mon Sep 17 00:00:00 2001
From: wycats
Date: Sat, 19 Jun 2010 08:19:00 -0700
Subject: Remove a relic of #request being in RackDelegation
---
actionpack/lib/action_controller/metal.rb | 11 +++++++++--
actionpack/lib/action_controller/metal/rack_delegation.rb | 4 ----
2 files changed, 9 insertions(+), 6 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 775a5002e2..159d1f0748 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -52,8 +52,7 @@ module ActionController
class Metal < AbstractController::Base
abstract!
- # :api: public
- attr_internal :params, :env
+ attr_internal :env
# Returns the last part of the controller's name, underscored, without the ending
# "Controller". For instance, MyApp::MyPostsController would return "my_posts" for
@@ -85,6 +84,14 @@ module ActionController
super
end
+ def params
+ @_params ||= request.parameters
+ end
+
+ def params=(val)
+ @_params = val
+ end
+
# Basic implementations for content_type=, location=, and headers are
# provided to reduce the dependency on the RackDelegation module
# in Renderer and Redirector.
diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb
index 508ea6e2b7..544b4989c7 100644
--- a/actionpack/lib/action_controller/metal/rack_delegation.rb
+++ b/actionpack/lib/action_controller/metal/rack_delegation.rb
@@ -14,10 +14,6 @@ module ActionController
super(action, request)
end
- def params
- @_params ||= @_request.parameters
- end
-
def response_body=(body)
response.body = body if response
super
--
cgit v1.2.3
From 728b9eccad99d22028577e8b06433e8344b15d01 Mon Sep 17 00:00:00 2001
From: Wincent Colaiuta
Date: Thu, 17 Jun 2010 09:17:31 +0200
Subject: option_groups_from_collection_for_select should return HTML-safe
string [#4879 state:resolved]
Signed-off-by: Xavier Noria
---
.../lib/action_view/helpers/form_options_helper.rb | 2 +-
.../test/template/form_options_helper_test.rb | 30 +++++++++-------------
2 files changed, 13 insertions(+), 19 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index fe71d2cdf7..e48580e0ad 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -398,7 +398,7 @@ module ActionView
options_for_select += "'
- end
+ end.html_safe
end
# Returns a string of tags, like options_for_select, but
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 19b73aa810..65b5f5ccc1 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -177,17 +177,16 @@ class FormOptionsHelperTest < ActionView::TestCase
end
def test_option_groups_from_collection_for_select
- @continents = [
- Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ),
- Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] )
- ]
-
assert_dom_equal(
"",
- option_groups_from_collection_for_select(@continents, "countries", "continent_name", "country_id", "country_name", "dk")
+ option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk")
)
end
+ def test_option_groups_from_collection_for_select_returns_html_safe_string
+ assert option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk").html_safe?
+ end
+
def test_grouped_options_for_select_with_array
assert_dom_equal(
"",
@@ -824,31 +823,21 @@ class FormOptionsHelperTest < ActionView::TestCase
end
def test_grouped_collection_select
- @continents = [
- Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ),
- Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] )
- ]
-
@post = Post.new
@post.origin = 'dk'
assert_dom_equal(
%Q{},
- grouped_collection_select("post", "origin", @continents, :countries, :continent_name, :country_id, :country_name)
+ grouped_collection_select("post", "origin", dummy_continents, :countries, :continent_name, :country_id, :country_name)
)
end
def test_grouped_collection_select_under_fields_for
- @continents = [
- Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ),
- Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] )
- ]
-
@post = Post.new
@post.origin = 'dk'
output_buffer = fields_for :post, @post do |f|
- concat f.grouped_collection_select("origin", @continents, :countries, :continent_name, :country_id, :country_name)
+ concat f.grouped_collection_select("origin", dummy_continents, :countries, :continent_name, :country_id, :country_name)
end
assert_dom_equal(
@@ -864,4 +853,9 @@ class FormOptionsHelperTest < ActionView::TestCase
Post.new("Babe went home", "Babe", "To a little house", "shh!"),
Post.new("Cabe went home", "Cabe", "To a little house", "shh!") ]
end
+
+ def dummy_continents
+ [ Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ),
+ Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) ]
+ end
end
--
cgit v1.2.3
From 312f43324159fbcd8749cd331ed7d6500a714a83 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?=
Date: Sat, 19 Jun 2010 17:51:29 +0200
Subject: Clear DescendantsTracker on each request.
---
actionpack/lib/action_dispatch/middleware/callbacks.rb | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb
index d07841218a..e4ae480bfb 100644
--- a/actionpack/lib/action_dispatch/middleware/callbacks.rb
+++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -8,7 +8,7 @@ module ActionDispatch
class Callbacks
include ActiveSupport::Callbacks
- define_callbacks :call, :terminator => "result == false", :rescuable => true
+ define_callbacks :call, :rescuable => true
define_callbacks :prepare, :scope => :name
# Add a preparation callback. Preparation callbacks are run before every
@@ -37,12 +37,12 @@ module ActionDispatch
def initialize(app, prepare_each_request = false)
@app, @prepare_each_request = app, prepare_each_request
- run_callbacks(:prepare)
+ _run_prepare_callbacks
end
def call(env)
- run_callbacks(:call) do
- run_callbacks(:prepare) if @prepare_each_request
+ _run_call_callbacks do
+ _run_prepare_callbacks if @prepare_each_request
@app.call(env)
end
end
--
cgit v1.2.3
From 65ce3d12971afd15de6ea22a2fc5af3ba1faf124 Mon Sep 17 00:00:00 2001
From: Andrew White
Date: Sat, 19 Jun 2010 20:52:55 +0100
Subject: Accept an object for :constraints option [#4904 state:resolved]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: José Valim
---
actionpack/lib/action_dispatch/routing/mapper.rb | 2 +-
actionpack/test/dispatch/routing_test.rb | 8 ++++++++
2 files changed, 9 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 0018b6485b..5d6147c48a 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -102,7 +102,7 @@ module ActionDispatch
end
def requirements
- @requirements ||= (@options[:constraints] || {}).tap do |requirements|
+ @requirements ||= (@options[:constraints].is_a?(Hash) ? @options[:constraints] : {}).tap do |requirements|
requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints]
@options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) }
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 899990c69d..c4cdc4b2a8 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -68,6 +68,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get 'admin/accounts' => "queenbee#accounts"
end
+ get 'admin/passwords' => "queenbee#passwords", :constraints => ::TestRoutingMapper::IpRestrictor
+
scope 'pt', :name_prefix => 'pt' do
resources :projects, :path_names => { :edit => 'editar', :new => 'novo' }, :path => 'projetos' do
post :preview, :on => :new
@@ -501,6 +503,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get '/admin/accounts', {}, {'REMOTE_ADDR' => '10.0.0.100'}
assert_equal 'pass', @response.headers['X-Cascade']
+
+ get '/admin/passwords', {}, {'REMOTE_ADDR' => '192.168.1.100'}
+ assert_equal 'queenbee#passwords', @response.body
+
+ get '/admin/passwords', {}, {'REMOTE_ADDR' => '10.0.0.100'}
+ assert_equal 'pass', @response.headers['X-Cascade']
end
end
--
cgit v1.2.3
From ed3f042e99949526f483d1f567e40031deea33d3 Mon Sep 17 00:00:00 2001
From: Andrew White
Date: Sat, 19 Jun 2010 22:35:54 +0100
Subject: Make polymorphic_url and scaffolding work with uncountable resources
[#3930 state:resolved]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: José Valim
---
.../lib/action_controller/polymorphic_routes.rb | 3 ++-
.../lib/action_controller/record_identifier.rb | 14 ++++++++++---
.../test/activerecord/polymorphic_routes_test.rb | 1 +
.../test/controller/record_identifier_test.rb | 23 ++++++++++++++++++++--
4 files changed, 35 insertions(+), 6 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb
index 7f2eb4306b..bee50a7a3b 100644
--- a/actionpack/lib/action_controller/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/polymorphic_routes.rb
@@ -11,7 +11,7 @@ module ActionController
# polymorphic_url([:admin, @article, @comment])
#
# results in:
- #
+ #
# admin_article_comment_url(@article, @comment)
#
# == Usage within the framework
@@ -166,6 +166,7 @@ module ActionController
route << RecordIdentifier.__send__("plural_class_name", record)
route = route.singularize if inflection == :singular
route << "_"
+ route << "index_" if RecordIdentifier.uncountable?(record) && inflection == :plural
end
action_prefix(options) + route + routing_type(options).to_s
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 907c369218..d20c3b64c5 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -1,7 +1,7 @@
require 'active_support/core_ext/module'
module ActionController
- # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
+ # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
# Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate
# the view actions to a higher logical level. Example:
#
@@ -28,7 +28,7 @@ module ActionController
# end
#
# As the example above shows, you can stop caring to a large extent what the actual id of the post is. You just know
- # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming
+ # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming
# convention and allows you to write less code if you follow it.
module RecordIdentifier
extend self
@@ -59,7 +59,7 @@ module ActionController
# If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
#
# dom_id(Post.find(45), :edit) # => "edit_post_45"
- def dom_id(record, prefix = nil)
+ def dom_id(record, prefix = nil)
if record_id = record_key_for_dom_id(record)
"#{dom_class(record, prefix)}#{JOIN}#{record_id}"
else
@@ -102,6 +102,14 @@ module ActionController
model_name_from_record_or_class(record_or_class).singular
end
+ # Identifies whether the class name of a record or class is uncountable. Examples:
+ #
+ # uncountable?(Sheep) # => true
+ # uncountable?(Post) => false
+ def uncountable?(record_or_class)
+ plural_class_name(record_or_class) == singular_class_name(record_or_class)
+ end
+
private
def model_name_from_record_or_class(record_or_class)
(record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb
index 9f5e8ec657..6e1e6cdd20 100644
--- a/actionpack/test/activerecord/polymorphic_routes_test.rb
+++ b/actionpack/test/activerecord/polymorphic_routes_test.rb
@@ -381,6 +381,7 @@ class PolymorphicRoutesTest < ActionController::TestCase
with_test_routes do
@series.save
assert_equal "http://example.com/series/#{@series.id}", polymorphic_url(@series)
+ assert_equal "http://example.com/series", polymorphic_url(Series.new)
end
end
diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb
index 813dedc80d..6a84475758 100644
--- a/actionpack/test/controller/record_identifier_test.rb
+++ b/actionpack/test/controller/record_identifier_test.rb
@@ -13,6 +13,19 @@ class Comment
end
end
+class Sheep
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
+ attr_reader :id
+ def to_key; id ? [id] : nil end
+ def save; @id = 1 end
+ def new_record?; @id.nil? end
+ def name
+ @id.nil? ? 'new sheep' : "sheep ##{@id}"
+ end
+end
+
class Comment::Nested < Comment; end
class Test::Unit::TestCase
@@ -20,7 +33,7 @@ class Test::Unit::TestCase
def comments_url
'http://www.example.com/comments'
end
-
+
def comment_url(comment)
"http://www.example.com/comments/#{comment.id}"
end
@@ -35,6 +48,7 @@ class RecordIdentifierTest < Test::Unit::TestCase
@record = @klass.new
@singular = 'comment'
@plural = 'comments'
+ @uncountable = Sheep
end
def test_dom_id_with_new_record
@@ -58,7 +72,7 @@ class RecordIdentifierTest < Test::Unit::TestCase
def test_dom_class
assert_equal @singular, dom_class(@record)
end
-
+
def test_dom_class_with_prefix
assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix)
end
@@ -79,6 +93,11 @@ class RecordIdentifierTest < Test::Unit::TestCase
assert_equal @plural, plural_class_name(@klass)
end
+ def test_uncountable
+ assert_equal true, uncountable?(@uncountable)
+ assert_equal false, uncountable?(@klass)
+ end
+
private
def method_missing(method, *args)
RecordIdentifier.send(method, *args)
--
cgit v1.2.3
From 1f84061c5c271647dc5f7f1311e365e134130e0f Mon Sep 17 00:00:00 2001
From: Andrew White
Date: Sat, 19 Jun 2010 12:53:09 +0100
Subject: Don't use module to work out shallow name prefix and path as it may
not accurately reflect the actual namespace [#4899 state:resolved]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: José Valim
---
actionpack/lib/action_dispatch/routing/mapper.rb | 26 ++++++++++++++++--------
actionpack/test/dispatch/routing_test.rb | 17 +++++++++++++++-
2 files changed, 33 insertions(+), 10 deletions(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 5d6147c48a..c31f681411 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -33,7 +33,7 @@ module ActionDispatch
end
class Mapping #:nodoc:
- IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow]
+ IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix]
def initialize(set, scope, args)
@set, @scope = set, scope
@@ -343,7 +343,7 @@ module ActionDispatch
def namespace(path)
path = path.to_s
- scope(:path => path, :name_prefix => path, :module => path) { yield }
+ scope(:path => path, :name_prefix => path, :module => path, :shallow_path => path, :shallow_prefix => path) { yield }
end
def constraints(constraints = {})
@@ -378,10 +378,18 @@ module ActionDispatch
Mapper.normalize_path("#{parent}/#{child}")
end
+ def merge_shallow_path_scope(parent, child)
+ Mapper.normalize_path("#{parent}/#{child}")
+ end
+
def merge_name_prefix_scope(parent, child)
parent ? "#{parent}_#{child}" : child
end
+ def merge_shallow_prefix_scope(parent, child)
+ parent ? "#{parent}_#{child}" : child
+ end
+
def merge_module_scope(parent, child)
parent ? "#{parent}/#{child}" : child
end
@@ -662,10 +670,10 @@ module ActionDispatch
with_scope_level(:nested) do
if parent_resource.shallow?
with_exclusive_scope do
- if @scope[:module].blank?
+ if @scope[:shallow_path].blank?
scope(*parent_resource.nested_scope) { yield }
else
- scope(@scope[:module], :name_prefix => @scope[:module].tr('/', '_')) do
+ scope(@scope[:shallow_path], :name_prefix => @scope[:shallow_prefix]) do
scope(*parent_resource.nested_scope) { yield }
end
end
@@ -848,7 +856,7 @@ module ActionDispatch
"#{@scope[:path]}(.:format)"
when :show, :update, :destroy
if parent_resource.shallow?
- "#{@scope[:module]}/#{parent_resource.path}/:id(.:format)"
+ "#{@scope[:shallow_path]}/#{parent_resource.path}/:id(.:format)"
else
"#{@scope[:path]}(.:format)"
end
@@ -856,7 +864,7 @@ module ActionDispatch
"#{@scope[:path]}/#{action_path(:new)}(.:format)"
when :edit
if parent_resource.shallow?
- "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(:edit)}(.:format)"
+ "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(:edit)}(.:format)"
else
"#{@scope[:path]}/#{action_path(:edit)}(.:format)"
end
@@ -866,7 +874,7 @@ module ActionDispatch
"#{@scope[:path]}/#{action_path(action)}(.:format)"
else
if parent_resource.shallow?
- "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)"
+ "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)"
else
"#{@scope[:path]}/#{action_path(action)}(.:format)"
end
@@ -880,7 +888,7 @@ module ActionDispatch
@scope[:path]
else
if parent_resource.shallow?
- "#{@scope[:module]}/#{parent_resource.path}/:id"
+ "#{@scope[:shallow_path]}/#{parent_resource.path}/:id"
else
@scope[:path]
end
@@ -901,7 +909,7 @@ module ActionDispatch
def name_for_action(action)
name_prefix = @scope[:name_prefix].blank? ? "" : "#{@scope[:name_prefix]}_"
- shallow_prefix = @scope[:module].blank? ? "" : "#{@scope[:module].tr('/', '_')}_"
+ shallow_prefix = @scope[:shallow_prefix].blank? ? "" : "#{@scope[:shallow_prefix]}_"
case action
when :index, :create
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index c4cdc4b2a8..495255c22b 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -278,8 +278,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ }
- scope :module => 'api' do
+ scope :module => :api do
resource :token
+ resources :errors, :shallow => true do
+ resources :notices
+ end
end
scope :path => 'api' do
@@ -1350,6 +1353,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_shallow_nested_routes_ignore_module
+ with_test_routes do
+ get '/errors/1/notices'
+ assert_equal 'api/notices#index', @response.body
+ assert_equal '/errors/1/notices', error_notices_path(:error_id => '1')
+
+ get '/notices/1'
+ assert_equal 'api/notices#show', @response.body
+ assert_equal '/notices/1', notice_path(:id => '1')
+ end
+ end
+
private
def with_test_routes
yield
--
cgit v1.2.3
From 86002a0dfe45c972a2498e33a6a2a882804603bd Mon Sep 17 00:00:00 2001
From: David Chelimsky
Date: Fri, 18 Jun 2010 22:20:10 -0500
Subject: Support render_template in view tests. Useful for specifying which
partials are rendered under different conditions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[#4903 state:resolved]
Signed-off-by: José Valim
---
actionpack/lib/action_view/test_case.rb | 1 +
actionpack/test/template/test_case_test.rb | 8 ++++++++
2 files changed, 9 insertions(+)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 15d424be74..306f59f9ca 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -84,6 +84,7 @@ module ActionView
def setup_with_controller
@controller = ActionView::TestCase::TestController.new
+ @request = @controller.request
@output_buffer = ActiveSupport::SafeBuffer.new
@rendered = ''
diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb
index 9b50ea8a42..c365aec841 100644
--- a/actionpack/test/template/test_case_test.rb
+++ b/actionpack/test/template/test_case_test.rb
@@ -218,4 +218,12 @@ module ActionView
end
end
end
+
+ class RenderTemplateTest < ActionView::TestCase
+ test "render template" do
+ controller.controller_path = "test"
+ render(:template => "test/calling_partial_with_layout")
+ assert_template "partial_for_use_in_layout"
+ end
+ end
end
--
cgit v1.2.3
From 95a8f252c028c94b70cce4888bce42b7e9e30786 Mon Sep 17 00:00:00 2001
From: rohit
Date: Wed, 16 Jun 2010 18:50:50 +0530
Subject: remove executable permission from files that don't need it. [#4802
state:resolved]
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/request.rb | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100755 => 100644 actionpack/lib/action_dispatch/http/request.rb
(limited to 'actionpack')
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
old mode 100755
new mode 100644
--
cgit v1.2.3
From bb6cd6d3ec02996c7dd11a4bb96381da18b7de8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarsoly=20Andr=C3=A1s?=
Date: Sat, 29 May 2010 22:09:14 +0200
Subject: Use Rack::Utils.bytesize when calculating content-length of exception
pages. [#4727 state:resolved]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: José Valim
---
actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'actionpack')
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 0a6d2bfc8a..e095b51342 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -122,7 +122,7 @@ module ActionDispatch
end
def render(status, body)
- [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, [body]]
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => body.bytesize.to_s}, [body]]
end
def public_path
--
cgit v1.2.3
From 96f5e59a26329aa972b8061a818410b0b378f306 Mon Sep 17 00:00:00 2001
From: Jan De Poorter
Date: Mon, 7 Jun 2010 15:03:07 +0200
Subject: Make sure a namespaced <%= render form %> still renders the _form
partial [#4784 state:resolved]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: José Valim
---
actionpack/lib/action_view/render/partials.rb | 2 +-
actionpack/test/controller/render_test.rb | 11 +++++++++++
actionpack/test/fixtures/fun/games/_form.erb | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
create mode 100644 actionpack/test/fixtures/fun/games/_form.erb
(limited to 'actionpack')
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index 85f67d4f14..fd896c263d 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -316,7 +316,7 @@ module ActionView
object.class.model_name.partial_path.dup.tap do |partial|
path = @view.controller_path
- partial.insert(0, "#{File.dirname(path)}/") if path.include?(?/)
+ partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/)
end
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index e3ed097c67..a57a12f271 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -7,6 +7,10 @@ module Fun
# :ported:
def hello_world
end
+
+ def nested_partial_with_form_builder
+ render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}, Proc.new {})
+ end
end
end
@@ -1230,6 +1234,13 @@ class RenderTest < ActionController::TestCase
assert_match(/