make_resourceful 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 (40) hide show
  1. data/Rakefile +31 -0
  2. data/Readme.rdoc +229 -0
  3. data/VERSION +1 -0
  4. data/lib/make_resourceful.rb +11 -0
  5. data/lib/resourceful/base.rb +63 -0
  6. data/lib/resourceful/builder.rb +405 -0
  7. data/lib/resourceful/default/accessors.rb +418 -0
  8. data/lib/resourceful/default/actions.rb +101 -0
  9. data/lib/resourceful/default/callbacks.rb +51 -0
  10. data/lib/resourceful/default/responses.rb +118 -0
  11. data/lib/resourceful/default/urls.rb +136 -0
  12. data/lib/resourceful/generators/resourceful_scaffold/resourceful_scaffold_generator.rb +87 -0
  13. data/lib/resourceful/generators/resourceful_scaffold/templates/controller.rb +5 -0
  14. data/lib/resourceful/generators/resourceful_scaffold/templates/fixtures.yml +10 -0
  15. data/lib/resourceful/generators/resourceful_scaffold/templates/functional_test.rb +50 -0
  16. data/lib/resourceful/generators/resourceful_scaffold/templates/helper.rb +2 -0
  17. data/lib/resourceful/generators/resourceful_scaffold/templates/migration.rb +13 -0
  18. data/lib/resourceful/generators/resourceful_scaffold/templates/model.rb +2 -0
  19. data/lib/resourceful/generators/resourceful_scaffold/templates/unit_test.rb +7 -0
  20. data/lib/resourceful/generators/resourceful_scaffold/templates/view__form.haml +5 -0
  21. data/lib/resourceful/generators/resourceful_scaffold/templates/view_edit.haml +11 -0
  22. data/lib/resourceful/generators/resourceful_scaffold/templates/view_index.haml +5 -0
  23. data/lib/resourceful/generators/resourceful_scaffold/templates/view_new.haml +9 -0
  24. data/lib/resourceful/generators/resourceful_scaffold/templates/view_partial.haml +12 -0
  25. data/lib/resourceful/generators/resourceful_scaffold/templates/view_show.haml +14 -0
  26. data/lib/resourceful/maker.rb +92 -0
  27. data/lib/resourceful/response.rb +33 -0
  28. data/lib/resourceful/serialize.rb +185 -0
  29. data/spec/accessors_spec.rb +474 -0
  30. data/spec/actions_spec.rb +310 -0
  31. data/spec/base_spec.rb +12 -0
  32. data/spec/builder_spec.rb +332 -0
  33. data/spec/callbacks_spec.rb +71 -0
  34. data/spec/integration_spec.rb +394 -0
  35. data/spec/maker_spec.rb +91 -0
  36. data/spec/response_spec.rb +37 -0
  37. data/spec/responses_spec.rb +314 -0
  38. data/spec/serialize_spec.rb +133 -0
  39. data/spec/urls_spec.rb +282 -0
  40. metadata +97 -0
@@ -0,0 +1,418 @@
1
+ module Resourceful
2
+ # This module contains various methods
3
+ # that are available from actions and callbacks.
4
+ # Default::Accessors and Default::URLs are the most useful to users;
5
+ # the rest are mostly used internally.
6
+ #
7
+ # However, if you want to poke around the internals a little,
8
+ # check out Default::Actions, which has the default Action definitions,
9
+ # and Default::Responses.included, which defines the default response_for[link:classes/Resourceful/Builder.html#M000061] blocks.
10
+ module Default
11
+ # This module contains all sorts of useful methods
12
+ # that allow access to the resources being worked with,
13
+ # metadata about the controller and action,
14
+ # and so forth.
15
+ #
16
+ # Many of these accessors call other accessors
17
+ # and are called by the default make_resourceful actions[link:classes/Resourceful/Default/Actions.html].
18
+ # This means that overriding one method
19
+ # can affect everything else.
20
+ #
21
+ # This can be dangerous, but it can also be very powerful.
22
+ # make_resourceful is designed to take advantage of overriding,
23
+ # so as long as the new methods accomplish the same purpose as the old ones,
24
+ # everything will just work.
25
+ # Even if you make a small mistake,
26
+ # it's hard to break the controller in any unexpected ways.
27
+ #
28
+ # For example, suppose your controller is called TagsController,
29
+ # but your model is called PhotoTag.
30
+ # All you have to do is override current_model_name:
31
+ #
32
+ # def current_model_name
33
+ # "PhotoTag"
34
+ # end
35
+ #
36
+ # Then current_model will return the PhotoTag model,
37
+ # current_object will call <tt>PhotoTag.find</tt>,
38
+ # and so forth.
39
+ #
40
+ # Overriding current_objects and current_object is particularly useful
41
+ # for providing customized model lookup logic.
42
+ module Accessors
43
+ # Returns an array of all the objects of the model corresponding to the controller.
44
+ # For UsersController, it essentially runs <tt>User.find(:all)</tt>.
45
+ #
46
+ # However, there are a few important differences.
47
+ # First, this method caches is results in the <tt>@current_objects</tt> instance variable.
48
+ # That way, multiple calls won't run multiple queries.
49
+ #
50
+ # Second, this method uses the current_model accessor,
51
+ # which provides a lot of flexibility
52
+ # (see the documentation for current_model for details).
53
+ def current_objects
54
+ @current_objects ||= current_model.find(:all)
55
+ end
56
+
57
+ # Calls current_objects and stores
58
+ # the result in an instance variable
59
+ # named after the controller.
60
+ #
61
+ # This is called automatically by the default make_resourceful actions.
62
+ # You shouldn't need to use it directly unless you're creating a new action.
63
+ #
64
+ # For example, in UsersController,
65
+ # calling +load_objects+ sets <tt>@users = current_objects</tt>.
66
+ def load_objects
67
+ instance_variable_set("@#{instance_variable_name}", current_objects)
68
+ end
69
+
70
+ # Returns the object referenced by the id parameter
71
+ # (or the newly-created object for the +new+ and +create+ actions).
72
+ # For UsersController, it essentially runs <tt>User.find(params[:id])</tt>.
73
+ #
74
+ # However, there are a few important differences.
75
+ # First, this method caches is results in the <tt>@current_objects</tt> instance variable.
76
+ # That way, multiple calls won't run multiple queries.
77
+ #
78
+ # Second, this method uses the current_model accessor,
79
+ # which provides a lot of flexibility
80
+ # (see the documentation for current_model for details).
81
+ #
82
+ # Note that this is different for a singleton controller,
83
+ # where there's only one resource per parent resource.
84
+ # Then this just returns that resource.
85
+ # For example, if Person has_one Hat,
86
+ # then in HatsController current_object essentially runs <tt>Person.find(params[:person_id]).hat</tt>.
87
+ def current_object
88
+ @current_object ||= if !parent? || plural?
89
+ current_model.find(params[:id]) if params[:id]
90
+ else
91
+ parent_object.send(instance_variable_name.singularize)
92
+ end
93
+ end
94
+
95
+
96
+ # Calls current_object and stores
97
+ # the result in an instance variable
98
+ # named after the controller.
99
+ #
100
+ # This is called automatically by the default make_resourceful actions.
101
+ # You shouldn't need to use it directly unless you're creating a new action.
102
+ #
103
+ # For example, in UsersController,
104
+ # calling +load_object+ sets <tt>@user = current_object</tt>.
105
+ def load_object
106
+ instance_variable_set("@#{instance_variable_name.singularize}", current_object)
107
+ end
108
+
109
+ # Creates a new object of the type of the current model
110
+ # with the current object's parameters.
111
+ # +current_object+ then returns this object for this action
112
+ # instead of looking up a new object.
113
+ #
114
+ # This is called automatically by the default make_resourceful actions.
115
+ # You shouldn't need to use it directly unless you're creating a new action.
116
+ #
117
+ # Note that if a parent object exists,
118
+ # the newly created object will automatically be a child of the parent object.
119
+ # For example, on POST /people/4/things,
120
+ #
121
+ # build_object
122
+ # current_object.person.id #=> 4
123
+ #
124
+ def build_object
125
+ @current_object = if current_model.respond_to? :build
126
+ current_model.build(object_parameters)
127
+ else
128
+ current_model.new(object_parameters).tap do |obj|
129
+ if singular? && parent?
130
+ obj.send("#{parent_name}_id=", parent_object.id)
131
+ obj.send("#{parent_name}_type=", parent_object.class.to_s) if polymorphic_parent?
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def namespaced_model_name
138
+ [self.class.model_namespace, current_model_name].compact.join('::')
139
+ end
140
+
141
+ # The string name of the current model.
142
+ # By default, this is derived from the name of the controller.
143
+ def current_model_name
144
+ controller_name.singularize.camelize
145
+ end
146
+
147
+ # An array of namespaces under which the current controller is.
148
+ # For example, in Admin::Content::PagesController:
149
+ #
150
+ # namespaces #=> [:admin, :content]
151
+ #
152
+ def namespaces
153
+ @namespaces ||= self.class.name.split('::').slice(0...-1).map(&:underscore).map(&:to_sym)
154
+ end
155
+
156
+ # The name of the instance variable that load_object and load_objects should assign to.
157
+ def instance_variable_name
158
+ controller_name
159
+ end
160
+
161
+ # The class of the current model.
162
+ # Note that if a parent object exists,
163
+ # this instead returns the association object.
164
+ # For example, in HatsController where Person has_many :hats,
165
+ #
166
+ # current_model #=> Person.find(params[:person_id]).hats
167
+ #
168
+ # This is useful because the association object uses duck typing
169
+ # to act like a model class.
170
+ # It supplies a find method that's automatically scoped
171
+ # to ensure that the object returned is actually a child of the parent,
172
+ # and so forth.
173
+ def current_model
174
+ if !parent? || singular?
175
+ namespaced_model_name.constantize
176
+ else
177
+ parent_object.send(instance_variable_name)
178
+ end
179
+ end
180
+
181
+ # Returns the hash passed as HTTP parameters
182
+ # that defines the new (or updated) attributes
183
+ # of the current object.
184
+ # This is only meaningful for +create+ or +update+.
185
+ def object_parameters
186
+ params[namespaced_model_name.underscore.tr('/', '_')]
187
+ end
188
+
189
+ # Returns a list of the names of all the potential parents of the current model.
190
+ # For a non-nested controller, this is <tt>[]</tt>.
191
+ # For example, in HatsController where Rack has_many :hats and Person has_many :hats,
192
+ #
193
+ # parents #=> ["rack", "person"]
194
+ #
195
+ # Note that the parents must be declared via Builder#belongs_to.
196
+ def parent_names
197
+ self.class.parents
198
+ end
199
+
200
+ # Returns true if an appropriate parent id parameter has been supplied.
201
+ # For example, in HatsController where Rack has_many :hats and Person has_many :hats,
202
+ # if <tt>params[:rack_id]</tt> or <tt>params[:person_id]</tt> is given,
203
+ #
204
+ # parent? #=> true
205
+ #
206
+ # Otherwise, if both <tt>params[:rack_id]</tt> and <tt>params[:rack_id]</tt> are nil,
207
+ #
208
+ # parent? #=> false
209
+ #
210
+ # Note that parents must be declared via Builder#belongs_to.
211
+ def parent?
212
+ !!parent_name
213
+ end
214
+
215
+ # Returns true if no parent id parameter can be found _and_ a belongs_to
216
+ # relationship on this controller was declared with a parent for shallow
217
+ # routing.
218
+ def shallow?
219
+ self.class.shallow_parent &&
220
+ (parent_name.nil? || parent_name == self.class.shallow_parent)
221
+ end
222
+
223
+ # Returns whether the parent (if it exists) is polymorphic
224
+ def polymorphic_parent?
225
+ !!polymorphic_parent_name
226
+ end
227
+
228
+ # Returns the name of the current parent object if a parent id is given,
229
+ # or nil otherwise. For example, in HatsController where Rack has_many
230
+ # :hats and Person has_many :hats, if <tt>params[:rack_id]</tt> is
231
+ # given,
232
+ #
233
+ # parent_name #=> "rack"
234
+ #
235
+ # If <tt>params[:person_id]</tt> is given,
236
+ #
237
+ # parent_name #=> "person"
238
+ #
239
+ # If both <tt>params[:rack_id]</tt> and <tt>params[:person_id]</tt> are
240
+ # nil,
241
+ #
242
+ # parent_name #=> nil
243
+ #
244
+ # There are several things to note about this method. First,
245
+ # make_resourceful only supports single-level model nesting. Thus, if
246
+ # neither <tt>params[:rack_id]</tt> nor <tt>params[:rack_id]</tt> are
247
+ # nil, the return value of +parent_name+ is undefined.
248
+ #
249
+ # Second, don't use parent_name to check whether a parent id is given.
250
+ # It's better to use the more semantic parent? method.
251
+ #
252
+ # Third, parent_name caches its return value in the
253
+ # <tt>@parent_name</tt> variable, which you should keep in mind if
254
+ # you're overriding it. However, because <tt>@parent_name == nil</tt>
255
+ # could mean that there is no parent _or_ that the method hasn't been
256
+ # run yet, it uses <tt>defined?(@parent_name)</tt> to do the caching
257
+ # rather than <tt>@parent_name ||=</tt>. See the source code.
258
+ #
259
+ # Finally, note that parents must be declared via Builder#belongs_to.
260
+ #
261
+ # FIXME - Perhaps this logic should be moved to parent?() or another
262
+ # init method
263
+ def parent_name
264
+ return @parent_name if defined?(@parent_name)
265
+ @parent_name = parent_names.find { |name| params["#{name}_id"] }
266
+ if @parent_name.nil?
267
+ # get any polymorphic parents through :as association inspection
268
+ names = params.keys.inject({}) do |hsh, key|
269
+ hsh[key] = key.chomp("_id") if key.to_s =~ /_id$/
270
+ hsh
271
+ end
272
+ names.each do |key, name|
273
+ begin
274
+ klass = name.camelize.constantize
275
+ if association = klass.reflect_on_all_associations.detect { |association| association.options[:as] && parent_names.include?(association.options[:as].to_s) }
276
+ @parent_name = name
277
+ @polymorphic_parent_name = association.options[:as].to_s
278
+ @parent_class_name = name.camelize
279
+ @parent_object = klass.find(params[key])
280
+ break
281
+ end
282
+ rescue
283
+ end
284
+ end
285
+ else
286
+ @parent_class_name = params["#{parent_name}_type"]
287
+ @polymorphic_parent = !@parent_class_name.nil? # NEVER USED
288
+ end
289
+ @parent_name
290
+ end
291
+
292
+ def polymorphic_parent_name
293
+ @polymorphic_parent_name
294
+ end
295
+
296
+ # Returns the class name of the current parent.
297
+ # For example, in HatsController where Person has_many :hats,
298
+ # if <tt>params[:person_id]</tt> is given,
299
+ #
300
+ # parent_class_name #=> 'Person'
301
+ #
302
+ # Note that parents must be declared via Builder#belongs_to.
303
+ def parent_class_name
304
+ parent_name # to init @parent_class_name
305
+ @parent_class_name ||= parent_name.nil? ? nil : parent_name.camelize
306
+ end
307
+
308
+ # Returns the model class of the current parent.
309
+ # For example, in HatsController where Person has_many :hats,
310
+ # if <tt>params[:person_id]</tt> is given,
311
+ #
312
+ # parent_models #=> Person
313
+ #
314
+ # Note that parents must be declared via Builder#belongs_to.
315
+ def parent_model
316
+ parent_class_name.nil? ? nil : parent_class_name.constantize
317
+ end
318
+
319
+ # Returns the current parent object for the current object.
320
+ # For example, in HatsController where Person has_many :hats,
321
+ # if <tt>params[:person_id]</tt> is given,
322
+ #
323
+ # parent_object #=> Person.find(params[:person_id])
324
+ #
325
+ # Note that parents must be declared via Builder#belongs_to.
326
+ #
327
+ # Note also that the results of this method are cached
328
+ # so that multiple calls don't result in multiple SQL queries.
329
+ def parent_object
330
+ @parent_object ||= parent_model.nil? ? nil : parent_model.find(params["#{parent_name}_id"])
331
+ end
332
+
333
+ # Assigns the current parent object, as given by parent_objects,
334
+ # to its proper instance variable, as given by parent_name.
335
+ #
336
+ # This is automatically added as a before_filter.
337
+ # You shouldn't need to use it directly unless you're creating a new action.
338
+ def load_parent_object
339
+ instance_variable_set("@#{parent_name}", parent_object) if parent?
340
+ instance_variable_set("@#{polymorphic_parent_name}", parent_object) if polymorphic_parent?
341
+ end
342
+
343
+ # Renders a 422 error if no parent id is given.
344
+ # This is meant to be used with before_filter
345
+ # to ensure that some actions are only called with a parent id.
346
+ # For example:
347
+ #
348
+ # before_filter :ensure_parent_exists, :only => [:create, :update]
349
+ #
350
+ def ensure_parent_exists
351
+ return true if parent?
352
+ render :text => 'No parent id given', :status => 422
353
+ return false
354
+ end
355
+
356
+ # Returns whether or not the database update in the +create+, +update+, and +destroy+
357
+ # was completed successfully.
358
+ def save_succeeded?
359
+ @save_succeeded
360
+ end
361
+
362
+ # Declares that the current databse update was completed successfully.
363
+ # Causes subsequent calls to <tt>save_succeeded?</tt> to return +true+.
364
+ #
365
+ # This is mostly meant to be used by the default actions,
366
+ # but it can be used by user-defined actions as well.
367
+ def save_succeeded!
368
+ @save_succeeded = true
369
+ end
370
+
371
+ # Declares that the current databse update was not completed successfully.
372
+ # Causes subsequent calls to <tt>save_succeeded?</tt> to return +false+.
373
+ #
374
+ # This is mostly meant to be used by the default actions,
375
+ # but it can be used by user-defined actions as well.
376
+ def save_failed!
377
+ @save_succeeded = false
378
+ end
379
+
380
+ # Returns whether or not the current action acts upon multiple objects.
381
+ # By default, the only such action is +index+.
382
+ def plural_action?
383
+ PLURAL_ACTIONS.include?(params[:action].to_sym)
384
+ end
385
+
386
+ # Returns whether or not the current action acts upon a single object.
387
+ # By default, this is the case for all actions but +index+.
388
+ def singular_action?
389
+ !plural_action?
390
+ end
391
+
392
+ # Returns whether the controller is a singleton,
393
+ # implying that there is only one such resource for each parent resource.
394
+ #
395
+ # Note that the way this is determined is based on the singularity of the controller name,
396
+ # so it may yield false positives for oddly-named controllers and need to be overridden.
397
+ #
398
+ # TODO: maybe we can define plural? and singular? as class_methods,
399
+ # so they are not visible to the world
400
+ def singular?
401
+ instance_variable_name.singularize == instance_variable_name
402
+ end
403
+
404
+ # Returns whether the controller is a normal plural controller,
405
+ # implying that there are multiple resources for each parent resource.
406
+ #
407
+ # Note that the way this is determined is based on the singularity of the controller name,
408
+ # so it may yield false negatives for oddly-named controllers.
409
+ # If this is the case, the singular? method should be overridden.
410
+ #
411
+ # TODO: maybe we can define plural? and singular? as class_methods,
412
+ # so they are not visible to the world
413
+ def plural?
414
+ !singular?
415
+ end
416
+ end
417
+ end
418
+ end
@@ -0,0 +1,101 @@
1
+ module Resourceful
2
+ module Default
3
+ # Contains the definitions of the default resourceful actions.
4
+ # These are made available with the Builder#actions method.
5
+ #
6
+ # These methods are very compact,
7
+ # so the best way to understand them is just to look at their source.
8
+ # Check out Resourceful::Accessors and Resourceful::Callbacks
9
+ # for the documentation of the methods called within the actions.
10
+ #
11
+ # Along with each action is listed the RESTful method
12
+ # which corresponds to the action.
13
+ # The controller in the examples is FoosController,
14
+ # and the id for single-object actions is 12.
15
+ module Actions
16
+ # GET /foos
17
+ def index
18
+ #load_objects
19
+ before :index
20
+ response_for :index
21
+ end
22
+
23
+ # GET /foos/12
24
+ def show
25
+ # NOTE - Moved this call to a more generic place
26
+ #load_object
27
+ before :show
28
+ response_for :show
29
+ rescue
30
+ response_for :show_fails
31
+ end
32
+
33
+ # POST /foos
34
+ def create
35
+ build_object
36
+ load_object
37
+ before :create
38
+ if current_object.save
39
+ save_succeeded!
40
+ after :create
41
+ response_for :create
42
+ else
43
+ save_failed!
44
+ after :create_fails
45
+ response_for :create_fails
46
+ end
47
+ end
48
+
49
+ # PUT /foos/12
50
+ def update
51
+ #load_object
52
+ before :update
53
+
54
+ begin
55
+ result = current_object.update_attributes object_parameters
56
+ rescue ActiveRecord::StaleObjectError
57
+ current_object.reload
58
+ result = false
59
+ end
60
+
61
+ if result
62
+ save_succeeded!
63
+ after :update
64
+ response_for :update
65
+ else
66
+ save_failed!
67
+ after :update_fails
68
+ response_for :update_fails
69
+ end
70
+ end
71
+
72
+ # GET /foos/new
73
+ def new
74
+ build_object
75
+ load_object
76
+ before :new
77
+ response_for :new
78
+ end
79
+
80
+ # GET /foos/12/edit
81
+ def edit
82
+ #load_object
83
+ before :edit
84
+ response_for :edit
85
+ end
86
+
87
+ # DELETE /foos/12
88
+ def destroy
89
+ #load_object
90
+ before :destroy
91
+ if current_object.destroy
92
+ after :destroy
93
+ response_for :destroy
94
+ else
95
+ after :destroy_fails
96
+ response_for :destroy_fails
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,51 @@
1
+ require 'resourceful/builder'
2
+
3
+ module Resourceful
4
+ module Default
5
+ # This module is mostly meant to be used by the make_resourceful default actions.
6
+ # It provides various methods that declare where callbacks set in the +make_resourceful+ block,
7
+ # like Builder#before and Builder#response_for,
8
+ # should be called.
9
+ module Callbacks
10
+ # Calls any +before+ callbacks set in the +make_resourceful+ block for the given event.
11
+ def before(event)
12
+ resourceful_fire(:before, event.to_sym)
13
+ end
14
+
15
+ # Calls any +after+ callbacks set in the +make_resourceful+ block for the given event.
16
+ def after(event)
17
+ resourceful_fire(:after, event.to_sym)
18
+ end
19
+
20
+ # Calls any +response_for+ callbacks set in the +make_resourceful+ block for the given event.
21
+ # Note that these aren't called directly,
22
+ # but instead passed along to Rails' respond_to method.
23
+ def response_for(event)
24
+ if responses = self.class.resourceful_responses[event.to_sym]
25
+ respond_to do |format|
26
+ responses.each do |key, value|
27
+ format.send(key, &scope(value))
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ # Returns a block identical to the given block,
34
+ # but in the context of the current controller.
35
+ # The returned block accepts no arguments,
36
+ # even if the given block accepted them.
37
+ def scope(block)
38
+ proc do
39
+ instance_eval(&(block || proc {}))
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def resourceful_fire(type, name)
46
+ callbacks = self.class.resourceful_callbacks[type][name] || []
47
+ callbacks.each { |callback| scope(callback).call }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,118 @@
1
+ module Resourceful
2
+ module Default
3
+ module Responses
4
+ # Sets the default flash message.
5
+ # This message can be overridden by passing in
6
+ # an HTTP parameter of the form "_flash[type]" via POST or GET.
7
+ #
8
+ # You can use this to easily have multiple forms
9
+ # post to the same create/edit/destroy actions
10
+ # but display different flash notices -
11
+ # without modifying the controller code at all.
12
+ #
13
+ # By default, the flash types are +notice+ when the database operation completes successfully
14
+ # and +error+ when it fails.
15
+ #
16
+ #--
17
+ # TODO: Move this out of here
18
+ #++
19
+ def set_default_flash(type, message)
20
+ flash[type] ||= (params[:_flash] && params[:_flash][type]) || message
21
+ end
22
+
23
+ # Sets the default redirect
24
+ # (the argument passed to +redirect_to+).
25
+ # This message can be overridden by passing in
26
+ # an HTTP parameter of the form "_redirect_on[status]" via POST or GET.
27
+ #
28
+ # You can use this to easily have multiple forms
29
+ # post to the same create/edit/destroy actions
30
+ # but redirect to different URLs -
31
+ # without modifying the controller code at all.
32
+ #
33
+ # By default, the redirect statuses are +success+ when the database operation completes successfully
34
+ # and +failure+ when it fails.
35
+ # Use the <tt>:status</tt> option to specify which status to run the redirect for.
36
+ # For example:
37
+ #
38
+ # set_default_redirect "/posts", :status => :failure
39
+ #
40
+ # This will run <tt>redirect_to params[:_redirect_on][:failure]</tt> if the parameter exists,
41
+ # or <tt>redirect_to "/posts"</tt> otherwise.
42
+ #
43
+ #--
44
+ # TODO: Move this out of here
45
+ #++
46
+ def set_default_redirect(to, options = {})
47
+ status = options[:status] || :success
48
+ redirect_to (params[:_redirect_on] && params[:_redirect_on][status]) || to
49
+ end
50
+
51
+ # This method is automatically run when this module is included in Resourceful::Base.
52
+ # It sets up the default responses for the default actions.
53
+ def self.included(base)
54
+ base.made_resourceful do
55
+ response_for(:show, :index, :edit, :new) do |format|
56
+ format.html
57
+ format.js
58
+ end
59
+
60
+ response_for(:show_fails) do |format|
61
+ not_found = Proc.new { render :text => I18n.t('make_resourceful.show.fails', :default => "No item found"), :status => 404 }
62
+ format.html &not_found
63
+ format.js &not_found
64
+ format.xml &not_found
65
+ end
66
+
67
+ response_for(:create) do |format|
68
+ format.html do
69
+ set_default_flash :notice, I18n.t('make_resourceful.create.success', :default => "Create successful!")
70
+ set_default_redirect object_path
71
+ end
72
+ format.js
73
+ end
74
+
75
+ response_for(:create_fails) do |format|
76
+ format.html do
77
+ set_default_flash :error, I18n.t('make_resourceful.create.fails', :default => "There was a problem!")
78
+ render :action => :new, :status => 422
79
+ end
80
+ format.js
81
+ end
82
+
83
+ response_for(:update) do |format|
84
+ format.html do
85
+ set_default_flash :notice, I18n.t('make_resourceful.update.success', :default => "Save successful!")
86
+ set_default_redirect object_path
87
+ end
88
+ format.js
89
+ end
90
+
91
+ response_for(:update_fails) do |format|
92
+ format.html do
93
+ set_default_flash :error, I18n.t('make_resourceful.update.fails', :default => "There was a problem saving!")
94
+ render :action => :edit, :status => 422
95
+ end
96
+ format.js
97
+ end
98
+
99
+ response_for(:destroy) do |format|
100
+ format.html do
101
+ set_default_flash :notice, I18n.t('make_resourceful.destroy.success', :default => "Record deleted!")
102
+ set_default_redirect objects_path
103
+ end
104
+ format.js
105
+ end
106
+
107
+ response_for(:destroy_fails) do |format|
108
+ format.html do
109
+ set_default_flash :error, I18n.t('make_resourceful.destroy.fails', :default => "There was a problem deleting!")
110
+ set_default_redirect :back, :status => :failure
111
+ end
112
+ format.js
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end