snusnu-merb_resource_controller 0.1.0 → 0.2.0
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/README.textile +168 -18
- data/Rakefile +1 -1
- data/TODO +0 -1
- data/lib/merb_resource_controller.rb +2 -1
- data/lib/merb_resource_controller/action_descriptor.rb +107 -0
- data/lib/merb_resource_controller/actions.rb +159 -13
- data/lib/merb_resource_controller/resource_controller.rb +28 -44
- data/lib/merb_resource_controller/resource_proxy.rb +43 -12
- data/spec/mrc_test_app/app/controllers/articles.rb +1 -0
- data/spec/mrc_test_app/app/models/community/comment.rb +20 -0
- data/spec/mrc_test_app/app/models/community/rating.rb +19 -0
- data/spec/mrc_test_app/app/views/community/ratings/new.html.erb +11 -0
- data/spec/mrc_test_app/config/init.rb +0 -1
- data/spec/mrc_test_app/spec/lib/action_descriptor_spec.rb +137 -0
- data/spec/mrc_test_app/spec/lib/resource_proxy_spec.rb +7 -7
- data/spec/mrc_test_app/spec/request/article_comment_ratings_spec.rb +196 -0
- data/spec/mrc_test_app/spec/request/articles_spec.rb +266 -0
- metadata +19 -18
- data/spec/mrc_test_app/Rakefile +0 -52
- data/spec/mrc_test_app/app/controllers/editors.rb +0 -7
- data/spec/mrc_test_app/app/views/community/ratings/edit.html.erb +0 -11
@@ -10,15 +10,14 @@ module Merb
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
12
|
def controlling(name, options = {})
|
13
|
-
|
14
|
-
@resource_proxy = Merb::ResourceController::ResourceProxy.new(name, options)
|
13
|
+
@resource_proxy = ResourceProxy.new(name, class_provided_formats, options)
|
15
14
|
yield @resource_proxy if block_given?
|
16
15
|
class_inheritable_reader :resource_proxy
|
17
16
|
include InstanceMethods
|
18
|
-
|
19
|
-
|
20
|
-
include
|
21
|
-
show_action(
|
17
|
+
@resource_proxy.registered_actions.each do |action_descriptor|
|
18
|
+
include action_descriptor.action_module
|
19
|
+
include action_descriptor.flash_module if action_descriptor.supports_flash_messages?
|
20
|
+
show_action(action_descriptor.action_name)
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
@@ -33,6 +32,26 @@ module Merb
|
|
33
32
|
end
|
34
33
|
|
35
34
|
|
35
|
+
def handle_content_type(action, format, scenario)
|
36
|
+
if handler = content_type_handler(action, format, scenario)
|
37
|
+
self.send(handler) if self.respond_to?(handler)
|
38
|
+
else
|
39
|
+
raise "no content type handler registered for #{action} #{format} #{scenario}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_type_handler(action, format, scenario)
|
44
|
+
resource_proxy.content_type_handler(action, format, scenario)
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_action_specific_provides(action)
|
48
|
+
if resource_proxy.has_format_restriction?(action)
|
49
|
+
provides_api, formats = resource_proxy.action_specific_provides(action)
|
50
|
+
self.send(provides_api, *formats)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
36
55
|
def singleton_controller?
|
37
56
|
resource_proxy.singleton_resource?
|
38
57
|
end
|
@@ -63,10 +82,7 @@ module Merb
|
|
63
82
|
|
64
83
|
|
65
84
|
def load_resource
|
66
|
-
|
67
|
-
# puts "path_to_resource: #{path.inspect}"
|
68
|
-
path.each do |pc|
|
69
|
-
# puts "setting @#{pc[0]} to #{pc[1].inspect}" if pc[1]
|
85
|
+
resource_proxy.path_to_resource(params).each do |pc|
|
70
86
|
instance_variable_set("@#{pc[0]}", pc[1]) if pc[1]
|
71
87
|
end
|
72
88
|
end
|
@@ -116,43 +132,11 @@ module Merb
|
|
116
132
|
end
|
117
133
|
|
118
134
|
|
119
|
-
def
|
120
|
-
|
135
|
+
def flash_messages_for?(action)
|
136
|
+
resource_proxy.flash_messages_for?(action)
|
121
137
|
end
|
122
138
|
|
123
139
|
end
|
124
|
-
|
125
|
-
module FlashSupport
|
126
|
-
|
127
|
-
protected
|
128
|
-
|
129
|
-
def successful_create_messages
|
130
|
-
{ :notice => "#{member.class.name} was successfully created" }
|
131
|
-
end
|
132
|
-
|
133
|
-
def failed_create_messages
|
134
|
-
{ :error => "Failed to create new #{member.class.name}" }
|
135
|
-
end
|
136
|
-
|
137
|
-
|
138
|
-
def successful_update_messages
|
139
|
-
{ :notice => "#{member.class.name} was successfully updated" }
|
140
|
-
end
|
141
|
-
|
142
|
-
def failed_update_messages
|
143
|
-
{ :error => "Failed to update #{member.class.name}" }
|
144
|
-
end
|
145
|
-
|
146
|
-
|
147
|
-
def successful_destroy_messages
|
148
|
-
{ :notice => "#{member.class.name} was successfully destroyed" }
|
149
|
-
end
|
150
|
-
|
151
|
-
def failed_destroy_messages
|
152
|
-
{ :error => "Failed to destroy #{member.class.name}" }
|
153
|
-
end
|
154
|
-
|
155
|
-
end
|
156
140
|
|
157
141
|
end
|
158
142
|
|
@@ -13,11 +13,12 @@ module Merb
|
|
13
13
|
:use => :all
|
14
14
|
})
|
15
15
|
|
16
|
-
attr_reader :resource, :parents, :registered_methods
|
16
|
+
attr_reader :resource, :provided_formats, :parents, :registered_methods
|
17
17
|
|
18
|
-
def initialize(resource, options = {})
|
18
|
+
def initialize(resource, provided_formats, options = {})
|
19
19
|
options = DEFAULT_OPTIONS.merge(options)
|
20
20
|
@resource, @singleton = load_resource(resource), !!options[:singleton]
|
21
|
+
@provided_formats = provided_formats || [ :html ]
|
21
22
|
@fully_qualified = !!options[:fully_qualified]
|
22
23
|
@actions, @registered_methods, @parents = [], [], []
|
23
24
|
@specific_methods_registered = options[:use] != :all
|
@@ -26,17 +27,54 @@ module Merb
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def action(name, options = {})
|
29
|
-
|
30
|
+
options = { :default_formats => true }.merge(options)
|
31
|
+
descriptor = ActionDescriptor.new(name, @provided_formats, options)
|
32
|
+
yield descriptor if block_given?
|
33
|
+
@actions << descriptor
|
30
34
|
end
|
31
35
|
|
32
|
-
def actions(*
|
33
|
-
|
36
|
+
def actions(*action_specs)
|
37
|
+
action_specs.each { |a| a.is_a?(Hash) ? action(a.delete(:name), a) : action(a) }
|
34
38
|
end
|
35
39
|
|
36
40
|
def registered_actions
|
37
41
|
@actions
|
38
42
|
end
|
39
43
|
|
44
|
+
def flash_messages_for?(action)
|
45
|
+
return false unless @actions.map { |ad| ad.action_name }.include?(action.to_sym)
|
46
|
+
@actions.any? { |ad| ad.action_name == action.to_sym && ad.supports_flash_messages? }
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def action_descriptor(action)
|
51
|
+
ad = @actions.select { |ad| ad.action_name == action.to_sym }
|
52
|
+
ad.first ? ad.first : raise("No action named #{action} is registered for this controller")
|
53
|
+
end
|
54
|
+
|
55
|
+
def content_type_handler(action, format, scenario)
|
56
|
+
action_descriptor(action).content_type_handler(format, scenario)
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_format_restriction?(action)
|
60
|
+
action_descriptor(action).has_format_restriction?
|
61
|
+
end
|
62
|
+
|
63
|
+
def action_specific_provides(action)
|
64
|
+
ad = action_descriptor(action)
|
65
|
+
[ ad.format_restriction_api, ad.restricted_formats ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def register_default_actions!
|
69
|
+
action :index unless @singleton
|
70
|
+
action :show
|
71
|
+
action :new, :only_provides => :html
|
72
|
+
action :edit, :only_provides => :html
|
73
|
+
action :create, :flash => true
|
74
|
+
action :update, :flash => true
|
75
|
+
action :destroy, :flash => true
|
76
|
+
end
|
77
|
+
|
40
78
|
# ----------------------------------------------------------------------------------------
|
41
79
|
# # one level nestings
|
42
80
|
# ----------------------------------------------------------------------------------------
|
@@ -275,13 +313,6 @@ module Merb
|
|
275
313
|
end
|
276
314
|
end
|
277
315
|
|
278
|
-
def register_default_actions!
|
279
|
-
action :index unless @singleton
|
280
|
-
[ :show, :new, :edit, :create, :update, :destroy ].each do |a|
|
281
|
-
action(a)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
316
|
|
286
317
|
# KEEP THESE for later
|
287
318
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Community
|
2
|
+
|
3
|
+
class Comment
|
4
|
+
|
5
|
+
include DataMapper::Resource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :article_id, Integer, :nullable => false
|
9
|
+
property :body, String, :nullable => false, :length => (3..255)
|
10
|
+
|
11
|
+
belongs_to :article
|
12
|
+
has n, :ratings, :class_name => "Community::Rating"
|
13
|
+
|
14
|
+
def article_title
|
15
|
+
article.title
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Community
|
2
|
+
|
3
|
+
class Rating
|
4
|
+
|
5
|
+
include DataMapper::Resource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :comment_id, Integer, :nullable => false
|
9
|
+
property :rate, Integer, :nullable => false
|
10
|
+
|
11
|
+
belongs_to :comment
|
12
|
+
|
13
|
+
def comment_body
|
14
|
+
comment.body
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
describe "Merb::ResourceController::ActionDescriptor" do
|
2
|
+
|
3
|
+
it "should raise if no action is given" do
|
4
|
+
lambda { Merb::ResourceController::ActionDescriptor.new }.should raise_error
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should raise if more than one format restriction was specified" do
|
8
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
9
|
+
options = { :provides => :xml, :does_not_provide => :json, :only_provides => :yml }
|
10
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, options) }.should raise_error
|
11
|
+
options = { :provides => :xml, :does_not_provide => :json }
|
12
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, options) }.should raise_error
|
13
|
+
options = { :provides => :xml, :only_provides => :json }
|
14
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, options) }.should raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow valid format restriction apis" do
|
18
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
19
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :provides => :xml) }.should_not raise_error
|
20
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :does_not_provide => :xml) }.should_not raise_error
|
21
|
+
lambda { Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :only_provides => :xml) }.should_not raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be able to infer the format restriction api" do
|
25
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
26
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats)
|
27
|
+
p.format_restriction_api.should == nil
|
28
|
+
p.has_format_restriction?.should be_false
|
29
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :provides => :xml)
|
30
|
+
p.format_restriction_api.should == :provides
|
31
|
+
p.has_format_restriction?.should be_true
|
32
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :provides => [ :xml, :json ])
|
33
|
+
p.format_restriction_api.should == :provides
|
34
|
+
p.has_format_restriction?.should be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should be able to infer the restricted formats" do
|
38
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
39
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats)
|
40
|
+
p.restricted_formats.should be_empty
|
41
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :provides => :xml)
|
42
|
+
p.restricted_formats.should == [ :xml ]
|
43
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats, :provides => [ :xml, :json ])
|
44
|
+
p.restricted_formats.should == [ :xml, :json ]
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "should remember the action it is proxying" do
|
49
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
50
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats)
|
51
|
+
p.action_name.should == :index
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should know about the module that defines the action" do
|
55
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
56
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats)
|
57
|
+
p.action_module.should == Merb::ResourceController::Actions::Index
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should know about the module that defines the flash support" do
|
61
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
62
|
+
p = Merb::ResourceController::ActionDescriptor.new(:index, provided_formats)
|
63
|
+
p.supports_flash_messages?.should be_false
|
64
|
+
p.has_flash_module?.should be_false
|
65
|
+
p.flash_module.should == nil
|
66
|
+
p = Merb::ResourceController::ActionDescriptor.new(:show, provided_formats)
|
67
|
+
p.supports_flash_messages?.should be_false
|
68
|
+
p.has_flash_module?.should be_false
|
69
|
+
p.flash_module.should == nil
|
70
|
+
p = Merb::ResourceController::ActionDescriptor.new(:new, provided_formats)
|
71
|
+
p.supports_flash_messages?.should be_false
|
72
|
+
p.has_flash_module?.should be_false
|
73
|
+
p.flash_module.should == nil
|
74
|
+
|
75
|
+
p = Merb::ResourceController::ActionDescriptor.new(:edit, provided_formats)
|
76
|
+
p.supports_flash_messages?.should be_false
|
77
|
+
p.has_flash_module?.should be_false
|
78
|
+
p.flash_module.should == nil
|
79
|
+
|
80
|
+
p = Merb::ResourceController::ActionDescriptor.new(:create, provided_formats)
|
81
|
+
p.supports_flash_messages?.should be_false
|
82
|
+
p.has_flash_module?.should be_true
|
83
|
+
p.flash_module.should == Merb::ResourceController::Actions::Create::FlashSupport
|
84
|
+
|
85
|
+
p = Merb::ResourceController::ActionDescriptor.new(:update, provided_formats)
|
86
|
+
p.supports_flash_messages?.should be_false
|
87
|
+
p.has_flash_module?.should be_true
|
88
|
+
p.flash_module.should == Merb::ResourceController::Actions::Update::FlashSupport
|
89
|
+
|
90
|
+
p = Merb::ResourceController::ActionDescriptor.new(:destroy, provided_formats)
|
91
|
+
p.supports_flash_messages?.should be_false
|
92
|
+
p.has_flash_module?.should be_true
|
93
|
+
p.flash_module.should == Merb::ResourceController::Actions::Destroy::FlashSupport
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should be able to infer the content_type_handler_method" do
|
98
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
99
|
+
p = Merb::ResourceController::ActionDescriptor.new(:create, provided_formats)
|
100
|
+
# builtin formats
|
101
|
+
p.content_type_handler_method(:html, :success).should == "html_response_on_successful_create"
|
102
|
+
p.content_type_handler_method(:html, :failure).should == "html_response_on_failed_create"
|
103
|
+
p.content_type_handler_method(:xml, :success).should == "xml_response_on_successful_create"
|
104
|
+
p.content_type_handler_method(:xml, :failure).should == "xml_response_on_failed_create"
|
105
|
+
p.content_type_handler_method(:json, :success).should == "json_response_on_successful_create"
|
106
|
+
p.content_type_handler_method(:json, :failure).should == "json_response_on_failed_create"
|
107
|
+
p.content_type_handler_method(:yml, :success).should == "yml_response_on_successful_create"
|
108
|
+
p.content_type_handler_method(:yml, :failure).should == "yml_response_on_failed_create"
|
109
|
+
# custom formats
|
110
|
+
p.content_type_handler_method(:foo, :success).should == "foo_response_on_successful_create"
|
111
|
+
p.content_type_handler_method(:foo, :failure).should == "foo_response_on_failed_create"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be able to register content type handlers" do
|
115
|
+
provided_formats = [ :html, :xml, :json, :yml ]
|
116
|
+
|
117
|
+
p = Merb::ResourceController::ActionDescriptor.new(:create, provided_formats)
|
118
|
+
p.handle :json, :success
|
119
|
+
# p.content_type_handler(:json, :success).should == "json_response_on_successful_create"
|
120
|
+
# p.content_type_handler(:json, :failure).should be_nil
|
121
|
+
|
122
|
+
# p = Merb::ResourceController::ActionDescriptor.new(:create, provided_formats)
|
123
|
+
# p.handle [ :xml, :json ], :success
|
124
|
+
# p.content_type_handler(:xml, :succes).should == "xml_response_on_successful_create"
|
125
|
+
# p.content_type_handler(:xml, :failure).should be_nil
|
126
|
+
# p.content_type_handler(:json, :succes).should == "json_response_on_successful_create"
|
127
|
+
# p.content_type_handler(:json, :failure).should be_nil
|
128
|
+
#
|
129
|
+
# p = Merb::ResourceController::ActionDescriptor.new(:create, provided_formats)
|
130
|
+
# p.handle [ :xml, :json ]
|
131
|
+
# p.content_type_handler(:xml, :succes).should == "xml_response_on_successful_create"
|
132
|
+
# p.content_type_handler(:xml, :failure).should == "xml_response_on_failed_create"
|
133
|
+
# p.content_type_handler(:json, :succes).should == "json_response_on_successful_create"
|
134
|
+
# p.content_type_handler(:json, :failure).should == "json_response_on_failed_create"
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -31,7 +31,7 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
31
31
|
describe "with default options" do
|
32
32
|
|
33
33
|
before(:each) do
|
34
|
-
options = { :defaults => true, :
|
34
|
+
options = { :defaults => true, :use => :all }
|
35
35
|
@p = Merb::ResourceController::ResourceProxy.new(:articles, options)
|
36
36
|
end
|
37
37
|
|
@@ -53,7 +53,7 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
53
53
|
|
54
54
|
it "should have the default actions registered" do
|
55
55
|
default_actions = [ :index, :show, :new, :edit, :create, :update, :destroy ]
|
56
|
-
actions = @p.registered_actions.map { |
|
56
|
+
actions = @p.registered_actions.map { |ad| ad.action_name }
|
57
57
|
|
58
58
|
actions.size.should == default_actions.size
|
59
59
|
actions.all? { |a| default_actions.include?(a) }.should be_true
|
@@ -77,14 +77,14 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
77
77
|
describe "with invalid (parent) resource" do
|
78
78
|
|
79
79
|
it "should raise NameError when initialized with an invalid resource" do
|
80
|
-
options = { :defaults => true, :
|
80
|
+
options = { :defaults => true, :use => :all }
|
81
81
|
lambda {
|
82
82
|
Merb::ResourceController::ResourceProxy.new(:foo, options)
|
83
83
|
}.should raise_error(NameError)
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should raise NameError when it should belong to an invalid parent resource" do
|
87
|
-
options = { :defaults => true, :
|
87
|
+
options = { :defaults => true, :use => :all }
|
88
88
|
lambda {
|
89
89
|
p = Merb::ResourceController::ResourceProxy.new("Community::Comment", options)
|
90
90
|
p.belongs_to :foo
|
@@ -97,7 +97,7 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
97
97
|
describe "with no parent resource" do
|
98
98
|
|
99
99
|
before(:each) do
|
100
|
-
options = { :defaults => true, :
|
100
|
+
options = { :defaults => true, :use => :all }
|
101
101
|
@p = Merb::ResourceController::ResourceProxy.new(:articles, options)
|
102
102
|
end
|
103
103
|
|
@@ -146,7 +146,7 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
146
146
|
describe "with a single parent resource" do
|
147
147
|
|
148
148
|
before(:each) do
|
149
|
-
options = { :defaults => true, :
|
149
|
+
options = { :defaults => true, :use => :all }
|
150
150
|
@p = Merb::ResourceController::ResourceProxy.new("Community::Comment", options)
|
151
151
|
@p.belongs_to :article
|
152
152
|
end
|
@@ -208,7 +208,7 @@ describe "Merb::ResourceController::ResourceProxy" do
|
|
208
208
|
describe "with multiple parent resources with default keys" do
|
209
209
|
|
210
210
|
before(:each) do
|
211
|
-
options = { :defaults => true, :
|
211
|
+
options = { :defaults => true, :use => :all }
|
212
212
|
@p = Merb::ResourceController::ResourceProxy.new("Community::Rating", options)
|
213
213
|
@p.belongs_to [ :article, "Community::Comment" ]
|
214
214
|
end
|