snusnu-merb_resource_controller 0.1.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.
Files changed (47) hide show
  1. data/LICENSE +20 -0
  2. data/README.textile +306 -0
  3. data/Rakefile +81 -0
  4. data/TODO +7 -0
  5. data/lib/merb_resource_controller/action_timeout_support.rb +53 -0
  6. data/lib/merb_resource_controller/actions.rb +169 -0
  7. data/lib/merb_resource_controller/identity_map_support.rb +20 -0
  8. data/lib/merb_resource_controller/resource_controller.rb +160 -0
  9. data/lib/merb_resource_controller/resource_proxy.rb +317 -0
  10. data/lib/merb_resource_controller.rb +29 -0
  11. data/spec/mrc_test_app/Rakefile +52 -0
  12. data/spec/mrc_test_app/app/controllers/application.rb +6 -0
  13. data/spec/mrc_test_app/app/controllers/articles.rb +3 -0
  14. data/spec/mrc_test_app/app/controllers/community/comments.rb +9 -0
  15. data/spec/mrc_test_app/app/controllers/community/ratings.rb +9 -0
  16. data/spec/mrc_test_app/app/controllers/editors.rb +7 -0
  17. data/spec/mrc_test_app/app/models/article.rb +19 -0
  18. data/spec/mrc_test_app/app/models/editor.rb +11 -0
  19. data/spec/mrc_test_app/app/views/articles/edit.html.erb +13 -0
  20. data/spec/mrc_test_app/app/views/articles/index.html.erb +25 -0
  21. data/spec/mrc_test_app/app/views/articles/new.html.erb +12 -0
  22. data/spec/mrc_test_app/app/views/articles/show.html.erb +8 -0
  23. data/spec/mrc_test_app/app/views/community/comments/edit.html.erb +12 -0
  24. data/spec/mrc_test_app/app/views/community/comments/index.html.erb +25 -0
  25. data/spec/mrc_test_app/app/views/community/comments/new.html.erb +3 -0
  26. data/spec/mrc_test_app/app/views/community/comments/show.html.erb +3 -0
  27. data/spec/mrc_test_app/app/views/community/ratings/edit.html.erb +11 -0
  28. data/spec/mrc_test_app/app/views/community/ratings/index.html.erb +25 -0
  29. data/spec/mrc_test_app/app/views/community/ratings/show.html.erb +3 -0
  30. data/spec/mrc_test_app/app/views/editors/edit.html.erb +12 -0
  31. data/spec/mrc_test_app/app/views/editors/new.html.erb +12 -0
  32. data/spec/mrc_test_app/app/views/editors/show.html.erb +7 -0
  33. data/spec/mrc_test_app/config/database.yml +33 -0
  34. data/spec/mrc_test_app/config/environments/development.rb +15 -0
  35. data/spec/mrc_test_app/config/environments/rake.rb +11 -0
  36. data/spec/mrc_test_app/config/environments/test.rb +12 -0
  37. data/spec/mrc_test_app/config/init.rb +36 -0
  38. data/spec/mrc_test_app/config/rack.rb +11 -0
  39. data/spec/mrc_test_app/config/router.rb +50 -0
  40. data/spec/mrc_test_app/spec/lib/resource_proxy_spec.rb +292 -0
  41. data/spec/mrc_test_app/spec/request/article_comments_spec.rb +208 -0
  42. data/spec/mrc_test_app/spec/request/article_editor_spec.rb +202 -0
  43. data/spec/mrc_test_app/spec/request/articles_spec.rb +208 -0
  44. data/spec/mrc_test_app/spec/request/comments_spec.rb +221 -0
  45. data/spec/mrc_test_app/spec/spec.opts +2 -0
  46. data/spec/mrc_test_app/spec/spec_helper.rb +206 -0
  47. metadata +166 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Martin Gamsjaeger
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,306 @@
1
+ h2. merb_resource_controller
2
+
3
+ A merb plugin that provides the default @CRUD@ actions for controllers and allows for easy customization
4
+ of the generated actions. @merb_resource_controller@ only supports @datamapper@ so far. Implementing support
5
+ for @active_record@ would be trivial, but I have no need for it.
6
+
7
+ Currently, @merb_resource_controller@ needs an extra specification inside the controller to define the nesting strategy
8
+ to use. This shouldn't really be necessary, since this information could be provided by the @Merb::Router@.
9
+ I'm planning to have a look into this soon! With that in place, nested resource_controllers could be _3 liners_
10
+ that just do what you would expect them to do.
11
+
12
+ To get you started with @merb_resource_controller@, all you have to do is extend it into your controller.
13
+ Most probably you will want extend it into the @Application@ controller, which will make the @controlling@
14
+ method available to all your application's controllers.
15
+
16
+ <pre>
17
+ <code>
18
+ class Application < Merb::Controller
19
+ extend Merb::ResourceController::Mixin::ClassMethods
20
+ end
21
+ </code>
22
+ </pre>
23
+
24
+ And here is a quick example showing a controller for a standard toplevel resource with all standard @CRUD@ actions.
25
+
26
+ <pre>
27
+ <code>
28
+ class Articles < Application
29
+ controlling :articles
30
+ end
31
+ </code>
32
+ </pre>
33
+
34
+ If you don't want all standard @CRUD@ actions to be generated, give @merb_resource_controller@ the exact list
35
+ of actions you want your controller to have.
36
+
37
+ <pre>
38
+ <code>
39
+ class Articles < Application
40
+ controlling :articles do |a|
41
+ a.action :create
42
+ a.action :update
43
+ end
44
+ end
45
+ </code>
46
+ </pre>
47
+
48
+ Alternatively, you can also add more than one action at once using the @actions@ method available on the @ResourceProxy@
49
+
50
+ <pre>
51
+ <code>
52
+ class Articles < Application
53
+ controlling :articles do |a|
54
+ a.actions :create, :update
55
+ end
56
+ end
57
+ </code>
58
+ </pre>
59
+
60
+
61
+ If you are using models that are nested inside some @module@ (maybe you're developing a @slice@ ?), you need to
62
+ provide the fully qualified class name to the @controlling@ method. Per default, @merb_resource_controller@ assumes
63
+ that you don't want to use the fully qualified name to generate your instance variables and association calls.
64
+
65
+ <pre>
66
+ <code>
67
+ class Ratings < Application
68
+ controlling "Community::Rating"
69
+ end
70
+ </code>
71
+ </pre>
72
+
73
+ This will initialize the instance variable @@ratings@ (or @@rating@ respectively). If this resource is nested below
74
+ another resource (see next section), this also means that the @:ratings@ (or @:rating@ respectively) association will
75
+ be used to navigate from the parent resource down to this resource.
76
+
77
+ If however, you want to use fully qualified names for your instance variables and association calls, you can explicitly
78
+ pass @:fully_qualified => true@ to the @controlling@ method (@false@ is the default).
79
+
80
+ <pre>
81
+ <code>
82
+ class Ratings < Application
83
+ controlling "Community::Rating", :fully_qualified => true
84
+ end
85
+ </code>
86
+ </pre>
87
+
88
+ This will initialize the instance variable @@community_ratings@ (or @@community_rating@ respectively). If this resource
89
+ is nested below another resource (see next section), this also means that the @:community_ratings@ (or
90
+ @:community_rating@ respectively) association will be used to navigate from the parent resource down to this resource.
91
+
92
+ h2. Nested Resources
93
+
94
+ @merb_resource_controller@ will automatically recognize if it is accessed from a toplevel or a nested url, and
95
+ will _adjust_ its actions accordingly. It will also initialize all the instance variables
96
+ you would expect for your chosen nesting strategy. This means, that when you have an URL like
97
+ @/articles/1/comments@, you will have an @@article@ variable pointing to @Article.get(1)@ and a @@comments@ variable
98
+ pointing to @Article.get(1).comments@.
99
+
100
+ It's important to note, that no database operations will be performed more than once!
101
+ So in the case of @/articles/1/comments/1/ratings@, @merb_resource_controller@ will do exactly what you would
102
+ expect it to do: It will issue @Article.get(1).comments.get(1).ratings@, initializing
103
+ @@article@, @@comment@ and @@ratings@ with the intermediate results on it's way down the association chain.
104
+
105
+ Speaking of an _association chain_, it is worth mentioning that it is by no means necessary that your
106
+ underlying models are connected via _real datamapper associations_ (like @has n, ...@ or @belongs_to@).
107
+ The only requirement is, that the object returned from a call to the nested _collection_ @respond_to?(:get)@
108
+ (in most cases it will be a @DataMapper::Collection@ anyway).
109
+
110
+
111
+ <pre>
112
+ </code>
113
+ class Comments < Application
114
+ controlling :comments do |c|
115
+ c.belongs_to :article
116
+ end
117
+ end
118
+
119
+ class Ratings < Application
120
+ controlling :ratings do |r|
121
+ r.belongs_to [ :article, :comment ]
122
+ end
123
+ end
124
+ </code>
125
+ </pre>
126
+
127
+ h2. Nested Singleton Resources
128
+
129
+ First of all, singleton resources (currently) must always be nested below at least one parent resource.
130
+
131
+ This is mostly because I somehow can't really imagine a usecase for a real toplevel singleton resource? I mean, there
132
+ must be _some_ information on _how_ to load that _one_ resource. Since we're mostly dealing with database backends here,
133
+ we should probably need some kind of _key_ to identify exactly _one_ dataset, but we don't get that _key_ from a resource
134
+ like @/profile@ (_where_ is the @:id@ param here?). So my guess is, that most of the toplevel singleton resources that
135
+ _are_ actually used, really are nested below some kind of resource that's stored in the @session@, most probably the
136
+ authenticated @user@ object. If this is the case, it would be perfectly valid, to just _really nest_ those singletons
137
+ below their real parent, and probably add a route alias to keep up the disguise. If you can come up with a usecase
138
+ where you have a real toplevel singleton resource that needs _no key_ to be loaded, just don't use
139
+ @merb_resource_controller@. Really, it's that simple! If however, I'm completely on the wrong track here, I would be glad
140
+ to be informed about it, so that I can fix things up.
141
+
142
+ The example code below behaves almost exactly like described in the section on _Nested Resources_ above. The only
143
+ two differences are, that 1) @no index action@ will be generated and that 2) the initialized instance variables will be
144
+ named @@article@ and @@editor@ if you have a singleton resource nested like @/articles/1/editor@. Just like you would
145
+ expect, no?
146
+
147
+ <pre>
148
+ <code>
149
+ class Editors < Application
150
+
151
+ controlling :editor, :singleton => true do |e|
152
+ e.belongs_to :article
153
+ end
154
+
155
+ end
156
+ </code>
157
+ </pre>
158
+
159
+ h2. DataMapper's Identity Map
160
+
161
+ Including @Merb::ResourceController::DM::IdentityMapSupport@ into any of your controller will wrap all actions
162
+ inside a dm repository block in order to be able to use DM's identitiy map feature. For more information on that topic,
163
+ have a look at "DataMapper's Identity Map":http://datamapper.org/doku.php?id=docs:identity_map
164
+
165
+ Feel free to include this module into _single_ controllers instead of including it into @Application@ controller, which
166
+ enables identity maps for _every_ controller action in your app.
167
+
168
+ <pre>
169
+ <code>
170
+ class Application < Merb::Controller
171
+ include Merb::ResourceController::DM::IdentityMapSupport
172
+ end
173
+ </code>
174
+ </pre>
175
+
176
+ h2. Action Timeouts
177
+
178
+ Extending @Merb::ResourceController::ActionTimeout@ into any of your controllers, will give you the @set_action_timeout@
179
+ method. If you specify an action_timeout greater or equal to @1@ and you have the @system_timer@ gem installed, the
180
+ action will timeout after the given amount of seconds. For a more detailed explanation on the topic have a look at
181
+ "Battling Wedged Mongrels with a Request Timeout":http://adam.blog.heroku.com/past/2008/6/17/battling_wedged_mongrels_with_a/
182
+
183
+ Feel free to set action timeouts for _single_ controllers instead of doing so in @Application@ controller, which sets
184
+ the same action timeout for _every_ controller action in your app.
185
+
186
+ <pre>
187
+ <code>
188
+ class Application < Merb::Controller
189
+ extend Merb::ResourceController::ActionTimeout
190
+ set_action_timeout 1
191
+ end
192
+ </code>
193
+ </pre>
194
+
195
+ h2. Defined Actions
196
+
197
+ All the above controllers will have the following actions defined. Feel free to override them, to customize
198
+ how the controllers behave. Of course you are also free to override all the methods used by these defined actions.
199
+
200
+ <pre>
201
+ <code>
202
+ def index
203
+ load_resource
204
+ display requested_resource
205
+ end
206
+
207
+ def show
208
+ load_resource
209
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
210
+ display requested_resource
211
+ end
212
+
213
+ def new
214
+ only_provides :html
215
+ load_resource
216
+ set_member(new_member)
217
+ display member
218
+ end
219
+
220
+ def edit
221
+ only_provides :html
222
+ load_resource
223
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
224
+ display requested_resource
225
+ end
226
+
227
+ def create
228
+ load_resource
229
+ set_member(new_member(params[member_name]))
230
+ if member.save
231
+ options = flash_supported? ? { :message => successful_create_messages } : {}
232
+ redirect redirect_on_successful_create, options
233
+ else
234
+ message.merge!(failed_create_messages) if flash_supported?
235
+ render :new
236
+ end
237
+ end
238
+
239
+ def update
240
+ load_resource
241
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
242
+ if requested_resource.update_attributes(params[member_name])
243
+ options = flash_supported? ? { :message => successful_update_messages } : {}
244
+ redirect redirect_on_successful_update, options
245
+ else
246
+ message.merge!(failed_update_messages) if flash_supported?
247
+ display requested_resource, :edit
248
+ end
249
+ end
250
+
251
+ def destroy
252
+ load_resource
253
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
254
+ if requested_resource.destroy
255
+ options = flash_supported? ? { :message => successful_destroy_messages } : {}
256
+ redirect redirect_on_successful_destroy, options
257
+ else
258
+ raise Merb::ControllerExceptions::InternalServerError
259
+ end
260
+ end
261
+ </code>
262
+ </pre>
263
+
264
+ h2. Additional Helper Methods
265
+
266
+ In addition to the actions and the methods they are using, you will probably want to override the redirection targets
267
+ These are the default method implementations you can override to this effect:
268
+
269
+ <pre>
270
+ <code>
271
+ def redirect_on_successful_create
272
+ target = singleton_controller? ? member_name : member
273
+ resource(*(has_parent? ? parents + [ target ] : [ target ]))
274
+ end
275
+
276
+ def redirect_on_successful_update
277
+ target = singleton_controller? ? member_name : member
278
+ resource(*(has_parent? ? parents + [ target ] : [ target ]))
279
+ end
280
+
281
+ def redirect_on_successful_destroy
282
+ if singleton_controller?
283
+ has_parent? ? resource(parent) : '/'
284
+ else
285
+ resource(*(has_parent? ? parents + [ collection_name ] : [ collection_name ]))
286
+ end
287
+ end
288
+ </code>
289
+ </pre>
290
+
291
+ h2. More Information
292
+
293
+ Have a look at @Merb::ResourceController::Actions@, @Merb::ResourceController::Mixin::InstanceMethods@ and
294
+ @Merb::ResourceController::Mixin::FlashSupport@ inside @lib/merb_resource_controller/actions.rb@ and
295
+ @lib/merb_resource_controller/resource_controller.rb@ to see what methods will be available inside your controllers.
296
+ If you want to see where the _real work gets done_, have a look at @lib/merb_resource_controller/resource_proxy.rb@
297
+
298
+ Of course, you should also have a look at the specs, to get a more concrete idea of how @merb_resource_controller@
299
+ behaves under the given circumstances.
300
+
301
+ h2. TODO
302
+
303
+ # Infer route nesting strategy from @Merb::Router@
304
+ # Customizable support for @provides@ and @only_provides@
305
+ # Support for user stamps (aka created_by and updated_by)
306
+ # Support for pagination once an _official_ merb pagination solution exists
data/Rakefile ADDED
@@ -0,0 +1,81 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/tasks/merb'
6
+ require "spec/rake/spectask"
7
+
8
+ GEM_NAME = "merb_resource_controller"
9
+ GEM_VERSION = "0.1.0"
10
+ AUTHOR = "Martin Gamsjaeger"
11
+ EMAIL = "gamsnjaga@gmail.com"
12
+ HOMEPAGE = "http://merbivore.com/"
13
+ SUMMARY = "A merb plugin that provides the default restful actions for controllers."
14
+
15
+ spec = Gem::Specification.new do |s|
16
+
17
+ s.rubyforge_project = 'merb_resource_controller'
18
+ s.name = GEM_NAME
19
+ s.version = GEM_VERSION
20
+ s.platform = Gem::Platform::RUBY
21
+ s.has_rdoc = false
22
+ s.extra_rdoc_files = [ "LICENSE", 'TODO']
23
+ s.summary = SUMMARY
24
+ s.description = s.summary
25
+ s.author = AUTHOR
26
+ s.email = EMAIL
27
+ s.homepage = HOMEPAGE
28
+ s.require_path = 'lib'
29
+
30
+ # be extra picky so that no coverage info and such gets included
31
+ s.files = %w(LICENSE README.textile Rakefile TODO) +
32
+ Dir.glob("{lib,spec}/**/*.rb") +
33
+ Dir.glob("{spec}/**") +
34
+ Dir.glob("{spec}/**/*.rb") +
35
+ Dir.glob("{spec}/**/*.yml") +
36
+ Dir.glob("{spec}/**/*.opts") +
37
+ Dir.glob("{spec}/**/*.html.erb") +
38
+ [ "spec/mrc_test_app/Rakefile"]
39
+
40
+ # runtime dependencies
41
+ s.add_dependency('merb-core', '~> 1.0')
42
+
43
+ # development dependencies
44
+ # if these are desired, install with:
45
+ # gem install merb_resource_controller --development
46
+ s.add_development_dependency('merb-assets', '~>1.0')
47
+ s.add_development_dependency('merb-helpers', '~>1.0')
48
+ s.add_development_dependency('dm-core', '~>0.9.8')
49
+ s.add_development_dependency('dm-validations', '~>0.9.8')
50
+ s.add_development_dependency('dm-serializer', '~>0.9.8')
51
+ s.add_development_dependency('dm-constraints', '~>0.9.8')
52
+
53
+ end
54
+
55
+ Rake::GemPackageTask.new(spec) do |pkg|
56
+ pkg.gem_spec = spec
57
+ end
58
+
59
+ desc "install the plugin as a gem"
60
+ task :install do
61
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
62
+ end
63
+
64
+ desc "Uninstall the gem"
65
+ task :uninstall do
66
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
67
+ end
68
+
69
+ desc "Create a gemspec file"
70
+ task :gemspec do
71
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
72
+ file.puts spec.to_ruby
73
+ end
74
+ end
75
+
76
+ desc 'Default: run spec examples'
77
+ task :spec do
78
+ puts "!!! README !!! Run 'rake spec' from the './spec/mrc_test_app' directory to run all specs for merb_resource_controller."
79
+ end
80
+
81
+ task :default => 'spec'
data/TODO ADDED
@@ -0,0 +1,7 @@
1
+ TODO
2
+ ====
3
+
4
+ # Infer route nesting strategy from @Merb::Router@
5
+ # Customizable support for @provides@ and @only_provides@
6
+ # Support for user stamps (aka created_by and updated_by)
7
+ # Support for pagination once an _official_ merb pagination solution exists
@@ -0,0 +1,53 @@
1
+ require 'system_timer'
2
+
3
+ module Merb
4
+ module ResourceController
5
+
6
+ # To be extended into controllers
7
+ module ActionTimeout
8
+
9
+ def self.for?(controller)
10
+ self.for(controller) > 0
11
+ end
12
+
13
+ def self.for(controller)
14
+ (@controllers ||= {})[Application] || @controllers[controller] || 0
15
+ end
16
+
17
+ def self.register(controller, seconds)
18
+ (@controllers ||= {})[controller] = seconds
19
+ end
20
+
21
+
22
+ def set_action_timeout(seconds)
23
+ if seconds >= 1
24
+ ActionTimeout.register(self, seconds)
25
+ include InstanceMethods
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+
31
+ # taken from:
32
+ # http://datamapper.org/doku.php?id=docs:identity_map
33
+ def _call_action(*args)
34
+ if Merb::Plugins.config[:merb_resource_controller][:action_timeout]
35
+ return super unless ActionTimeout.for?(self.class)
36
+ timeout = ActionTimeout.for(self.class)
37
+ Merb.logger.info "SystemTimer.timeout for #{args[0]}: #{timeout} seconds"
38
+ # more information on system_timer:
39
+ # http://adam.blog.heroku.com/past/2008/6/17/battling_wedged_mongrels_with_a/
40
+ SystemTimer.timeout(timeout) do
41
+ super
42
+ end
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,169 @@
1
+ module Merb
2
+ module ResourceController
3
+
4
+ module Actions
5
+
6
+ module Index
7
+
8
+ # def index
9
+ # @articles = Article.all
10
+ # display @articles
11
+ # end
12
+
13
+ def index
14
+ load_resource
15
+ display requested_resource
16
+ end
17
+
18
+ end
19
+
20
+ module Show
21
+
22
+ # def show(id)
23
+ # @article = Article.get(id)
24
+ # raise NotFound unless @article
25
+ # display @article
26
+ # end
27
+
28
+ def show
29
+ load_resource
30
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
31
+ display requested_resource
32
+ end
33
+
34
+ end
35
+
36
+ module New
37
+
38
+ # def new
39
+ # only_provides :html
40
+ # @article = Article.new
41
+ # display @article
42
+ # end
43
+
44
+ def new
45
+ only_provides :html
46
+ load_resource
47
+ set_member(new_member)
48
+ display member
49
+ end
50
+
51
+ end
52
+
53
+ module Edit
54
+
55
+ # def edit(id)
56
+ # only_provides :html
57
+ # @article = Article.get(id)
58
+ # raise NotFound unless @article
59
+ # display @article
60
+ # end
61
+
62
+ def edit
63
+ only_provides :html
64
+ load_resource
65
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
66
+ display requested_resource
67
+ end
68
+
69
+ end
70
+
71
+ module Create
72
+
73
+ # def create(article)
74
+ # @article = Article.new(article)
75
+ # if @article.save
76
+ # redirect resource(@article), :message => { :notice => "Article was successfully created" }
77
+ # else
78
+ # message[:error] = "Article failed to be created"
79
+ # render :new
80
+ # end
81
+ # end
82
+
83
+ def create
84
+ load_resource
85
+ set_member(new_member)
86
+ if member.save
87
+ options = flash_supported? ? { :message => successful_create_messages } : {}
88
+ redirect redirect_on_successful_create, options
89
+ else
90
+ message.merge!(failed_create_messages) if flash_supported?
91
+ render :new, :status => 406
92
+ end
93
+ end
94
+
95
+ def redirect_on_successful_create
96
+ target = singleton_controller? ? member_name : member
97
+ resource(*(has_parent? ? parents + [ target ] : [ target ]))
98
+ end
99
+
100
+ end
101
+
102
+ module Update
103
+
104
+ # def update(id, article)
105
+ # @article = Article.get(id)
106
+ # raise NotFound unless @article
107
+ # if @article.update_attributes(article)
108
+ # redirect resource(@article), :message => { :notice => "Article was successfully updated" }
109
+ # else
110
+ # display @article, :edit
111
+ # end
112
+ # end
113
+
114
+ def update
115
+ load_resource
116
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
117
+ if requested_resource.update_attributes(params[member_name])
118
+ options = flash_supported? ? { :message => successful_update_messages } : {}
119
+ redirect redirect_on_successful_update, options
120
+ else
121
+ message.merge!(failed_update_messages) if flash_supported?
122
+ display requested_resource, :edit, :status => 406
123
+ end
124
+ end
125
+
126
+ def redirect_on_successful_update
127
+ target = singleton_controller? ? member_name : member
128
+ resource(*(has_parent? ? parents + [ target ] : [ target ]))
129
+ end
130
+
131
+ end
132
+
133
+ module Destroy
134
+
135
+ # def destroy(id)
136
+ # @article = Article.get(id)
137
+ # raise NotFound unless @article
138
+ # if @article.destroy
139
+ # redirect resource(:articles)
140
+ # else
141
+ # raise InternalServerError
142
+ # end
143
+ # end
144
+
145
+ def destroy
146
+ load_resource
147
+ raise Merb::ControllerExceptions::NotFound unless requested_resource
148
+ if requested_resource.destroy
149
+ options = flash_supported? ? { :message => successful_destroy_messages } : {}
150
+ redirect redirect_on_successful_destroy, options
151
+ else
152
+ raise Merb::ControllerExceptions::InternalServerError
153
+ end
154
+ end
155
+
156
+ def redirect_on_successful_destroy
157
+ if singleton_controller?
158
+ has_parent? ? resource(parent) : '/'
159
+ else
160
+ resource(*(has_parent? ? parents + [ collection_name ] : [ collection_name ]))
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,20 @@
1
+ module Merb
2
+ module ResourceController
3
+ module DM
4
+
5
+ # include this into controllers
6
+ module IdentityMapSupport
7
+
8
+ # taken from:
9
+ # http://datamapper.org/doku.php?id=docs:identity_map
10
+ def _call_action(*)
11
+ repository do |r| # enable identity_map
12
+ Merb.logger.info "Using DM Identity map inside #{r.name} repository block"
13
+ super
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end