inherited_resources 1.0.6 → 1.1.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +4 -0
- data/README.rdoc +30 -8
- data/Rakefile +3 -3
- data/lib/generators/rails/USAGE +10 -0
- data/lib/generators/rails/inherited_resources_controller_generator.rb +11 -0
- data/lib/generators/rails/templates/controller.rb +5 -0
- data/lib/inherited_resources.rb +5 -10
- data/lib/inherited_resources/actions.rb +8 -8
- data/lib/inherited_resources/base.rb +0 -3
- data/lib/inherited_resources/version.rb +1 -1
- data/test/aliases_test.rb +2 -2
- data/test/association_chain_test.rb +2 -2
- data/test/base_test.rb +1 -1
- data/test/belongs_to_test.rb +2 -1
- data/test/customized_base_test.rb +1 -1
- data/test/test_helper.rb +9 -5
- data/test/url_helpers_test.rb +24 -8
- metadata +20 -36
- data/lib/inherited_resources/legacy/respond_to.rb +0 -151
- data/lib/inherited_resources/legacy/responder.rb +0 -220
- data/rails/init.rb +0 -1
- data/test/respond_to_test.rb +0 -174
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
@@ -10,19 +10,23 @@ a screencast made by Fabio Akita about its features:
|
|
10
10
|
|
11
11
|
http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with-inherited-resources
|
12
12
|
|
13
|
-
|
13
|
+
== Rails 3
|
14
14
|
|
15
|
-
|
15
|
+
Inherited Resources master branch is now supports Rails 3 and is backward incompatible.
|
16
16
|
|
17
|
-
|
17
|
+
You can install it as:
|
18
18
|
|
19
|
-
|
19
|
+
sudo gem install inherited_resources --version=1.1.pre
|
20
20
|
|
21
|
-
If you want
|
21
|
+
If you want to use the Rails 2.3.x version, you should install:
|
22
22
|
|
23
|
-
|
23
|
+
sudo gem install inherited_resources --version=1.0
|
24
24
|
|
25
|
-
|
25
|
+
Or checkout from the v1.0 branch:
|
26
|
+
|
27
|
+
http://github.com/josevalim/inherited_resources/tree/v1.0
|
28
|
+
|
29
|
+
== HasScope
|
26
30
|
|
27
31
|
Since Inherited Resources 1.0, has_scope is not part of its core anymore.
|
28
32
|
However, if you are using has_scope in your application, Inherited Resources
|
@@ -36,7 +40,7 @@ And can be installed as:
|
|
36
40
|
|
37
41
|
sudo gem install has_scope
|
38
42
|
|
39
|
-
|
43
|
+
== Responders
|
40
44
|
|
41
45
|
Since Inherited Resources 1.0, responders are not part of its core anymore,
|
42
46
|
but is set as Inherited Resources dependency and it's used by default by
|
@@ -211,6 +215,24 @@ provided. So you can do:
|
|
211
215
|
end
|
212
216
|
end
|
213
217
|
|
218
|
+
If you simply want to change the flash message for a particular action, you can
|
219
|
+
pass the message to the parent action using the keys :notice and :alert (as you
|
220
|
+
would with flash):
|
221
|
+
|
222
|
+
class ProjectsController < InheritedResources::Base
|
223
|
+
def create
|
224
|
+
create!(:notice => "Dude! Nice job creating that project.")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
You can still pass the block to change the redirect, as mentioned above:
|
229
|
+
|
230
|
+
class ProjectsController < InheritedResources::Base
|
231
|
+
def create
|
232
|
+
create!(:notice => "Dude! Nice job creating that project.") { root_url }
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
214
236
|
Now let's suppose that before create a project you have to do something special
|
215
237
|
but you don't want to create a before filter for it:
|
216
238
|
|
data/Rakefile
CHANGED
@@ -16,9 +16,9 @@ begin
|
|
16
16
|
s.homepage = "http://github.com/josevalim/inherited_resources"
|
17
17
|
s.description = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important."
|
18
18
|
s.authors = ['José Valim']
|
19
|
-
s.files = FileList["[A-Z]*", "
|
20
|
-
s.add_dependency("responders", "~> 0.
|
21
|
-
s.add_dependency("has_scope", "~> 0.
|
19
|
+
s.files = FileList["[A-Z]*", "init.rb", "{lib}/**/*"]
|
20
|
+
s.add_dependency("responders", "~> 0.5.0")
|
21
|
+
s.add_dependency("has_scope", "~> 0.4.2")
|
22
22
|
end
|
23
23
|
|
24
24
|
Jeweler::GemcutterTasks.new
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
Stubs out a scaffolded controller and its views using InheritedResources.
|
3
|
+
Pass the model name, either CamelCased or under_scored. The controller
|
4
|
+
name is retrieved as a pluralized version of the model name.
|
5
|
+
|
6
|
+
To create a controller within a module, specify the model name as a
|
7
|
+
path like 'parent_module/controller_name'.
|
8
|
+
|
9
|
+
This generates a controller class in app/controllers and invokes helper,
|
10
|
+
template engine and test framework generators.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'generators/rails/scaffold_controller/scaffold_controller_generator'
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Generators
|
5
|
+
class InheritedResourcesControllerGenerator < ScaffoldControllerGenerator
|
6
|
+
def self.source_root
|
7
|
+
@source_root ||= File.expand_path("templates", File.dirname(__FILE__))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/inherited_resources.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
# respond_to is the only file that should be loaded before hand. All others
|
2
|
-
# are loaded on demand.
|
3
|
-
#
|
4
|
-
unless defined?(ActionController::Responder)
|
5
|
-
require 'inherited_resources/legacy/responder'
|
6
|
-
require 'inherited_resources/legacy/respond_to'
|
7
|
-
end
|
8
|
-
|
9
1
|
require 'responders'
|
10
2
|
I18n.load_path.unshift File.expand_path(File.join(File.dirname(__FILE__), 'inherited_resources', 'locales', 'en.yml'))
|
11
3
|
|
@@ -27,11 +19,14 @@ module InheritedResources
|
|
27
19
|
def self.flash_keys=(array)
|
28
20
|
Responders::FlashResponder.flash_keys = array
|
29
21
|
end
|
22
|
+
|
23
|
+
class Railtie < ::Rails::Railtie
|
24
|
+
railtie_name :inherited_resources
|
25
|
+
config.generators.scaffold_controller = :inherited_resources_controller
|
26
|
+
end
|
30
27
|
end
|
31
28
|
|
32
29
|
class ActionController::Base
|
33
|
-
public :flash, :render
|
34
|
-
|
35
30
|
# If you cannot inherit from InheritedResources::Base you can call
|
36
31
|
# inherit_resource in your controller to have all the required modules and
|
37
32
|
# funcionality included.
|
@@ -3,26 +3,26 @@ module InheritedResources
|
|
3
3
|
module Actions
|
4
4
|
|
5
5
|
# GET /resources
|
6
|
-
def index(
|
7
|
-
respond_with(*
|
6
|
+
def index(&block)
|
7
|
+
respond_with(*with_chain(collection), &block)
|
8
8
|
end
|
9
9
|
alias :index! :index
|
10
10
|
|
11
11
|
# GET /resources/1
|
12
|
-
def show(
|
13
|
-
respond_with(*
|
12
|
+
def show(&block)
|
13
|
+
respond_with(*with_chain(resource), &block)
|
14
14
|
end
|
15
15
|
alias :show! :show
|
16
16
|
|
17
17
|
# GET /resources/new
|
18
|
-
def new(
|
19
|
-
respond_with(*
|
18
|
+
def new(&block)
|
19
|
+
respond_with(*with_chain(build_resource), &block)
|
20
20
|
end
|
21
21
|
alias :new! :new
|
22
22
|
|
23
23
|
# GET /resources/1/edit
|
24
|
-
def edit(
|
25
|
-
respond_with(*
|
24
|
+
def edit(&block)
|
25
|
+
respond_with(*with_chain(resource), &block)
|
26
26
|
end
|
27
27
|
alias :edit! :edit
|
28
28
|
|
@@ -12,10 +12,7 @@ module InheritedResources
|
|
12
12
|
# or overwrite some helpers in the base_helpers.rb file.
|
13
13
|
#
|
14
14
|
class Base < ::ApplicationController
|
15
|
-
unloadable
|
16
|
-
|
17
15
|
# Overwrite inherit_resources to add specific InheritedResources behavior.
|
18
|
-
#
|
19
16
|
def self.inherit_resources(base)
|
20
17
|
base.class_eval do
|
21
18
|
include InheritedResources::Actions
|
data/test/aliases_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
3
|
class Pet
|
4
|
-
|
4
|
+
extend ActiveModel::Naming
|
5
5
|
end
|
6
6
|
|
7
7
|
class Puppet
|
8
|
-
|
8
|
+
extend ActiveModel::Naming
|
9
9
|
end
|
10
10
|
|
11
11
|
class PetsController < InheritedResources::Base
|
data/test/base_test.rb
CHANGED
data/test/belongs_to_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -17,13 +17,17 @@ require 'mocha'
|
|
17
17
|
ENV["RAILS_ENV"] = "test"
|
18
18
|
RAILS_ROOT = "anywhere"
|
19
19
|
|
20
|
-
gem
|
20
|
+
gem "activesupport", "3.0.0.beta"
|
21
|
+
require "active_support"
|
21
22
|
|
22
|
-
gem
|
23
|
-
require
|
23
|
+
gem "activemodel", "3.0.0.beta"
|
24
|
+
require "active_model"
|
24
25
|
|
25
|
-
gem
|
26
|
-
require
|
26
|
+
gem "actionpack", "3.0.0.beta"
|
27
|
+
require "action_controller"
|
28
|
+
require "action_dispatch/middleware/flash"
|
29
|
+
|
30
|
+
require "rails/railtie"
|
27
31
|
|
28
32
|
I18n.load_path << File.join(File.dirname(__FILE__), 'locales', 'en.yml')
|
29
33
|
I18n.reload!
|
data/test/url_helpers_test.rb
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
|
-
class Universe
|
3
|
+
class Universe
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
end
|
4
6
|
class UniversesController < InheritedResources::Base
|
5
7
|
defaults :singleton => true, :route_instance_name => 'universum'
|
6
8
|
end
|
7
9
|
|
8
|
-
class House
|
10
|
+
class House
|
11
|
+
extend ActiveModel::Naming
|
12
|
+
end
|
9
13
|
class HousesController < InheritedResources::Base
|
10
14
|
end
|
11
15
|
|
12
|
-
class Backpack
|
16
|
+
class Backpack
|
17
|
+
extend ActiveModel::Naming
|
18
|
+
end
|
13
19
|
module Admin; end
|
14
20
|
class Admin::BackpacksController < InheritedResources::Base
|
15
21
|
defaults :route_collection_name => 'tour_backpacks'
|
16
22
|
end
|
17
23
|
|
18
|
-
class Table
|
24
|
+
class Table
|
25
|
+
extend ActiveModel::Naming
|
26
|
+
end
|
19
27
|
class TablesController < InheritedResources::Base
|
20
28
|
belongs_to :house
|
21
29
|
end
|
@@ -34,26 +42,34 @@ class OwnersController < InheritedResources::Base
|
|
34
42
|
singleton_belongs_to :house
|
35
43
|
end
|
36
44
|
|
37
|
-
class Bed
|
45
|
+
class Bed
|
46
|
+
extend ActiveModel::Naming
|
47
|
+
end
|
38
48
|
class BedsController < InheritedResources::Base
|
39
49
|
optional_belongs_to :house, :building
|
40
50
|
end
|
41
51
|
|
42
|
-
class Desk
|
52
|
+
class Desk
|
53
|
+
extend ActiveModel::Naming
|
54
|
+
end
|
43
55
|
module Admin
|
44
56
|
class DesksController < InheritedResources::Base
|
45
57
|
optional_belongs_to :house
|
46
58
|
end
|
47
59
|
end
|
48
60
|
|
49
|
-
class Dish
|
61
|
+
class Dish
|
62
|
+
extend ActiveModel::Naming
|
63
|
+
end
|
50
64
|
class DishesController < InheritedResources::Base
|
51
65
|
belongs_to :house do
|
52
66
|
polymorphic_belongs_to :table, :kitchen
|
53
67
|
end
|
54
68
|
end
|
55
69
|
|
56
|
-
class Center
|
70
|
+
class Center
|
71
|
+
extend ActiveModel::Naming
|
72
|
+
end
|
57
73
|
class CentersController < InheritedResources::Base
|
58
74
|
acts_as_singleton!
|
59
75
|
|
metadata
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inherited_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 1
|
7
|
-
- 0
|
8
|
-
- 6
|
9
|
-
version: 1.0.6
|
4
|
+
version: 1.1.pre
|
10
5
|
platform: ruby
|
11
6
|
authors:
|
12
7
|
- "Jos\xC3\xA9 Valim"
|
@@ -14,37 +9,29 @@ autorequire:
|
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
11
|
|
17
|
-
date: 2010-
|
12
|
+
date: 2010-02-06 00:00:00 +01:00
|
18
13
|
default_executable:
|
19
14
|
dependencies:
|
20
15
|
- !ruby/object:Gem::Dependency
|
21
16
|
name: responders
|
22
|
-
|
23
|
-
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
20
|
requirements:
|
25
21
|
- - ~>
|
26
22
|
- !ruby/object:Gem::Version
|
27
|
-
|
28
|
-
|
29
|
-
- 4
|
30
|
-
- 6
|
31
|
-
version: 0.4.6
|
32
|
-
type: :runtime
|
33
|
-
version_requirements: *id001
|
23
|
+
version: 0.5.0
|
24
|
+
version:
|
34
25
|
- !ruby/object:Gem::Dependency
|
35
26
|
name: has_scope
|
36
|
-
|
37
|
-
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
30
|
requirements:
|
39
31
|
- - ~>
|
40
32
|
- !ruby/object:Gem::Version
|
41
|
-
|
42
|
-
|
43
|
-
- 5
|
44
|
-
- 0
|
45
|
-
version: 0.5.0
|
46
|
-
type: :runtime
|
47
|
-
version_requirements: *id002
|
33
|
+
version: 0.4.2
|
34
|
+
version:
|
48
35
|
description: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important.
|
49
36
|
email: jose.valim@gmail.com
|
50
37
|
executables: []
|
@@ -58,6 +45,9 @@ files:
|
|
58
45
|
- MIT-LICENSE
|
59
46
|
- README.rdoc
|
60
47
|
- Rakefile
|
48
|
+
- lib/generators/rails/USAGE
|
49
|
+
- lib/generators/rails/inherited_resources_controller_generator.rb
|
50
|
+
- lib/generators/rails/templates/controller.rb
|
61
51
|
- lib/inherited_resources.rb
|
62
52
|
- lib/inherited_resources/actions.rb
|
63
53
|
- lib/inherited_resources/base.rb
|
@@ -66,15 +56,12 @@ files:
|
|
66
56
|
- lib/inherited_resources/blank_slate.rb
|
67
57
|
- lib/inherited_resources/class_methods.rb
|
68
58
|
- lib/inherited_resources/dsl.rb
|
69
|
-
- lib/inherited_resources/legacy/respond_to.rb
|
70
|
-
- lib/inherited_resources/legacy/responder.rb
|
71
59
|
- lib/inherited_resources/locales/en.yml
|
72
60
|
- lib/inherited_resources/polymorphic_helpers.rb
|
73
61
|
- lib/inherited_resources/responder.rb
|
74
62
|
- lib/inherited_resources/singleton_helpers.rb
|
75
63
|
- lib/inherited_resources/url_helpers.rb
|
76
64
|
- lib/inherited_resources/version.rb
|
77
|
-
- rails/init.rb
|
78
65
|
has_rdoc: true
|
79
66
|
homepage: http://github.com/josevalim/inherited_resources
|
80
67
|
licenses: []
|
@@ -88,20 +75,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
75
|
requirements:
|
89
76
|
- - ">="
|
90
77
|
- !ruby/object:Gem::Version
|
91
|
-
segments:
|
92
|
-
- 0
|
93
78
|
version: "0"
|
79
|
+
version:
|
94
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
81
|
requirements:
|
96
|
-
- - "
|
82
|
+
- - ">"
|
97
83
|
- !ruby/object:Gem::Version
|
98
|
-
|
99
|
-
|
100
|
-
version: "0"
|
84
|
+
version: 1.3.1
|
85
|
+
version:
|
101
86
|
requirements: []
|
102
87
|
|
103
88
|
rubyforge_project: inherited_resources
|
104
|
-
rubygems_version: 1.3.
|
89
|
+
rubygems_version: 1.3.5
|
105
90
|
signing_key:
|
106
91
|
specification_version: 3
|
107
92
|
summary: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important.
|
@@ -118,7 +103,6 @@ test_files:
|
|
118
103
|
- test/optional_belongs_to_test.rb
|
119
104
|
- test/polymorphic_test.rb
|
120
105
|
- test/redirect_to_test.rb
|
121
|
-
- test/respond_to_test.rb
|
122
106
|
- test/singleton_test.rb
|
123
107
|
- test/test_helper.rb
|
124
108
|
- test/url_helpers_test.rb
|
@@ -1,151 +0,0 @@
|
|
1
|
-
module ActionController #:nodoc:
|
2
|
-
class Base #:nodoc:
|
3
|
-
attr_accessor :formats
|
4
|
-
|
5
|
-
class_inheritable_accessor :mimes_for_respond_to, :responder, :instance_writer => false
|
6
|
-
|
7
|
-
self.responder = ActionController::Responder
|
8
|
-
self.mimes_for_respond_to = ActiveSupport::OrderedHash.new
|
9
|
-
|
10
|
-
if defined?(ApplicationController)
|
11
|
-
ApplicationController.responder ||= ActionController::Responder
|
12
|
-
ApplicationController.mimes_for_respond_to ||= ActiveSupport::OrderedHash.new
|
13
|
-
end
|
14
|
-
|
15
|
-
# Defines mimes that are rendered by default when invoking respond_with.
|
16
|
-
#
|
17
|
-
# Examples:
|
18
|
-
#
|
19
|
-
# respond_to :html, :xml, :json
|
20
|
-
#
|
21
|
-
# All actions on your controller will respond to :html, :xml and :json.
|
22
|
-
#
|
23
|
-
# But if you want to specify it based on your actions, you can use only and
|
24
|
-
# except:
|
25
|
-
#
|
26
|
-
# respond_to :html
|
27
|
-
# respond_to :xml, :json, :except => [ :edit ]
|
28
|
-
#
|
29
|
-
# The definition above explicits that all actions respond to :html. And all
|
30
|
-
# actions except :edit respond to :xml and :json.
|
31
|
-
#
|
32
|
-
# You can specify also only parameters:
|
33
|
-
#
|
34
|
-
# respond_to :rjs, :only => :create
|
35
|
-
#
|
36
|
-
def self.respond_to(*mimes)
|
37
|
-
options = mimes.extract_options!
|
38
|
-
clear_respond_to unless mimes_for_respond_to
|
39
|
-
|
40
|
-
only_actions = Array(options.delete(:only))
|
41
|
-
except_actions = Array(options.delete(:except))
|
42
|
-
|
43
|
-
mimes.each do |mime|
|
44
|
-
mime = mime.to_sym
|
45
|
-
mimes_for_respond_to[mime] = {}
|
46
|
-
mimes_for_respond_to[mime][:only] = only_actions unless only_actions.empty?
|
47
|
-
mimes_for_respond_to[mime][:except] = except_actions unless except_actions.empty?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Clear all mimes in respond_to.
|
52
|
-
def self.clear_respond_to
|
53
|
-
write_inheritable_attribute(:mimes_for_respond_to, ActiveSupport::OrderedHash.new)
|
54
|
-
end
|
55
|
-
|
56
|
-
def respond_to(*mimes, &block)
|
57
|
-
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
|
58
|
-
if response = retrieve_response_from_mimes(mimes, &block)
|
59
|
-
response.call
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def respond_with(*resources, &block)
|
64
|
-
if response = retrieve_response_from_mimes([], &block)
|
65
|
-
options = resources.extract_options!
|
66
|
-
options.merge!(:default_response => response)
|
67
|
-
(options.delete(:responder) || responder).call(self, resources, options)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
|
73
|
-
# Collect mimes declared in the class method respond_to valid for the
|
74
|
-
# current action.
|
75
|
-
#
|
76
|
-
def collect_mimes_from_class_level #:nodoc:
|
77
|
-
action = action_name.to_sym
|
78
|
-
|
79
|
-
mimes_for_respond_to.keys.select do |mime|
|
80
|
-
config = mimes_for_respond_to[mime]
|
81
|
-
|
82
|
-
if config[:except]
|
83
|
-
!config[:except].include?(action)
|
84
|
-
elsif config[:only]
|
85
|
-
config[:only].include?(action)
|
86
|
-
else
|
87
|
-
true
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Collects mimes and return the response for the negotiated format. Returns
|
93
|
-
# nil if :not_acceptable was sent to the client.
|
94
|
-
#
|
95
|
-
def retrieve_response_from_mimes(mimes, &block)
|
96
|
-
responder = ActionController::MimeResponds::Responder.new(self)
|
97
|
-
mimes = collect_mimes_from_class_level if mimes.empty?
|
98
|
-
mimes.each { |mime| responder.send(mime) }
|
99
|
-
block.call(responder) if block_given?
|
100
|
-
|
101
|
-
if format = responder.negotiate_mime
|
102
|
-
self.response.template.template_format = format.to_sym
|
103
|
-
self.response.content_type = format.to_s
|
104
|
-
self.formats = [ format.to_sym ]
|
105
|
-
responder.response_for(format) || proc { default_render }
|
106
|
-
else
|
107
|
-
head :not_acceptable
|
108
|
-
nil
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
module MimeResponds
|
114
|
-
class Responder #:nodoc:
|
115
|
-
attr_reader :order
|
116
|
-
|
117
|
-
def any(*args, &block)
|
118
|
-
if args.any?
|
119
|
-
args.each { |type| send(type, &block) }
|
120
|
-
else
|
121
|
-
custom(Mime::ALL, &block)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
alias :all :any
|
125
|
-
|
126
|
-
def custom(mime_type, &block)
|
127
|
-
mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s)
|
128
|
-
@order << mime_type
|
129
|
-
@responses[mime_type] ||= block
|
130
|
-
end
|
131
|
-
|
132
|
-
def response_for(mime)
|
133
|
-
@responses[mime] || @responses[Mime::ALL]
|
134
|
-
end
|
135
|
-
|
136
|
-
def negotiate_mime
|
137
|
-
@mime_type_priority.each do |priority|
|
138
|
-
if priority == Mime::ALL
|
139
|
-
return @order.find { |m| m != Mime::ALL } || Mime::SET.first
|
140
|
-
elsif @order.include?(Mime::ALL)
|
141
|
-
return @mime_type_priority.find { |m| m != Mime::ALL } || Mime::SET.first
|
142
|
-
elsif @order.include?(priority)
|
143
|
-
return priority
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
nil
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
@@ -1,220 +0,0 @@
|
|
1
|
-
module ActionController #:nodoc:
|
2
|
-
# Responder is responsible to expose a resource for different mime requests,
|
3
|
-
# usually depending on the HTTP verb. The responder is triggered when
|
4
|
-
# respond_with is called. The simplest case to study is a GET request:
|
5
|
-
#
|
6
|
-
# class PeopleController < ApplicationController
|
7
|
-
# respond_to :html, :xml, :json
|
8
|
-
#
|
9
|
-
# def index
|
10
|
-
# @people = Person.find(:all)
|
11
|
-
# respond_with(@people)
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# When a request comes, for example with format :xml, three steps happen:
|
16
|
-
#
|
17
|
-
# 1) responder searches for a template at people/index.xml;
|
18
|
-
#
|
19
|
-
# 2) if the template is not available, it will invoke :to_xml in the given resource;
|
20
|
-
#
|
21
|
-
# 3) if the responder does not respond_to :to_xml, call :to_format on it.
|
22
|
-
#
|
23
|
-
# === Builtin HTTP verb semantics
|
24
|
-
#
|
25
|
-
# Rails default responder holds semantics for each HTTP verb. Depending on the
|
26
|
-
# content type, verb and the resource status, it will behave differently.
|
27
|
-
#
|
28
|
-
# Using Rails default responder, a POST request for creating an object could
|
29
|
-
# be written as:
|
30
|
-
#
|
31
|
-
# def create
|
32
|
-
# @user = User.new(params[:user])
|
33
|
-
# flash[:notice] = 'User was successfully created.' if @user.save
|
34
|
-
# respond_with(@user)
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# Which is exactly the same as:
|
38
|
-
#
|
39
|
-
# def create
|
40
|
-
# @user = User.new(params[:user])
|
41
|
-
#
|
42
|
-
# respond_to do |format|
|
43
|
-
# if @user.save
|
44
|
-
# flash[:notice] = 'User was successfully created.'
|
45
|
-
# format.html { redirect_to(@user) }
|
46
|
-
# format.xml { render :xml => @user, :status => :created, :location => @user }
|
47
|
-
# else
|
48
|
-
# format.html { render :action => "new" }
|
49
|
-
# format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# The same happens for PUT and DELETE requests.
|
55
|
-
#
|
56
|
-
# === Nested resources
|
57
|
-
#
|
58
|
-
# You can given nested resource as you do in form_for and polymorphic_url.
|
59
|
-
# Consider the project has many tasks example. The create action for
|
60
|
-
# TasksController would be like:
|
61
|
-
#
|
62
|
-
# def create
|
63
|
-
# @project = Project.find(params[:project_id])
|
64
|
-
# @task = @project.comments.build(params[:task])
|
65
|
-
# flash[:notice] = 'Task was successfully created.' if @task.save
|
66
|
-
# respond_with(@project, @task)
|
67
|
-
# end
|
68
|
-
#
|
69
|
-
# Giving an array of resources, you ensure that the responder will redirect to
|
70
|
-
# project_task_url instead of task_url.
|
71
|
-
#
|
72
|
-
# Namespaced and singleton resources requires a symbol to be given, as in
|
73
|
-
# polymorphic urls. If a project has one manager which has many tasks, it
|
74
|
-
# should be invoked as:
|
75
|
-
#
|
76
|
-
# respond_with(@project, :manager, @task)
|
77
|
-
#
|
78
|
-
# Check polymorphic_url documentation for more examples.
|
79
|
-
#
|
80
|
-
class Responder
|
81
|
-
attr_reader :controller, :request, :format, :resource, :resources, :options
|
82
|
-
|
83
|
-
ACTIONS_FOR_VERBS = {
|
84
|
-
:post => :new,
|
85
|
-
:put => :edit
|
86
|
-
}
|
87
|
-
|
88
|
-
def initialize(controller, resources, options={})
|
89
|
-
@controller = controller
|
90
|
-
@request = controller.request
|
91
|
-
@format = controller.formats.first
|
92
|
-
@resource = resources.is_a?(Array) ? resources.last : resources
|
93
|
-
@resources = resources
|
94
|
-
@options = options
|
95
|
-
@action = options.delete(:action)
|
96
|
-
@default_response = options.delete(:default_response)
|
97
|
-
end
|
98
|
-
|
99
|
-
delegate :head, :render, :redirect_to, :to => :controller
|
100
|
-
delegate :get?, :post?, :put?, :delete?, :to => :request
|
101
|
-
|
102
|
-
# Undefine :to_json and :to_yaml since it's defined on Object
|
103
|
-
undef_method(:to_json) if method_defined?(:to_json)
|
104
|
-
undef_method(:to_yaml) if method_defined?(:to_yaml)
|
105
|
-
|
106
|
-
# Initializes a new responder an invoke the proper format. If the format is
|
107
|
-
# not defined, call to_format.
|
108
|
-
#
|
109
|
-
def self.call(*args)
|
110
|
-
new(*args).respond
|
111
|
-
end
|
112
|
-
|
113
|
-
# Main entry point for responder responsible to dispatch to the proper format.
|
114
|
-
#
|
115
|
-
def respond
|
116
|
-
method = :"to_#{format}"
|
117
|
-
respond_to?(method) ? send(method) : to_format
|
118
|
-
end
|
119
|
-
|
120
|
-
# HTML format does not render the resource, it always attempt to render a
|
121
|
-
# template.
|
122
|
-
#
|
123
|
-
def to_html
|
124
|
-
default_render
|
125
|
-
rescue ActionView::MissingTemplate => e
|
126
|
-
navigation_behavior(e)
|
127
|
-
end
|
128
|
-
|
129
|
-
# All others formats follow the procedure below. First we try to render a
|
130
|
-
# template, if the template is not available, we verify if the resource
|
131
|
-
# responds to :to_format and display it.
|
132
|
-
#
|
133
|
-
def to_format
|
134
|
-
default_render
|
135
|
-
rescue ActionView::MissingTemplate => e
|
136
|
-
raise unless resourceful?
|
137
|
-
api_behavior(e)
|
138
|
-
end
|
139
|
-
|
140
|
-
protected
|
141
|
-
|
142
|
-
# This is the common behavior for "navigation" requests, like :html, :iphone and so forth.
|
143
|
-
def navigation_behavior(error)
|
144
|
-
if get?
|
145
|
-
raise error
|
146
|
-
elsif has_errors? && default_action
|
147
|
-
render :action => default_action
|
148
|
-
else
|
149
|
-
redirect_to resource_location
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# This is the common behavior for "API" requests, like :xml and :json.
|
154
|
-
def api_behavior(error)
|
155
|
-
if get?
|
156
|
-
display resource
|
157
|
-
elsif has_errors?
|
158
|
-
display resource.errors, :status => :unprocessable_entity
|
159
|
-
elsif post?
|
160
|
-
display resource, :status => :created, :location => resource_location
|
161
|
-
else
|
162
|
-
head :ok
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# Checks whether the resource responds to the current format or not.
|
167
|
-
#
|
168
|
-
def resourceful?
|
169
|
-
resource.respond_to?(:"to_#{format}")
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns the resource location by retrieving it from the options or
|
173
|
-
# returning the resources array.
|
174
|
-
#
|
175
|
-
def resource_location
|
176
|
-
options[:location] || resources
|
177
|
-
end
|
178
|
-
|
179
|
-
# If a given response block was given, use it, otherwise call render on
|
180
|
-
# controller.
|
181
|
-
#
|
182
|
-
def default_render
|
183
|
-
@default_response.call
|
184
|
-
end
|
185
|
-
|
186
|
-
# display is just a shortcut to render a resource with the current format.
|
187
|
-
#
|
188
|
-
# display @user, :status => :ok
|
189
|
-
#
|
190
|
-
# For xml request is equivalent to:
|
191
|
-
#
|
192
|
-
# render :xml => @user, :status => :ok
|
193
|
-
#
|
194
|
-
# Options sent by the user are also used:
|
195
|
-
#
|
196
|
-
# respond_with(@user, :status => :created)
|
197
|
-
# display(@user, :status => :ok)
|
198
|
-
#
|
199
|
-
# Results in:
|
200
|
-
#
|
201
|
-
# render :xml => @user, :status => :created
|
202
|
-
#
|
203
|
-
def display(resource, given_options={})
|
204
|
-
controller.send :render, given_options.merge!(options).merge!(format => resource)
|
205
|
-
end
|
206
|
-
|
207
|
-
# Check if the resource has errors or not.
|
208
|
-
#
|
209
|
-
def has_errors?
|
210
|
-
resource.respond_to?(:errors) && !resource.errors.empty?
|
211
|
-
end
|
212
|
-
|
213
|
-
# By default, render the :edit action for html requests with failure, unless
|
214
|
-
# the verb is post.
|
215
|
-
#
|
216
|
-
def default_action
|
217
|
-
@action ||= ACTIONS_FOR_VERBS[request.method]
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
data/rails/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'inherited_resources'
|
data/test/respond_to_test.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class Project
|
4
|
-
def to_html
|
5
|
-
'Generated HTML'
|
6
|
-
end
|
7
|
-
|
8
|
-
def to_xml
|
9
|
-
'Generated XML'
|
10
|
-
end
|
11
|
-
|
12
|
-
[:to_json, :to_rss, :to_rjs].each do |method|
|
13
|
-
undef_method method if respond_to? method
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class ProjectsController < ActionController::Base
|
18
|
-
respond_to :html
|
19
|
-
respond_to :xml, :except => :edit
|
20
|
-
respond_to :rjs, :only => :edit
|
21
|
-
respond_to :rss, :only => :index
|
22
|
-
respond_to :json, :except => :index
|
23
|
-
respond_to :csv, :except => :index
|
24
|
-
|
25
|
-
def index
|
26
|
-
respond_with(Project.new)
|
27
|
-
end
|
28
|
-
|
29
|
-
def respond_with_resource
|
30
|
-
respond_with(Project.new)
|
31
|
-
end
|
32
|
-
|
33
|
-
def respond_with_resource_and_options
|
34
|
-
respond_with(Project.new, :location => 'http://test.host/')
|
35
|
-
end
|
36
|
-
|
37
|
-
def respond_with_resource_and_blocks
|
38
|
-
respond_with(Project.new) do |format|
|
39
|
-
format.json { render :text => 'Render JSON' }
|
40
|
-
format.rss { render :text => 'Render RSS' }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# If the user request Mime::ALL and we have a template called action.html.erb,
|
45
|
-
# the html template should be rendered *unless* html is specified inside the
|
46
|
-
# block. This tests exactly this case.
|
47
|
-
#
|
48
|
-
def respond_to_skip_default_template
|
49
|
-
respond_with(Project.new) do |format|
|
50
|
-
format.html { render :text => 'Render HTML' }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class SuperProjectsController < ProjectsController
|
56
|
-
end
|
57
|
-
|
58
|
-
class NonInheritedResourcesController < ActionController::Base
|
59
|
-
def index
|
60
|
-
respond_to do |format|
|
61
|
-
format.xml { render :text => 'Render XML' }
|
62
|
-
format.any { render :text => 'Render HTML' }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class RespondToFunctionalTest < ActionController::TestCase
|
68
|
-
tests ProjectsController
|
69
|
-
|
70
|
-
def test_respond_with_layout_rendering
|
71
|
-
@request.accept = 'text/html'
|
72
|
-
get :index
|
73
|
-
assert_equal 'Index HTML', @response.body.strip
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_respond_with_calls_to_format_on_resource
|
77
|
-
@request.accept = 'application/xml'
|
78
|
-
get :index
|
79
|
-
assert_equal 'Generated XML', @response.body.strip
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_respond_with_inherits_format
|
83
|
-
@request.accept = 'application/xml'
|
84
|
-
get :index
|
85
|
-
assert_equal 'Generated XML', @response.body.strip
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_respond_with_renders_status_not_acceptable_if_mime_type_is_not_registered
|
89
|
-
@request.accept = 'text/csv'
|
90
|
-
get :index
|
91
|
-
assert_equal '406 Not Acceptable', @response.status
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_respond_with_raises_error_if_could_not_respond
|
95
|
-
@request.accept = 'application/rss+xml'
|
96
|
-
assert_raise ActionView::MissingTemplate do
|
97
|
-
get :index
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_respond_to_all
|
102
|
-
@request.accept = '*/*'
|
103
|
-
get :index
|
104
|
-
assert_equal 'Index HTML', @response.body.strip
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_respond_with_sets_content_type_properly
|
108
|
-
@request.accept = 'text/html'
|
109
|
-
get :index
|
110
|
-
assert_equal 'text/html', @response.content_type
|
111
|
-
assert_equal :html, @response.template.template_format
|
112
|
-
|
113
|
-
@request.accept = 'application/xml'
|
114
|
-
get :index
|
115
|
-
assert_equal 'application/xml', @response.content_type
|
116
|
-
assert_equal :xml, @response.template.template_format
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_respond_with_forwads_extra_options_to_render
|
120
|
-
@request.accept = 'application/xml'
|
121
|
-
get :respond_with_resource_and_options
|
122
|
-
assert_equal 'Generated XML', @response.body.strip
|
123
|
-
assert_equal 'http://test.host/', @response.headers['Location']
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_respond_to_when_a_resource_is_given_as_option
|
127
|
-
@request.accept = 'text/html'
|
128
|
-
get :respond_with_resource
|
129
|
-
assert_equal 'RespondTo HTML', @response.body.strip
|
130
|
-
|
131
|
-
@request.accept = 'application/xml'
|
132
|
-
get :respond_with_resource
|
133
|
-
assert_equal 'Generated XML', @response.body.strip
|
134
|
-
|
135
|
-
@request.accept = 'application/rss+xml'
|
136
|
-
get :respond_with_resource
|
137
|
-
assert_equal '406 Not Acceptable', @response.status
|
138
|
-
|
139
|
-
@request.accept = 'application/json'
|
140
|
-
assert_raise ActionView::MissingTemplate do
|
141
|
-
get :respond_with_resource
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def test_respond_to_overwrite_class_method_definition
|
146
|
-
@request.accept = 'application/rss+xml'
|
147
|
-
get :respond_with_resource_and_blocks
|
148
|
-
assert_equal 'Render RSS', @response.body.strip
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_respond_to_first_configured_mime_in_respond_to_when_mime_type_is_all
|
152
|
-
@request.accept = '*/*'
|
153
|
-
assert_raise ActionView::MissingTemplate do
|
154
|
-
get :respond_with_resource_and_blocks
|
155
|
-
end
|
156
|
-
assert_equal 'text/html', @response.content_type
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_respond_to_skip_default_template_when_it_is_in_block
|
160
|
-
@request.accept = '*/*'
|
161
|
-
get :respond_to_skip_default_template
|
162
|
-
assert_equal 'Render HTML', @response.body.strip
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
class RespondToFunctionalStandardControllerTest < ActionController::TestCase
|
167
|
-
tests NonInheritedResourcesController
|
168
|
-
|
169
|
-
def test_respond_with_no_specific_format
|
170
|
-
@request.accept = 'application/xml,application/xhtml+xml,text/html'
|
171
|
-
get :index
|
172
|
-
assert_equal 'Render HTML', @response.body.strip
|
173
|
-
end
|
174
|
-
end
|