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.
@@ -10,15 +10,14 @@ module Merb
10
10
  module ClassMethods
11
11
 
12
12
  def controlling(name, options = {})
13
- options = { :flash => true }.merge!(options)
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
- include FlashSupport if options[:flash]
19
- @resource_proxy.registered_actions.each do |a|
20
- include Merb::ResourceController::Actions.const_get("#{a[:name].to_s.camel_case}")
21
- show_action(a[:name])
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
- path = resource_proxy.path_to_resource(params)
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 flash_supported?
120
- self.kind_of?(FlashSupport)
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
- @actions << { :name => name.to_sym }.merge(options)
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(*names)
33
- names.each { |n| @actions << n.is_a?(Hash) ? n : { :name => n.to_sym } }
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
 
@@ -1,3 +1,4 @@
1
1
  class Articles < Application
2
+ provides :xml, :json
2
3
  controlling :articles
3
4
  end
@@ -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,11 @@
1
+ <h2>New Rating</h2>
2
+
3
+ <%= form_for(@rating, :action => resource(@comment, :ratings)) do %>
4
+
5
+ <p><%= text_field :rate, :label => "Rating" %></p>
6
+
7
+ <p><%= submit "Create" %></p>
8
+
9
+ <% end =%>
10
+
11
+ <%= link_to 'Show Comment', resource(@comment) %>
@@ -11,7 +11,6 @@ dependency "dm-constraints", dm_gems_version
11
11
  dependency "merb-assets", merb_gems_version
12
12
  dependency "merb-helpers", merb_gems_version
13
13
 
14
-
15
14
  use_orm :datamapper
16
15
  use_test :rspec
17
16
  use_template_engine :erb
@@ -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, :flash => true, :use => :all }
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 { |h| h[:name] }
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, :flash => true, :use => :all }
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, :flash => true, :use => :all }
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, :flash => true, :use => :all }
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, :flash => true, :use => :all }
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, :flash => true, :use => :all }
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