pager-resource_controller 1.0.20080513

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 (201) hide show
  1. data/LICENSE +22 -0
  2. data/README +276 -0
  3. data/Rakefile +55 -0
  4. data/TODO +1 -0
  5. data/generators/scaffold_resource/USAGE +29 -0
  6. data/generators/scaffold_resource/scaffold_resource_generator.rb +101 -0
  7. data/generators/scaffold_resource/templates/controller.rb +2 -0
  8. data/generators/scaffold_resource/templates/fixtures.yml +10 -0
  9. data/generators/scaffold_resource/templates/functional_test.rb +57 -0
  10. data/generators/scaffold_resource/templates/helper.rb +2 -0
  11. data/generators/scaffold_resource/templates/migration.rb +15 -0
  12. data/generators/scaffold_resource/templates/model.rb +2 -0
  13. data/generators/scaffold_resource/templates/old_migration.rb +13 -0
  14. data/generators/scaffold_resource/templates/shoulda_functional_test.rb +19 -0
  15. data/generators/scaffold_resource/templates/unit_test.rb +7 -0
  16. data/generators/scaffold_resource/templates/view__form.erb +6 -0
  17. data/generators/scaffold_resource/templates/view__form.haml +5 -0
  18. data/generators/scaffold_resource/templates/view_edit.erb +16 -0
  19. data/generators/scaffold_resource/templates/view_edit.haml +11 -0
  20. data/generators/scaffold_resource/templates/view_index.erb +22 -0
  21. data/generators/scaffold_resource/templates/view_index.haml +19 -0
  22. data/generators/scaffold_resource/templates/view_new.erb +12 -0
  23. data/generators/scaffold_resource/templates/view_new.haml +9 -0
  24. data/generators/scaffold_resource/templates/view_show.erb +9 -0
  25. data/generators/scaffold_resource/templates/view_show.haml +9 -0
  26. data/init.rb +6 -0
  27. data/install.rb +1 -0
  28. data/lib/resource_controller.rb +11 -0
  29. data/lib/resource_controller/accessors.rb +76 -0
  30. data/lib/resource_controller/action_options.rb +28 -0
  31. data/lib/resource_controller/actions.rb +75 -0
  32. data/lib/resource_controller/base.rb +15 -0
  33. data/lib/resource_controller/class_methods.rb +22 -0
  34. data/lib/resource_controller/controller.rb +63 -0
  35. data/lib/resource_controller/failable_action_options.rb +17 -0
  36. data/lib/resource_controller/helpers.rb +28 -0
  37. data/lib/resource_controller/helpers/current_objects.rb +69 -0
  38. data/lib/resource_controller/helpers/internal.rb +59 -0
  39. data/lib/resource_controller/helpers/nested.rb +45 -0
  40. data/lib/resource_controller/helpers/urls.rb +124 -0
  41. data/lib/resource_controller/response_collector.rb +21 -0
  42. data/lib/urligence.rb +50 -0
  43. data/rails/init.rb +1 -0
  44. data/test/Rakefile +10 -0
  45. data/test/app/controllers/application.rb +7 -0
  46. data/test/app/controllers/cms/options_controller.rb +3 -0
  47. data/test/app/controllers/cms/products_controller.rb +2 -0
  48. data/test/app/controllers/comments_controller.rb +3 -0
  49. data/test/app/controllers/people_controller.rb +9 -0
  50. data/test/app/controllers/photos_controller.rb +10 -0
  51. data/test/app/controllers/posts_controller.rb +10 -0
  52. data/test/app/controllers/projects_controller.rb +3 -0
  53. data/test/app/controllers/somethings_controller.rb +3 -0
  54. data/test/app/controllers/tags_controller.rb +13 -0
  55. data/test/app/controllers/users_controller.rb +12 -0
  56. data/test/app/helpers/application_helper.rb +3 -0
  57. data/test/app/helpers/cms/products_helper.rb +2 -0
  58. data/test/app/helpers/comments_helper.rb +2 -0
  59. data/test/app/helpers/options_helper.rb +2 -0
  60. data/test/app/helpers/people_helper.rb +2 -0
  61. data/test/app/helpers/photos_helper.rb +2 -0
  62. data/test/app/helpers/posts_helper.rb +2 -0
  63. data/test/app/helpers/projects_helper.rb +2 -0
  64. data/test/app/helpers/somethings_helper.rb +2 -0
  65. data/test/app/helpers/tags_helper.rb +2 -0
  66. data/test/app/helpers/users_helper.rb +2 -0
  67. data/test/app/models/account.rb +3 -0
  68. data/test/app/models/comment.rb +3 -0
  69. data/test/app/models/option.rb +3 -0
  70. data/test/app/models/photo.rb +4 -0
  71. data/test/app/models/post.rb +3 -0
  72. data/test/app/models/product.rb +3 -0
  73. data/test/app/models/project.rb +2 -0
  74. data/test/app/models/something.rb +2 -0
  75. data/test/app/models/tag.rb +3 -0
  76. data/test/app/views/cms/options/edit.rhtml +17 -0
  77. data/test/app/views/cms/options/index.rhtml +20 -0
  78. data/test/app/views/cms/options/new.rhtml +16 -0
  79. data/test/app/views/cms/options/show.rhtml +8 -0
  80. data/test/app/views/cms/products/edit.rhtml +17 -0
  81. data/test/app/views/cms/products/index.rhtml +20 -0
  82. data/test/app/views/cms/products/new.rhtml +16 -0
  83. data/test/app/views/cms/products/show.rhtml +8 -0
  84. data/test/app/views/comments/edit.rhtml +27 -0
  85. data/test/app/views/comments/index.rhtml +24 -0
  86. data/test/app/views/comments/new.rhtml +26 -0
  87. data/test/app/views/comments/show.rhtml +18 -0
  88. data/test/app/views/layouts/application.rhtml +17 -0
  89. data/test/app/views/layouts/comments.rhtml +17 -0
  90. data/test/app/views/layouts/options.rhtml +17 -0
  91. data/test/app/views/layouts/people.rhtml +17 -0
  92. data/test/app/views/layouts/photos.rhtml +17 -0
  93. data/test/app/views/layouts/projects.rhtml +17 -0
  94. data/test/app/views/layouts/somethings.rhtml +17 -0
  95. data/test/app/views/layouts/tags.rhtml +17 -0
  96. data/test/app/views/people/edit.rhtml +17 -0
  97. data/test/app/views/people/index.rhtml +20 -0
  98. data/test/app/views/people/new.rhtml +16 -0
  99. data/test/app/views/people/show.rhtml +8 -0
  100. data/test/app/views/photos/edit.rhtml +17 -0
  101. data/test/app/views/photos/index.rhtml +20 -0
  102. data/test/app/views/photos/new.rhtml +16 -0
  103. data/test/app/views/photos/show.rhtml +8 -0
  104. data/test/app/views/posts/edit.rhtml +22 -0
  105. data/test/app/views/posts/index.rhtml +22 -0
  106. data/test/app/views/posts/new.rhtml +21 -0
  107. data/test/app/views/posts/show.rhtml +13 -0
  108. data/test/app/views/projects/edit.rhtml +17 -0
  109. data/test/app/views/projects/index.rhtml +20 -0
  110. data/test/app/views/projects/new.rhtml +16 -0
  111. data/test/app/views/projects/show.rhtml +8 -0
  112. data/test/app/views/somethings/edit.rhtml +17 -0
  113. data/test/app/views/somethings/index.rhtml +20 -0
  114. data/test/app/views/somethings/new.rhtml +16 -0
  115. data/test/app/views/somethings/show.rhtml +8 -0
  116. data/test/app/views/tags/edit.rhtml +17 -0
  117. data/test/app/views/tags/index.rhtml +20 -0
  118. data/test/app/views/tags/index.rjs +0 -0
  119. data/test/app/views/tags/new.rhtml +16 -0
  120. data/test/app/views/tags/show.rhtml +8 -0
  121. data/test/app/views/users/edit.rhtml +17 -0
  122. data/test/app/views/users/index.rhtml +20 -0
  123. data/test/app/views/users/new.rhtml +16 -0
  124. data/test/app/views/users/show.rhtml +8 -0
  125. data/test/config/boot.rb +45 -0
  126. data/test/config/database.yml +16 -0
  127. data/test/config/environment.rb +64 -0
  128. data/test/config/environments/development.rb +21 -0
  129. data/test/config/environments/test.rb +19 -0
  130. data/test/config/routes.rb +51 -0
  131. data/test/db/migrate/001_create_posts.rb +12 -0
  132. data/test/db/migrate/002_create_products.rb +11 -0
  133. data/test/db/migrate/003_create_comments.rb +13 -0
  134. data/test/db/migrate/004_create_options.rb +12 -0
  135. data/test/db/migrate/005_create_photos.rb +11 -0
  136. data/test/db/migrate/006_create_tags.rb +17 -0
  137. data/test/db/migrate/007_create_somethings.rb +11 -0
  138. data/test/db/migrate/008_create_accounts.rb +11 -0
  139. data/test/db/migrate/009_add_account_id_to_photos.rb +9 -0
  140. data/test/db/migrate/010_create_projects.rb +11 -0
  141. data/test/db/schema.rb +65 -0
  142. data/test/script/console +3 -0
  143. data/test/script/destroy +3 -0
  144. data/test/script/generate +3 -0
  145. data/test/script/server +3 -0
  146. data/test/test/fixtures/accounts.yml +7 -0
  147. data/test/test/fixtures/comments.yml +11 -0
  148. data/test/test/fixtures/options.yml +9 -0
  149. data/test/test/fixtures/photos.yml +9 -0
  150. data/test/test/fixtures/photos_tags.yml +3 -0
  151. data/test/test/fixtures/posts.yml +9 -0
  152. data/test/test/fixtures/products.yml +7 -0
  153. data/test/test/fixtures/projects.yml +7 -0
  154. data/test/test/fixtures/somethings.yml +7 -0
  155. data/test/test/fixtures/tags.yml +7 -0
  156. data/test/test/functional/cms/options_controller_test.rb +20 -0
  157. data/test/test/functional/cms/products_controller_test.rb +18 -0
  158. data/test/test/functional/comments_controller_test.rb +26 -0
  159. data/test/test/functional/people_controller_test.rb +34 -0
  160. data/test/test/functional/photos_controller_test.rb +128 -0
  161. data/test/test/functional/posts_controller_test.rb +34 -0
  162. data/test/test/functional/projects_controller_test.rb +18 -0
  163. data/test/test/functional/somethings_controller_test.rb +28 -0
  164. data/test/test/functional/tags_controller_test.rb +64 -0
  165. data/test/test/functional/users_controller_test.rb +24 -0
  166. data/test/test/test_helper.rb +12 -0
  167. data/test/test/unit/accessors_test.rb +91 -0
  168. data/test/test/unit/account_test.rb +7 -0
  169. data/test/test/unit/action_options_test.rb +66 -0
  170. data/test/test/unit/base_test.rb +11 -0
  171. data/test/test/unit/comment_test.rb +10 -0
  172. data/test/test/unit/failable_action_options_test.rb +50 -0
  173. data/test/test/unit/helpers/current_objects_test.rb +127 -0
  174. data/test/test/unit/helpers/internal_test.rb +88 -0
  175. data/test/test/unit/helpers/nested_test.rb +82 -0
  176. data/test/test/unit/helpers/urls_test.rb +71 -0
  177. data/test/test/unit/helpers_test.rb +25 -0
  178. data/test/test/unit/option_test.rb +10 -0
  179. data/test/test/unit/photo_test.rb +10 -0
  180. data/test/test/unit/post_test.rb +10 -0
  181. data/test/test/unit/project_test.rb +10 -0
  182. data/test/test/unit/response_collector_test.rb +31 -0
  183. data/test/test/unit/something_test.rb +10 -0
  184. data/test/test/unit/tag_test.rb +10 -0
  185. data/test/test/unit/urligence_test.rb +203 -0
  186. data/test/vendor/plugins/shoulda/README +123 -0
  187. data/test/vendor/plugins/shoulda/Rakefile +29 -0
  188. data/test/vendor/plugins/shoulda/bin/convert_to_should_syntax +40 -0
  189. data/test/vendor/plugins/shoulda/init.rb +3 -0
  190. data/test/vendor/plugins/shoulda/lib/shoulda.rb +47 -0
  191. data/test/vendor/plugins/shoulda/lib/shoulda/active_record_helpers.rb +338 -0
  192. data/test/vendor/plugins/shoulda/lib/shoulda/color.rb +77 -0
  193. data/test/vendor/plugins/shoulda/lib/shoulda/context.rb +143 -0
  194. data/test/vendor/plugins/shoulda/lib/shoulda/controller_tests/controller_tests.rb +470 -0
  195. data/test/vendor/plugins/shoulda/lib/shoulda/controller_tests/formats/html.rb +192 -0
  196. data/test/vendor/plugins/shoulda/lib/shoulda/controller_tests/formats/xml.rb +162 -0
  197. data/test/vendor/plugins/shoulda/lib/shoulda/general.rb +119 -0
  198. data/test/vendor/plugins/shoulda/lib/shoulda/private_helpers.rb +17 -0
  199. data/test/vendor/plugins/shoulda/tasks/list_tests.rake +40 -0
  200. data/uninstall.rb +1 -0
  201. metadata +410 -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,22 @@
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
+ actions_to_remove = []
14
+ actions_to_remove += (ResourceController::ACTIONS - [:new_action] + [:new]) - opts unless opts.first == :all
15
+ actions_to_remove += [*config[:except]] if config[:except]
16
+ actions_to_remove.uniq!
17
+
18
+ actions_to_remove.each { |action| undef_method(action)}
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,63 @@
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) ? FailableActionOptions.new : 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, :model_name, :model, :object_path, :edit_object_path,
19
+ :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
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,17 @@
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, :after, :response, :wants, :to => :success
16
+ end
17
+ 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,69 @@
1
+ module ResourceController::Helpers::CurrentObjects
2
+ protected
3
+ # Used internally to return the model for your resource.
4
+ #
5
+ def model
6
+ model_name.to_s.camelize.constantize
7
+ end
8
+
9
+
10
+ # Used to fetch the collection for the index method
11
+ #
12
+ # In order to customize the way the collection is fetched, to add something like pagination, for example, override this method.
13
+ #
14
+ def collection
15
+ end_of_association_chain.find(:all)
16
+ end
17
+
18
+ # Returns the current param.
19
+ #
20
+ # Defaults to params[:id].
21
+ #
22
+ # Override this method if you'd like to use an alternate param name.
23
+ #
24
+ def param
25
+ params[:id]
26
+ end
27
+
28
+ # Used to fetch the current member object in all of the singular methods that operate on an existing member.
29
+ #
30
+ # Override this method if you'd like to fetch your objects in some alternate way, like using a permalink.
31
+ #
32
+ # class PostsController < ResourceController::Base
33
+ # private
34
+ # def object
35
+ # @object ||= end_of_association_chain.find_by_permalink(param)
36
+ # end
37
+ # end
38
+ #
39
+ def object
40
+ @object ||= end_of_association_chain.find(param) unless param.nil?
41
+ @object
42
+ end
43
+
44
+ # Used internally to load the member object in to an instance variable @#{model_name} (i.e. @post)
45
+ #
46
+ def load_object
47
+ instance_variable_set "@#{parent_type}", parent_object if parent?
48
+ instance_variable_set "@#{object_name}", object
49
+ end
50
+
51
+ # Used internally to load the collection in to an instance variable @#{model_name.pluralize} (i.e. @posts)
52
+ #
53
+ def load_collection
54
+ instance_variable_set "@#{parent_type}", parent_object if parent?
55
+ instance_variable_set "@#{object_name.to_s.pluralize}", collection
56
+ end
57
+
58
+ # Returns the form params. Defaults to params[model_name] (i.e. params["post"])
59
+ #
60
+ def object_params
61
+ params["#{object_name}"]
62
+ end
63
+
64
+ # Builds the object, but doesn't save it, during the new, and create action.
65
+ #
66
+ def build_object
67
+ @object ||= end_of_association_chain.send parent? ? :build : :new, object_params
68
+ end
69
+ end
@@ -0,0 +1,59 @@
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::Helpers::Internal
6
+ protected
7
+ # Used to actually pass the responses along to the controller's respond_to method.
8
+ #
9
+ def response_for(action)
10
+ respond_to do |wants|
11
+ options_for(action).response.each do |method, block|
12
+ if block.nil?
13
+ wants.send(method)
14
+ else
15
+ wants.send(method) { instance_eval(&block) }
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ # Calls the after callbacks for the action, if one is present.
22
+ #
23
+ def after(action)
24
+ invoke_callbacks *options_for(action).after
25
+ end
26
+
27
+ # Calls the before block for the action, if one is present.
28
+ #
29
+ def before(action)
30
+ invoke_callbacks *self.class.send(action).before
31
+ end
32
+
33
+ # Sets the flash for the action, if it is present.
34
+ #
35
+ def set_flash(action)
36
+ flash[:notice] = options_for(action).flash if options_for(action).flash
37
+ end
38
+
39
+ # Returns the options for an action, which is a symbol.
40
+ #
41
+ # Manages splitting things like :create_fails.
42
+ #
43
+ def options_for(action)
44
+ action = action == :new_action ? [action] : "#{action}".split('_').map(&:to_sym)
45
+ options = self.class.send(action.first)
46
+ options = options.send(action.last == :fails ? :fails : :success) if ResourceController::FAILABLE_ACTIONS.include? action.first
47
+
48
+ options
49
+ end
50
+
51
+ def invoke_callbacks(*callbacks)
52
+ unless callbacks.empty?
53
+ callbacks.select { |callback| callback.is_a? Symbol }.each { |symbol| send(symbol) }
54
+
55
+ block = callbacks.detect { |callback| callback.is_a? Proc }
56
+ instance_eval &block unless block.nil?
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,45 @@
1
+ # Nested and Polymorphic Resource Helpers
2
+ #
3
+ module ResourceController::Helpers::Nested
4
+ protected
5
+ # Returns the relevant association proxy of the parent. (i.e. /posts/1/comments # => @post.comments)
6
+ #
7
+ def parent_association
8
+ @parent_association ||= parent_object.send(model_name.to_s.pluralize.to_sym)
9
+ end
10
+
11
+ # Returns the type of the current parent
12
+ #
13
+ def parent_type
14
+ @parent_type ||= [*belongs_to].find { |parent| !params["#{parent}_id".to_sym].nil? }
15
+ end
16
+
17
+ # Returns true/false based on whether or not a parent is present.
18
+ #
19
+ def parent?
20
+ !parent_type.nil?
21
+ end
22
+
23
+ # Returns the current parent param, if there is a parent. (i.e. params[:post_id])
24
+ def parent_param
25
+ params["#{parent_type}_id".to_sym]
26
+ end
27
+
28
+ # Like the model method, but for a parent relationship.
29
+ #
30
+ def parent_model
31
+ parent_type.to_s.camelize.constantize
32
+ end
33
+
34
+ # Returns the current parent object if a parent object is present.
35
+ #
36
+ def parent_object
37
+ parent? ? parent_model.find(parent_param) : nil
38
+ end
39
+
40
+ # If there is a parent, returns the relevant association proxy. Otherwise returns model.
41
+ #
42
+ def end_of_association_chain
43
+ parent? ? parent_association : model
44
+ end
45
+ end
@@ -0,0 +1,124 @@
1
+ # Thanks to Urligence, you get some free url helpers.
2
+ #
3
+ # No matter what your controller looks like...
4
+ #
5
+ # [edit_|new_]object_url # is the equivalent of saying [edit_|new_]post_url(@post)
6
+ # [edit_|new_]object_url(some_other_object) # allows you to specify an object, but still maintain any paths or namespaces that are present
7
+ #
8
+ # collection_url # is like saying posts_url
9
+ #
10
+ # Url helpers are especially useful when working with polymorphic controllers.
11
+ #
12
+ # # /posts/1/comments
13
+ # object_url #=> /posts/1/comments/#{@comment.to_param}
14
+ # object_url(comment) #=> /posts/1/comments/#{comment.to_param}
15
+ # edit_object_url #=> /posts/1/comments/#{@comment.to_param}/edit
16
+ # collection_url #=> /posts/1/comments
17
+ #
18
+ # # /products/1/comments
19
+ # object_url #=> /products/1/comments/#{@comment.to_param}
20
+ # object_url(comment) #=> /products/1/comments/#{comment.to_param}
21
+ # edit_object_url #=> /products/1/comments/#{@comment.to_param}/edit
22
+ # collection_url #=> /products/1/comments
23
+ #
24
+ # # /comments
25
+ # object_url #=> /comments/#{@comment.to_param}
26
+ # object_url(comment) #=> /comments/#{comment.to_param}
27
+ # edit_object_url #=> /comments/#{@comment.to_param}/edit
28
+ # collection_url #=> /comments
29
+ #
30
+ # Or with namespaced, nested controllers...
31
+ #
32
+ # # /admin/products/1/options
33
+ # object_url #=> /admin/products/1/options/#{@option.to_param}
34
+ # object_url(option) #=> /admin/products/1/options/#{option.to_param}
35
+ # edit_object_url #=> /admin/products/1/options/#{@option.to_param}/edit
36
+ # collection_url #=> /admin/products/1/options
37
+ #
38
+ # You get the idea. Everything is automagical! All parameters are inferred.
39
+ #
40
+ module ResourceController::Helpers::Urls
41
+ protected
42
+ ['', 'edit_'].each do |type|
43
+ symbol = type.blank? ? nil : type.gsub(/_/, '').to_sym
44
+
45
+ define_method("#{type}object_url") do |*alternate_object|
46
+ smart_url *object_url_options(symbol, alternate_object.first)
47
+ end
48
+
49
+ define_method("#{type}object_path") do |*alternate_object|
50
+ smart_path *object_url_options(symbol, alternate_object.first)
51
+ end
52
+
53
+ define_method("hash_for_#{type}object_url") do |*alternate_object|
54
+ hash_for_smart_url *object_url_options(symbol, alternate_object.first)
55
+ end
56
+
57
+ define_method("hash_for_#{type}object_path") do |*alternate_object|
58
+ hash_for_smart_path *object_url_options(symbol, alternate_object.first)
59
+ end
60
+ end
61
+
62
+ def new_object_url
63
+ smart_url *new_object_url_options
64
+ end
65
+
66
+ def new_object_path
67
+ smart_path *new_object_url_options
68
+ end
69
+
70
+ def hash_for_new_object_url
71
+ hash_for_smart_url *new_object_url_options
72
+ end
73
+
74
+ def hash_for_new_object_path
75
+ hash_for_smart_path *new_object_url_options
76
+ end
77
+
78
+ def collection_url
79
+ smart_url *collection_url_options
80
+ end
81
+
82
+ def collection_path
83
+ smart_path *collection_url_options
84
+ end
85
+
86
+ def hash_for_collection_url
87
+ hash_for_smart_url *collection_url_options
88
+ end
89
+
90
+ def hash_for_collection_path
91
+ hash_for_smart_path *collection_url_options
92
+ end
93
+
94
+ # Used internally to provide the options to smart_url from Urligence.
95
+ #
96
+ def collection_url_options
97
+ namespaces + [parent_url_options, route_name.to_s.pluralize.to_sym]
98
+ end
99
+
100
+ # Used internally to provide the options to smart_url from Urligence.
101
+ #
102
+ def object_url_options(action_prefix = nil, alternate_object = nil)
103
+ [action_prefix] + namespaces + [parent_url_options, [route_name.to_sym, alternate_object || object]]
104
+ end
105
+
106
+ # Used internally to provide the options to smart_url from Urligence.
107
+ #
108
+ def new_object_url_options
109
+ [:new] + namespaces + [parent_url_options, route_name.to_sym]
110
+ end
111
+
112
+ def parent_url_options
113
+ parent? ? [parent_type.to_sym, parent_object] : nil
114
+ end
115
+
116
+ # Returns all of the current namespaces of the current controller, symbolized, in array form.
117
+ #
118
+ def namespaces
119
+ names = self.class.name.split("::")
120
+ names.pop
121
+
122
+ names.map(&:downcase).map(&:to_sym)
123
+ end
124
+ end