dkubb-resource_controller 0.6.5

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 (233) hide show
  1. data/LICENSE +22 -0
  2. data/README.rdoc +330 -0
  3. data/VERSION.yml +4 -0
  4. data/generators/scaffold_resource/USAGE +29 -0
  5. data/generators/scaffold_resource/scaffold_resource_generator.rb +179 -0
  6. data/generators/scaffold_resource/templates/controller.rb +2 -0
  7. data/generators/scaffold_resource/templates/fixtures.yml +10 -0
  8. data/generators/scaffold_resource/templates/functional_test.rb +57 -0
  9. data/generators/scaffold_resource/templates/helper.rb +2 -0
  10. data/generators/scaffold_resource/templates/migration.rb +15 -0
  11. data/generators/scaffold_resource/templates/model.rb +2 -0
  12. data/generators/scaffold_resource/templates/old_migration.rb +13 -0
  13. data/generators/scaffold_resource/templates/rspec/functional_spec.rb +255 -0
  14. data/generators/scaffold_resource/templates/rspec/helper_spec.rb +11 -0
  15. data/generators/scaffold_resource/templates/rspec/routing_spec.rb +61 -0
  16. data/generators/scaffold_resource/templates/rspec/unit_spec.rb +11 -0
  17. data/generators/scaffold_resource/templates/rspec/views/edit_spec.rb +28 -0
  18. data/generators/scaffold_resource/templates/rspec/views/index_spec.rb +26 -0
  19. data/generators/scaffold_resource/templates/rspec/views/new_spec.rb +30 -0
  20. data/generators/scaffold_resource/templates/rspec/views/show_spec.rb +25 -0
  21. data/generators/scaffold_resource/templates/shoulda_functional_test.rb +19 -0
  22. data/generators/scaffold_resource/templates/unit_test.rb +7 -0
  23. data/generators/scaffold_resource/templates/view__form.erb +6 -0
  24. data/generators/scaffold_resource/templates/view__form.haml +5 -0
  25. data/generators/scaffold_resource/templates/view_edit.erb +16 -0
  26. data/generators/scaffold_resource/templates/view_edit.haml +11 -0
  27. data/generators/scaffold_resource/templates/view_index.erb +22 -0
  28. data/generators/scaffold_resource/templates/view_index.haml +19 -0
  29. data/generators/scaffold_resource/templates/view_new.erb +12 -0
  30. data/generators/scaffold_resource/templates/view_new.haml +9 -0
  31. data/generators/scaffold_resource/templates/view_show.erb +9 -0
  32. data/generators/scaffold_resource/templates/view_show.haml +9 -0
  33. data/lib/resource_controller.rb +26 -0
  34. data/lib/resource_controller/accessors.rb +77 -0
  35. data/lib/resource_controller/action_options.rb +40 -0
  36. data/lib/resource_controller/actions.rb +75 -0
  37. data/lib/resource_controller/base.rb +15 -0
  38. data/lib/resource_controller/class_methods.rb +24 -0
  39. data/lib/resource_controller/controller.rb +70 -0
  40. data/lib/resource_controller/failable_action_options.rb +25 -0
  41. data/lib/resource_controller/helpers.rb +28 -0
  42. data/lib/resource_controller/helpers/current_objects.rb +73 -0
  43. data/lib/resource_controller/helpers/internal.rb +80 -0
  44. data/lib/resource_controller/helpers/nested.rb +67 -0
  45. data/lib/resource_controller/helpers/singleton_customizations.rb +64 -0
  46. data/lib/resource_controller/helpers/urls.rb +132 -0
  47. data/lib/resource_controller/response_collector.rb +27 -0
  48. data/lib/resource_controller/singleton.rb +15 -0
  49. data/lib/urligence.rb +50 -0
  50. data/rails/init.rb +6 -0
  51. data/test/Rakefile +10 -0
  52. data/test/app/controllers/accounts_controller.rb +6 -0
  53. data/test/app/controllers/application_controller.rb +7 -0
  54. data/test/app/controllers/cms/options_controller.rb +3 -0
  55. data/test/app/controllers/cms/personnel_controller.rb +2 -0
  56. data/test/app/controllers/cms/photos_controller.rb +6 -0
  57. data/test/app/controllers/cms/products_controller.rb +3 -0
  58. data/test/app/controllers/comments_controller.rb +3 -0
  59. data/test/app/controllers/images_controller.rb +4 -0
  60. data/test/app/controllers/options_controller.rb +8 -0
  61. data/test/app/controllers/people_controller.rb +9 -0
  62. data/test/app/controllers/photos_controller.rb +12 -0
  63. data/test/app/controllers/posts_controller.rb +10 -0
  64. data/test/app/controllers/projects_controller.rb +3 -0
  65. data/test/app/controllers/somethings_controller.rb +3 -0
  66. data/test/app/controllers/tags_controller.rb +13 -0
  67. data/test/app/controllers/users_controller.rb +12 -0
  68. data/test/app/helpers/accounts_helper.rb +2 -0
  69. data/test/app/helpers/application_helper.rb +3 -0
  70. data/test/app/helpers/cms/products_helper.rb +2 -0
  71. data/test/app/helpers/comments_helper.rb +2 -0
  72. data/test/app/helpers/images_helper.rb +2 -0
  73. data/test/app/helpers/options_helper.rb +2 -0
  74. data/test/app/helpers/people_helper.rb +2 -0
  75. data/test/app/helpers/photos_helper.rb +2 -0
  76. data/test/app/helpers/posts_helper.rb +2 -0
  77. data/test/app/helpers/projects_helper.rb +2 -0
  78. data/test/app/helpers/somethings_helper.rb +2 -0
  79. data/test/app/helpers/tags_helper.rb +2 -0
  80. data/test/app/helpers/users_helper.rb +2 -0
  81. data/test/app/models/account.rb +4 -0
  82. data/test/app/models/comment.rb +3 -0
  83. data/test/app/models/image.rb +3 -0
  84. data/test/app/models/option.rb +3 -0
  85. data/test/app/models/personnel.rb +3 -0
  86. data/test/app/models/photo.rb +5 -0
  87. data/test/app/models/post.rb +3 -0
  88. data/test/app/models/product.rb +3 -0
  89. data/test/app/models/project.rb +2 -0
  90. data/test/app/models/something.rb +2 -0
  91. data/test/app/models/tag.rb +3 -0
  92. data/test/app/models/user.rb +3 -0
  93. data/test/app/views/accounts/_form.html.erb +4 -0
  94. data/test/app/views/accounts/edit.html.erb +14 -0
  95. data/test/app/views/accounts/new.html.erb +12 -0
  96. data/test/app/views/accounts/show.html.erb +5 -0
  97. data/test/app/views/cms/options/edit.rhtml +17 -0
  98. data/test/app/views/cms/options/index.rhtml +20 -0
  99. data/test/app/views/cms/options/new.rhtml +16 -0
  100. data/test/app/views/cms/options/show.rhtml +8 -0
  101. data/test/app/views/cms/photos/edit.rhtml +17 -0
  102. data/test/app/views/cms/photos/index.rhtml +20 -0
  103. data/test/app/views/cms/photos/new.rhtml +16 -0
  104. data/test/app/views/cms/photos/show.rhtml +8 -0
  105. data/test/app/views/cms/products/edit.rhtml +17 -0
  106. data/test/app/views/cms/products/index.rhtml +20 -0
  107. data/test/app/views/cms/products/new.rhtml +16 -0
  108. data/test/app/views/cms/products/show.rhtml +8 -0
  109. data/test/app/views/comments/edit.rhtml +27 -0
  110. data/test/app/views/comments/index.rhtml +24 -0
  111. data/test/app/views/comments/new.rhtml +26 -0
  112. data/test/app/views/comments/show.rhtml +18 -0
  113. data/test/app/views/images/_form.html.erb +4 -0
  114. data/test/app/views/images/edit.html.erb +14 -0
  115. data/test/app/views/images/new.html.erb +12 -0
  116. data/test/app/views/layouts/application.rhtml +17 -0
  117. data/test/app/views/layouts/comments.rhtml +17 -0
  118. data/test/app/views/layouts/options.rhtml +17 -0
  119. data/test/app/views/layouts/people.rhtml +17 -0
  120. data/test/app/views/layouts/photos.rhtml +17 -0
  121. data/test/app/views/layouts/projects.rhtml +17 -0
  122. data/test/app/views/layouts/somethings.rhtml +17 -0
  123. data/test/app/views/layouts/tags.rhtml +17 -0
  124. data/test/app/views/options/_form.html.erb +8 -0
  125. data/test/app/views/options/edit.html.erb +16 -0
  126. data/test/app/views/options/index.html.erb +21 -0
  127. data/test/app/views/options/new.html.erb +12 -0
  128. data/test/app/views/options/show.html.erb +10 -0
  129. data/test/app/views/people/edit.rhtml +17 -0
  130. data/test/app/views/people/index.rhtml +20 -0
  131. data/test/app/views/people/new.rhtml +16 -0
  132. data/test/app/views/people/show.rhtml +8 -0
  133. data/test/app/views/photos/edit.rhtml +17 -0
  134. data/test/app/views/photos/index.rhtml +20 -0
  135. data/test/app/views/photos/new.rhtml +16 -0
  136. data/test/app/views/photos/show.rhtml +8 -0
  137. data/test/app/views/posts/edit.rhtml +22 -0
  138. data/test/app/views/posts/index.rhtml +22 -0
  139. data/test/app/views/posts/new.rhtml +21 -0
  140. data/test/app/views/posts/show.rhtml +13 -0
  141. data/test/app/views/projects/edit.rhtml +17 -0
  142. data/test/app/views/projects/index.rhtml +20 -0
  143. data/test/app/views/projects/new.rhtml +16 -0
  144. data/test/app/views/projects/show.rhtml +8 -0
  145. data/test/app/views/somethings/edit.rhtml +17 -0
  146. data/test/app/views/somethings/index.rhtml +20 -0
  147. data/test/app/views/somethings/new.rhtml +16 -0
  148. data/test/app/views/somethings/show.rhtml +8 -0
  149. data/test/app/views/tags/edit.rhtml +17 -0
  150. data/test/app/views/tags/index.rhtml +20 -0
  151. data/test/app/views/tags/index.rjs +0 -0
  152. data/test/app/views/tags/new.rhtml +16 -0
  153. data/test/app/views/tags/show.rhtml +8 -0
  154. data/test/app/views/users/edit.rhtml +17 -0
  155. data/test/app/views/users/index.rhtml +20 -0
  156. data/test/app/views/users/new.rhtml +16 -0
  157. data/test/app/views/users/show.rhtml +8 -0
  158. data/test/config/boot.rb +110 -0
  159. data/test/config/database.yml +9 -0
  160. data/test/config/environment.rb +49 -0
  161. data/test/config/environments/development.rb +20 -0
  162. data/test/config/environments/test.rb +19 -0
  163. data/test/config/initializers/inflections.rb +14 -0
  164. data/test/config/routes.rb +61 -0
  165. data/test/db/migrate/001_create_posts.rb +12 -0
  166. data/test/db/migrate/002_create_products.rb +11 -0
  167. data/test/db/migrate/003_create_comments.rb +13 -0
  168. data/test/db/migrate/004_create_options.rb +13 -0
  169. data/test/db/migrate/005_create_photos.rb +11 -0
  170. data/test/db/migrate/006_create_tags.rb +17 -0
  171. data/test/db/migrate/007_create_somethings.rb +11 -0
  172. data/test/db/migrate/008_create_accounts.rb +11 -0
  173. data/test/db/migrate/009_add_account_id_to_photos.rb +9 -0
  174. data/test/db/migrate/010_create_projects.rb +11 -0
  175. data/test/db/migrate/011_create_images.rb +12 -0
  176. data/test/db/migrate/012_create_users.rb +11 -0
  177. data/test/db/migrate/013_create_personnel.rb +11 -0
  178. data/test/db/migrate/014_add_personnel_id_to_photos.rb +9 -0
  179. data/test/db/schema.rb +78 -0
  180. data/test/script/console +3 -0
  181. data/test/script/destroy +3 -0
  182. data/test/script/generate +3 -0
  183. data/test/script/server +3 -0
  184. data/test/test/fixtures/accounts.yml +7 -0
  185. data/test/test/fixtures/comments.yml +11 -0
  186. data/test/test/fixtures/images.yml +6 -0
  187. data/test/test/fixtures/options.yml +9 -0
  188. data/test/test/fixtures/personnel.yml +5 -0
  189. data/test/test/fixtures/photos.yml +9 -0
  190. data/test/test/fixtures/photos_tags.yml +3 -0
  191. data/test/test/fixtures/posts.yml +9 -0
  192. data/test/test/fixtures/products.yml +7 -0
  193. data/test/test/fixtures/projects.yml +7 -0
  194. data/test/test/fixtures/somethings.yml +7 -0
  195. data/test/test/fixtures/tags.yml +7 -0
  196. data/test/test/fixtures/users.yml +5 -0
  197. data/test/test/functional/cms/options_controller_test.rb +23 -0
  198. data/test/test/functional/cms/photos_controller_test.rb +43 -0
  199. data/test/test/functional/cms/products_controller_test.rb +23 -0
  200. data/test/test/functional/comments_controller_test.rb +26 -0
  201. data/test/test/functional/images_controller_test.rb +37 -0
  202. data/test/test/functional/people_controller_test.rb +34 -0
  203. data/test/test/functional/photos_controller_test.rb +130 -0
  204. data/test/test/functional/posts_controller_test.rb +34 -0
  205. data/test/test/functional/projects_controller_test.rb +28 -0
  206. data/test/test/functional/somethings_controller_test.rb +28 -0
  207. data/test/test/functional/tags_controller_test.rb +64 -0
  208. data/test/test/functional/users_controller_test.rb +24 -0
  209. data/test/test/test_helper.rb +13 -0
  210. data/test/test/unit/accessors_test.rb +110 -0
  211. data/test/test/unit/account_test.rb +7 -0
  212. data/test/test/unit/action_options_test.rb +109 -0
  213. data/test/test/unit/base_test.rb +11 -0
  214. data/test/test/unit/comment_test.rb +10 -0
  215. data/test/test/unit/failable_action_options_test.rb +77 -0
  216. data/test/test/unit/helpers/current_objects_test.rb +133 -0
  217. data/test/test/unit/helpers/internal_test.rb +106 -0
  218. data/test/test/unit/helpers/nested_test.rb +86 -0
  219. data/test/test/unit/helpers/singleton_current_objects_test.rb +68 -0
  220. data/test/test/unit/helpers/singleton_nested_test.rb +77 -0
  221. data/test/test/unit/helpers/singleton_urls_test.rb +67 -0
  222. data/test/test/unit/helpers/urls_test.rb +75 -0
  223. data/test/test/unit/helpers_test.rb +25 -0
  224. data/test/test/unit/image_test.rb +7 -0
  225. data/test/test/unit/option_test.rb +10 -0
  226. data/test/test/unit/photo_test.rb +10 -0
  227. data/test/test/unit/post_test.rb +10 -0
  228. data/test/test/unit/project_test.rb +10 -0
  229. data/test/test/unit/response_collector_test.rb +49 -0
  230. data/test/test/unit/something_test.rb +10 -0
  231. data/test/test/unit/tag_test.rb +10 -0
  232. data/test/test/unit/urligence_test.rb +203 -0
  233. metadata +332 -0
@@ -0,0 +1,15 @@
1
+ module ResourceController
2
+
3
+ # == ResourceController::Base
4
+ #
5
+ # Inherit from this class to create your RESTful controller. See the README for usage.
6
+ #
7
+ class Base < ::ApplicationController
8
+ unloadable
9
+
10
+ def self.inherited(subclass)
11
+ super
12
+ subclass.class_eval { resource_controller }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module ResourceController
2
+ module ClassMethods
3
+
4
+ # Use this method in your controller to specify which actions you'd like it to respond to.
5
+ #
6
+ # class PostsController < ResourceController::Base
7
+ # actions :all, :except => :create
8
+ # end
9
+ def actions(*opts)
10
+ config = {}
11
+ config.merge!(opts.pop) if opts.last.is_a?(Hash)
12
+
13
+ all_actions = (singleton? ? ResourceController::SINGLETON_ACTIONS : ResourceController::ACTIONS) - [:new_action] + [:new]
14
+
15
+ actions_to_remove = []
16
+ actions_to_remove += all_actions - opts unless opts.first == :all
17
+ actions_to_remove += [*config[:except]] if config[:except]
18
+ actions_to_remove.uniq!
19
+
20
+ actions_to_remove.each { |action| undef_method(action) if method_defined?(action) }
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ module ResourceController
2
+ module Controller
3
+ def self.included(subclass)
4
+ subclass.class_eval do
5
+ include ResourceController::Helpers
6
+ include ResourceController::Actions
7
+ extend ResourceController::Accessors
8
+ extend ResourceController::ClassMethods
9
+
10
+ class_reader_writer :belongs_to, *NAME_ACCESSORS
11
+ NAME_ACCESSORS.each { |accessor| send(accessor, controller_name.singularize.underscore) }
12
+
13
+ ACTIONS.each do |action|
14
+ class_scoping_reader action, FAILABLE_ACTIONS.include?(action) ? ResourceController::FailableActionOptions.new : ResourceController::ActionOptions.new
15
+ end
16
+
17
+ self.helper_method :object_url, :edit_object_url, :new_object_url, :collection_url, :object, :collection,
18
+ :parent, :parent_type, :parent_object, :parent_model, :model_name, :model, :object_path,
19
+ :edit_object_path, :new_object_path, :collection_path, :hash_for_collection_path, :hash_for_object_path,
20
+ :hash_for_edit_object_path, :hash_for_new_object_path, :hash_for_collection_url,
21
+ :hash_for_object_url, :hash_for_edit_object_url, :hash_for_new_object_url, :parent?,
22
+ :collection_url_options, :object_url_options, :new_object_url_options
23
+
24
+ end
25
+
26
+ init_default_actions(subclass)
27
+ end
28
+
29
+ private
30
+ def self.init_default_actions(klass)
31
+ klass.class_eval do
32
+ index.wants.html
33
+ edit.wants.html
34
+ new_action.wants.html
35
+
36
+ show do
37
+ wants.html
38
+
39
+ failure.wants.html { render :text => "Member object not found." }
40
+ end
41
+
42
+ create do
43
+ flash "Successfully created!"
44
+ wants.html { redirect_to object_url }
45
+
46
+ failure.wants.html { render :action => "new" }
47
+ end
48
+
49
+ update do
50
+ flash "Successfully updated!"
51
+ wants.html { redirect_to object_url }
52
+
53
+ failure.wants.html { render :action => "edit" }
54
+ end
55
+
56
+ destroy do
57
+ flash "Successfully removed!"
58
+ wants.html { redirect_to collection_url }
59
+ failure.wants.html { redirect_to object_url }
60
+ end
61
+
62
+ class << self
63
+ def singleton?
64
+ false
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,25 @@
1
+ module ResourceController
2
+ class FailableActionOptions
3
+ extend ResourceController::Accessors
4
+
5
+ scoping_reader :success, :fails
6
+ alias_method :failure, :fails
7
+
8
+ block_accessor :before
9
+
10
+ def initialize
11
+ @success = ActionOptions.new
12
+ @fails = ActionOptions.new
13
+ end
14
+
15
+ delegate :flash, :flash_now, :after, :response, :wants, :to => :success
16
+
17
+ def dup
18
+ returning self.class.new do |duplicate|
19
+ duplicate.instance_variable_set(:@success, success.dup)
20
+ duplicate.instance_variable_set(:@fails, fails.dup)
21
+ duplicate.instance_variable_set(:@before, before.dup) unless before.nil?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module ResourceController
2
+ # == ResourceController::Helpers
3
+ #
4
+ # Included in Base.
5
+ #
6
+ # These helpers are used internally to manage objects, generate urls, and manage parent resource associations.
7
+ #
8
+ # If you want to customize certain controller behaviour, like member-object, and collection fetching, overriding these methods is all it takes.
9
+ #
10
+ # See the docs below, and the README for examples
11
+ #
12
+ # *Please Note: many of these helpers build on top of each other, and require that behaviour to be maintained, in order for other functionality to work properly.*
13
+ #
14
+ # e.g. All fetching must be done on top of the method end_of_association_chain, or else parent resources (including polymorphic ones) won't function correctly.
15
+ #
16
+ # class PostsController < ResourceController::Base
17
+ # private
18
+ # def object
19
+ # @object ||= end_of_association_chain.find_by_permalink(param)
20
+ # end
21
+ # end
22
+ module Helpers
23
+ include ResourceController::Helpers::Urls
24
+ include ResourceController::Helpers::Internal
25
+ include ResourceController::Helpers::Nested
26
+ include ResourceController::Helpers::CurrentObjects
27
+ end
28
+ end
@@ -0,0 +1,73 @@
1
+ module ResourceController
2
+ module Helpers
3
+ module CurrentObjects
4
+ protected
5
+ # Used internally to return the model for your resource.
6
+ #
7
+ def model
8
+ model_name.to_s.camelize.constantize
9
+ end
10
+
11
+
12
+ # Used to fetch the collection for the index method
13
+ #
14
+ # In order to customize the way the collection is fetched, to add something like pagination, for example, override this method.
15
+ #
16
+ def collection
17
+ end_of_association_chain.all
18
+ end
19
+
20
+ # Returns the current param.
21
+ #
22
+ # Defaults to params[:id].
23
+ #
24
+ # Override this method if you'd like to use an alternate param name.
25
+ #
26
+ def param
27
+ params[:id]
28
+ end
29
+
30
+ # Used to fetch the current member object in all of the singular methods that operate on an existing member.
31
+ #
32
+ # Override this method if you'd like to fetch your objects in some alternate way, like using a permalink.
33
+ #
34
+ # class PostsController < ResourceController::Base
35
+ # private
36
+ # def object
37
+ # @object ||= end_of_association_chain.find_by_permalink(param)
38
+ # end
39
+ # end
40
+ #
41
+ def object
42
+ @object ||= end_of_association_chain.get!(param) unless param.nil?
43
+ @object
44
+ end
45
+
46
+ # Used internally to load the member object in to an instance variable @#{model_name} (i.e. @post)
47
+ #
48
+ def load_object
49
+ instance_variable_set "@#{parent_type}", parent_object if parent?
50
+ instance_variable_set "@#{object_name}", object
51
+ end
52
+
53
+ # Used internally to load the collection in to an instance variable @#{model_name.pluralize} (i.e. @posts)
54
+ #
55
+ def load_collection
56
+ instance_variable_set "@#{parent_type}", parent_object if parent?
57
+ instance_variable_set "@#{object_name.to_s.pluralize}", collection
58
+ end
59
+
60
+ # Returns the form params. Defaults to params[model_name] (i.e. params["post"])
61
+ #
62
+ def object_params
63
+ params["#{object_name}"]
64
+ end
65
+
66
+ # Builds the object, but doesn't save it, during the new, and create action.
67
+ #
68
+ def build_object
69
+ @object ||= end_of_association_chain.new object_params
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,80 @@
1
+ # Internal action lifecycle management.
2
+ #
3
+ # All of these methods are used internally to execute the options, set by the user in ActionOptions and FailableActionOptions
4
+ #
5
+ module ResourceController
6
+ module Helpers
7
+ module Internal
8
+ protected
9
+ # Used to actually pass the responses along to the controller's respond_to method.
10
+ #
11
+ def response_for(action)
12
+ respond_to do |wants|
13
+ options_for(action).response.each do |method, block|
14
+ if block.nil?
15
+ wants.send(method)
16
+ else
17
+ wants.send(method) { instance_eval(&block) }
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # Calls the after callbacks for the action, if one is present.
24
+ #
25
+ def after(action)
26
+ invoke_callbacks *options_for(action).after
27
+ end
28
+
29
+ # Calls the before block for the action, if one is present.
30
+ #
31
+ def before(action)
32
+ invoke_callbacks *self.class.send(action).before
33
+ end
34
+
35
+ # Sets the flash and flash_now for the action, if it is present.
36
+ #
37
+ def set_flash(action)
38
+ set_normal_flash(action)
39
+ set_flash_now(action)
40
+ end
41
+
42
+ # Sets the regular flash (i.e. flash[:notice] = '...')
43
+ #
44
+ def set_normal_flash(action)
45
+ if f = options_for(action).flash
46
+ flash[:notice] = f.is_a?(Proc) ? instance_eval(&f) : options_for(action).flash
47
+ end
48
+ end
49
+
50
+ # Sets the flash.now (i.e. flash.now[:notice] = '...')
51
+ #
52
+ def set_flash_now(action)
53
+ if f = options_for(action).flash_now
54
+ flash.now[:notice] = f.is_a?(Proc) ? instance_eval(&f) : options_for(action).flash_now
55
+ end
56
+ end
57
+
58
+ # Returns the options for an action, which is a symbol.
59
+ #
60
+ # Manages splitting things like :create_fails.
61
+ #
62
+ def options_for(action)
63
+ action = action == :new_action ? [action] : "#{action}".split('_').map(&:to_sym)
64
+ options = self.class.send(action.first)
65
+ options = options.send(action.last == :fails ? :fails : :success) if ResourceController::FAILABLE_ACTIONS.include? action.first
66
+
67
+ options
68
+ end
69
+
70
+ def invoke_callbacks(*callbacks)
71
+ unless callbacks.empty?
72
+ callbacks.select { |callback| callback.is_a? Symbol }.each { |symbol| send(symbol) }
73
+
74
+ block = callbacks.detect { |callback| callback.is_a? Proc }
75
+ instance_eval &block unless block.nil?
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,67 @@
1
+ # Nested and Polymorphic Resource Helpers
2
+ #
3
+ module ResourceController
4
+ module Helpers
5
+ module Nested
6
+ protected
7
+ # Returns the relevant association proxy of the parent. (i.e. /posts/1/comments # => @post.comments)
8
+ #
9
+ def parent_association
10
+ @parent_association ||= parent_object.send(model_name.to_s.pluralize.to_sym)
11
+ end
12
+
13
+ # Returns the type of the current parent
14
+ #
15
+ def parent_type
16
+ @parent_type ||= parent_type_from_params || parent_type_from_request
17
+ end
18
+
19
+ # Returns the type of the current parent extracted from params
20
+ #
21
+ def parent_type_from_params
22
+ [*belongs_to].find { |parent| !params["#{parent}_id".to_sym].nil? }
23
+ end
24
+
25
+ # Returns the type of the current parent extracted form a request path
26
+ #
27
+ def parent_type_from_request
28
+ [*belongs_to].find { |parent| request.path.split('/').include? parent.to_s }
29
+ end
30
+
31
+ # Returns true/false based on whether or not a parent is present.
32
+ #
33
+ def parent?
34
+ !parent_type.nil?
35
+ end
36
+
37
+ # Returns true/false based on whether or not a parent is a singleton.
38
+ #
39
+ def parent_singleton?
40
+ !parent_type_from_request.nil? && parent_type_from_params.nil?
41
+ end
42
+
43
+ # Returns the current parent param, if there is a parent. (i.e. params[:post_id])
44
+ def parent_param
45
+ params["#{parent_type}_id".to_sym]
46
+ end
47
+
48
+ # Like the model method, but for a parent relationship.
49
+ #
50
+ def parent_model
51
+ parent_type.to_s.camelize.constantize
52
+ end
53
+
54
+ # Returns the current parent object if a parent object is present.
55
+ #
56
+ def parent_object
57
+ parent? && !parent_singleton? ? parent_model.get!(parent_param) : nil
58
+ end
59
+
60
+ # If there is a parent, returns the relevant association proxy. Otherwise returns model.
61
+ #
62
+ def end_of_association_chain
63
+ parent? ? parent_association : model
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,64 @@
1
+ # Singleton Resource Helpers
2
+ #
3
+ # Used internally to transform a plural RESTful controller into a singleton
4
+ #
5
+ module ResourceController
6
+ module Helpers
7
+ module SingletonCustomizations
8
+ def self.included(subclass)
9
+ subclass.class_eval do
10
+ methods_to_undefine = [:param, :index, :collection, :load_collection, :collection_url,
11
+ :collection_path, :hash_for_collection_url, :hash_for_collection_path]
12
+ methods_to_undefine.each { |method| undef_method(method) if method_defined? method }
13
+
14
+ class << self
15
+ def singleton?
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ protected
23
+ # Used to fetch the current object in a singleton controller.
24
+ #
25
+ # By defult this method is able to fetch the current object for resources nested with the :has_one association only. (i.e. /users/1/image # => @user.image)
26
+ # In other cases you should override this method and provide your custom code to fetch a singleton resource object, like using a session hash.
27
+ #
28
+ # class AccountsController < ResourceController::Singleton
29
+ # private
30
+ # def object
31
+ # @object ||= Account.get!(session[:account_id])
32
+ # end
33
+ # end
34
+ #
35
+ def object
36
+ @object ||= parent? ? end_of_association_chain : nil
37
+ end
38
+
39
+ # Returns the :has_one association proxy of the parent. (i.e. /users/1/image # => @user.image)
40
+ #
41
+ def parent_association
42
+ @parent_association ||= parent_object.send(model_name.to_sym)
43
+ end
44
+
45
+ # Used internally to provide the options to smart_url in a singleton controller.
46
+ #
47
+ def object_url_options(action_prefix = nil, alternate_object = nil)
48
+ [action_prefix] + namespaces + [parent_url_options, route_name.to_sym]
49
+ end
50
+
51
+ # Builds the object, but doesn't save it, during the new, and create action.
52
+ #
53
+ def build_object
54
+ @object ||= singleton_build_object_base.send parent? ? "build_#{model_name}".to_sym : :new, object_params
55
+ end
56
+
57
+ # Singleton controllers don't build off of association proxy, so we can't use end_of_association_chain here
58
+ #
59
+ def singleton_build_object_base
60
+ parent? ? parent_object : model
61
+ end
62
+ end
63
+ end
64
+ end