Commit 48c7a14e1352c12068961b181196222d95aabc2c
1 parent
d3a8294d
Exists in
master
and in
1 other branch
added josevalim's inherited resources for RESTful controllers
Showing
35 changed files
with
4937 additions
and
0 deletions
Show diff stats
vendor/gems/josevalim-inherited_resources-0.8.5/.specification
0 → 100644
| ... | ... | @@ -0,0 +1,104 @@ |
| 1 | +--- !ruby/object:Gem::Specification | |
| 2 | +name: josevalim-inherited_resources | |
| 3 | +version: !ruby/object:Gem::Version | |
| 4 | + version: 0.8.5 | |
| 5 | +platform: ruby | |
| 6 | +authors: | |
| 7 | +- "Jos\xC3\xA9 Valim" | |
| 8 | +autorequire: | |
| 9 | +bindir: bin | |
| 10 | +cert_chain: [] | |
| 11 | + | |
| 12 | +date: 2009-07-24 00:00:00 -04:00 | |
| 13 | +default_executable: | |
| 14 | +dependencies: [] | |
| 15 | + | |
| 16 | +description: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important. | |
| 17 | +email: jose.valim@gmail.com | |
| 18 | +executables: [] | |
| 19 | + | |
| 20 | +extensions: [] | |
| 21 | + | |
| 22 | +extra_rdoc_files: | |
| 23 | +- README | |
| 24 | +files: | |
| 25 | +- CHANGELOG | |
| 26 | +- MIT-LICENSE | |
| 27 | +- README | |
| 28 | +- Rakefile | |
| 29 | +- VERSION | |
| 30 | +- lib/inherited_resources.rb | |
| 31 | +- lib/inherited_resources/actions.rb | |
| 32 | +- lib/inherited_resources/base.rb | |
| 33 | +- lib/inherited_resources/base_helpers.rb | |
| 34 | +- lib/inherited_resources/belongs_to_helpers.rb | |
| 35 | +- lib/inherited_resources/class_methods.rb | |
| 36 | +- lib/inherited_resources/dumb_responder.rb | |
| 37 | +- lib/inherited_resources/has_scope_helpers.rb | |
| 38 | +- lib/inherited_resources/polymorphic_helpers.rb | |
| 39 | +- lib/inherited_resources/respond_to.rb | |
| 40 | +- lib/inherited_resources/singleton_helpers.rb | |
| 41 | +- lib/inherited_resources/url_helpers.rb | |
| 42 | +- test/respond_to_test.rb | |
| 43 | +- test/customized_belongs_to_test.rb | |
| 44 | +- test/nested_belongs_to_test.rb | |
| 45 | +- test/base_test.rb | |
| 46 | +- test/redirect_to_test.rb | |
| 47 | +- test/has_scope_test.rb | |
| 48 | +- test/class_methods_test.rb | |
| 49 | +- test/aliases_test.rb | |
| 50 | +- test/flash_test.rb | |
| 51 | +- test/url_helpers_test.rb | |
| 52 | +- test/base_helpers_test.rb | |
| 53 | +- test/belongs_to_test.rb | |
| 54 | +- test/polymorphic_test.rb | |
| 55 | +- test/defaults_test.rb | |
| 56 | +- test/singleton_test.rb | |
| 57 | +- test/optional_belongs_to_test.rb | |
| 58 | +- test/test_helper.rb | |
| 59 | +has_rdoc: true | |
| 60 | +homepage: http://github.com/josevalim/inherited_resources | |
| 61 | +licenses: [] | |
| 62 | + | |
| 63 | +post_install_message: | |
| 64 | +rdoc_options: | |
| 65 | +- --charset=UTF-8 | |
| 66 | +require_paths: | |
| 67 | +- lib | |
| 68 | +required_ruby_version: !ruby/object:Gem::Requirement | |
| 69 | + requirements: | |
| 70 | + - - ">=" | |
| 71 | + - !ruby/object:Gem::Version | |
| 72 | + version: "0" | |
| 73 | + version: | |
| 74 | +required_rubygems_version: !ruby/object:Gem::Requirement | |
| 75 | + requirements: | |
| 76 | + - - ">=" | |
| 77 | + - !ruby/object:Gem::Version | |
| 78 | + version: "0" | |
| 79 | + version: | |
| 80 | +requirements: [] | |
| 81 | + | |
| 82 | +rubyforge_project: inherited_resources | |
| 83 | +rubygems_version: 1.3.4 | |
| 84 | +signing_key: | |
| 85 | +specification_version: 3 | |
| 86 | +summary: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important. | |
| 87 | +test_files: | |
| 88 | +- test/respond_to_test.rb | |
| 89 | +- test/customized_belongs_to_test.rb | |
| 90 | +- test/nested_belongs_to_test.rb | |
| 91 | +- test/base_test.rb | |
| 92 | +- test/redirect_to_test.rb | |
| 93 | +- test/has_scope_test.rb | |
| 94 | +- test/class_methods_test.rb | |
| 95 | +- test/aliases_test.rb | |
| 96 | +- test/flash_test.rb | |
| 97 | +- test/url_helpers_test.rb | |
| 98 | +- test/base_helpers_test.rb | |
| 99 | +- test/belongs_to_test.rb | |
| 100 | +- test/polymorphic_test.rb | |
| 101 | +- test/defaults_test.rb | |
| 102 | +- test/singleton_test.rb | |
| 103 | +- test/optional_belongs_to_test.rb | |
| 104 | +- test/test_helper.rb | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG
0 → 100644
| ... | ... | @@ -0,0 +1,95 @@ |
| 1 | +# Version 0.8 | |
| 2 | + | |
| 3 | +* Fixed a small bug on optional belongs to with namespaced controllers. | |
| 4 | +* Allow a parameter to be given to collection_url in polymorphic cases to replace | |
| 5 | + the parent. | |
| 6 | +* Allow InheritedResources to be called without inheritance. | |
| 7 | +* Ensure that controllers that inherit from a controller with InheritedResources | |
| 8 | + works properly. | |
| 9 | + | |
| 10 | +# Version 0.7 | |
| 11 | + | |
| 12 | +* Allow procs as default value in has scope to be able to use values from session, for example. | |
| 13 | +* Allow blocks with arity 0 or -1 to be given as the redirect url: | |
| 14 | + | |
| 15 | + def destroy | |
| 16 | + destroy!{ project_url(@project) } | |
| 17 | + end | |
| 18 | + | |
| 19 | +* Allow interpolation_options to be set in the application controller. | |
| 20 | +* Added has_scope to controller (an interface for named_scopes). | |
| 21 | +* Added polymorphic_belongs_to, optional_belongs_to and singleton_belongs_to | |
| 22 | + as quick methods. | |
| 23 | +* Only load belongs_to, singleton and polymorphic helpers if they are actually | |
| 24 | + required. base_helpers, class_methods, dumb_responder and url_helpers are loaded | |
| 25 | + when you inherited from base for the first time. | |
| 26 | + | |
| 27 | +# Version 0.6 | |
| 28 | + | |
| 29 | +* Ensure that the default template is not rendered if the default_template_format | |
| 30 | + is not accepted. This is somehow related with the security breach report: | |
| 31 | + | |
| 32 | + http://www.rorsecurity.info/journal/2009/4/24/hidden-actions-render-templates.html | |
| 33 | + | |
| 34 | + IR forbids based on mime types. For example: respond_to :html, :except => :index | |
| 35 | + ensures that the index.html.erb view is not rendered, making your IR controllers | |
| 36 | + safer. | |
| 37 | + | |
| 38 | +* Fixed a bug that happens only when format.xml is given to blocks and then it | |
| 39 | + acts as default, instead of format.html. | |
| 40 | +* Fixed a strange bug where when you have create.html.erb or update.html.erb, | |
| 41 | + it makes IE6 and IE7 return unprocessable entity (because they send Mime::ALL). | |
| 42 | +* Stop rescueing any error when constantizing the resource class and allow | |
| 43 | + route_prefix to be nil. | |
| 44 | +* Cleaned up tests and responder structure. Whenever you pass a block to aliases | |
| 45 | + and this block responds to the request, the other blocks are not parsed improving performance. | |
| 46 | +* [BACKWARDS INCOMPATIBLE] By default, Inherited Resources respond only :html requests. | |
| 47 | +* Added a quick way to overwrite the redirect to url in :create, :update and :destroy. | |
| 48 | + | |
| 49 | +# Version 0.5 | |
| 50 | + | |
| 51 | +* Decoupled routes name from :instance_name and :collection_name. This way we | |
| 52 | + have more flexibility. Use route_instance_name and route_collection_name to | |
| 53 | + to change routes. | |
| 54 | +* Avoid calling human_name on nil when a resource class is not defined. | |
| 55 | +* Only call I18n if it's defined. | |
| 56 | + | |
| 57 | +# Version 0.4 | |
| 58 | + | |
| 59 | +* Dealing with namespaced controllers out of the box. | |
| 60 | +* Added support to namespaced routes through :route_prefix. | |
| 61 | +* Added fix when resource_url is not defined. | |
| 62 | +* Added better handling for namespaced controllers. | |
| 63 | +* Added flash messages scoped by namespaced controllers. | |
| 64 | +* Deprecated {{resource}} in I18n, use {{resource_name}} instead. | |
| 65 | +* rspec bug fix is not automatically required anymore. User has to do it | |
| 66 | + explicitly. | |
| 67 | +* Added a file which fix a rspec bug when render is called inside a method | |
| 68 | + which receives a block. | |
| 69 | +* parent? does not take begin_of_association_chain into account anymore | |
| 70 | +* Added options to url helpers. | |
| 71 | +* Added :optional to belongs_to associations. It allows you to deal with | |
| 72 | + categories/1/products/2 and /products/2 with just one controller. | |
| 73 | +* Cleaned up tests. | |
| 74 | + | |
| 75 | +# Version 0.3 | |
| 76 | + | |
| 77 | +* Minor bump after three bug fixes. | |
| 78 | +* Bug fix when showing warning of constant redefinition. | |
| 79 | +* Bug fix with ApplicationController not being unloaded properly on development. | |
| 80 | +* Bug fix when having root singleton resources. Calling collection_url would | |
| 81 | + raise "NoMethodError _url", not it will call root_url. | |
| 82 | +* More comments on UrlHelpers. | |
| 83 | + | |
| 84 | +# Version 0.2 | |
| 85 | + | |
| 86 | +* Bug fix when ApplicationController is already loaded when we load respond_to. | |
| 87 | +* Added support success/failure blocks. | |
| 88 | +* Eager loading of files to work properly in multithreaded environments. | |
| 89 | + | |
| 90 | +# Version 0.1 | |
| 91 | + | |
| 92 | +* Added more helper_methods. | |
| 93 | +* Added Rails 2.3.0 and changed tests to work with ActionController::TestCase. | |
| 94 | +* First release. Support to I18n, singleton controllers, polymorphic | |
| 95 | +controllers, belongs_to, nested_belongs_to and url helpers. | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE
0 → 100644
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +Copyright (c) 2009 José Valim | |
| 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. | ... | ... |
| ... | ... | @@ -0,0 +1,517 @@ |
| 1 | +Inherited Resources | |
| 2 | +License: MIT | |
| 3 | +Version: 0.8.5 | |
| 4 | + | |
| 5 | +You can also read this README in pretty html at the GitHub project Wiki page: | |
| 6 | + | |
| 7 | + http://wiki.github.com/josevalim/inherited_resources | |
| 8 | + | |
| 9 | +Description | |
| 10 | +----------- | |
| 11 | + | |
| 12 | +Inherited Resources speeds up development by making your controllers inherit | |
| 13 | +all restful actions so you just have to focus on what is important. It makes | |
| 14 | +your controllers more powerful and cleaner at the same time. | |
| 15 | + | |
| 16 | +Plus, making your controllers follow a pattern, it helps you to write better | |
| 17 | +code by following fat models and skinny controllers convention. | |
| 18 | + | |
| 19 | +Inherited Resources is tested and compatible with Rails 2.2.x and Rails 2.3.x. | |
| 20 | + | |
| 21 | +keywords: resources, controller, singleton, belongs_to, polymorphic, named_scope and I18n | |
| 22 | + | |
| 23 | +Installation | |
| 24 | +------------ | |
| 25 | + | |
| 26 | +Install Inherited Resources is very easy. It is stored in GitHub, so just run | |
| 27 | +the following: | |
| 28 | + | |
| 29 | + gem sources -a http://gems.github.com | |
| 30 | + sudo gem install josevalim-inherited_resources | |
| 31 | + | |
| 32 | +If you want it as plugin, just do: | |
| 33 | + | |
| 34 | + script/plugin install git://github.com/josevalim/inherited_resources.git | |
| 35 | + | |
| 36 | +rspec-rails <= 1.1.12 known bug | |
| 37 | +------------------------------- | |
| 38 | + | |
| 39 | +InheritedResources has a known bug with rspec-rails. Please upgrade your rspec | |
| 40 | +version or use the fix which ships with InheritedResources: | |
| 41 | + | |
| 42 | + require 'inherited_resources/spec' | |
| 43 | + | |
| 44 | +Basic Usage | |
| 45 | +----------- | |
| 46 | + | |
| 47 | +To use Inherited Resources you just have to inherit (duh) it: | |
| 48 | + | |
| 49 | + class ProjectsController < InheritedResources::Base | |
| 50 | + end | |
| 51 | + | |
| 52 | +And all actions are defined and working, check it! Your projects collection | |
| 53 | +(in the index action) is still available in the instance variable @projects | |
| 54 | +and your project resource (all other actions) is available as @ project. | |
| 55 | + | |
| 56 | +The next step is to define which mime types this controller provides: | |
| 57 | + | |
| 58 | + class ProjectsController < InheritedResources::Base | |
| 59 | + respond_to :html, :xml, :json | |
| 60 | + end | |
| 61 | + | |
| 62 | +You can also specify them based per action: | |
| 63 | + | |
| 64 | + class ProjectsController < InheritedResources::Base | |
| 65 | + respond_to :html, :xml, :json | |
| 66 | + respond_to :js, :only => :create | |
| 67 | + respond_to :iphone, :except => [ :edit, :update ] | |
| 68 | + end | |
| 69 | + | |
| 70 | +For each request, it first checkes if the "controller/action.format" file is | |
| 71 | +available (for example "projects/create.xml") and if it's not, it checks if | |
| 72 | +the resource respond to :to_format (in this case, :to_xml). Otherwise returns 404. | |
| 73 | + | |
| 74 | +Another option is to specify which actions the controller will inherit from | |
| 75 | +the InheritedResources::Base: | |
| 76 | + | |
| 77 | + class ProjectsController < InheritedResources::Base | |
| 78 | + actions :index, :show, :new, :create | |
| 79 | + end | |
| 80 | + | |
| 81 | +Or: | |
| 82 | + | |
| 83 | + class ProjectsController < InheritedResources::Base | |
| 84 | + actions :all, :except => [ :edit, :update, :destroy ] | |
| 85 | + end | |
| 86 | + | |
| 87 | +In your views, you will get the following helpers: | |
| 88 | + | |
| 89 | + resource #=> @project | |
| 90 | + collection #=> @projects | |
| 91 | + resource_class #=> Project | |
| 92 | + | |
| 93 | +As you might expect, collection (@projects instance variable) is only available | |
| 94 | +on index actions. | |
| 95 | + | |
| 96 | +If for some reason you cannot inherit from InheritedResources::Base, you can | |
| 97 | +call inherit_resources or resource_controller in your controller class scope: | |
| 98 | + | |
| 99 | + class AccountsController < ApplicationController | |
| 100 | + inherit_resources # or resource_controller | |
| 101 | + end | |
| 102 | + | |
| 103 | +Overwriting defaults | |
| 104 | +-------------------- | |
| 105 | + | |
| 106 | +Whenever you inherit from InheritedResources, several defaults are assumed. | |
| 107 | +For example you can have an AccountsController to account management while the | |
| 108 | +resource is an User: | |
| 109 | + | |
| 110 | + class AccountsController < InheritedResources::Base | |
| 111 | + defaults :resource_class => User, :collection_name, 'users', :instance_name => 'user' | |
| 112 | + end | |
| 113 | + | |
| 114 | +In the case above, in your views you will have @users and @user variables, but | |
| 115 | +the routes used will still be accounts_url and account_url. If you plan also to | |
| 116 | +change the routes, you can use :route_collection_name and :route_instance_name. | |
| 117 | + | |
| 118 | +Namespaced controllers work out of the box, but if you need to specify a | |
| 119 | +different route prefix, you can do the following: | |
| 120 | + | |
| 121 | + class Administrators::PeopleController < InheritedResources::Base | |
| 122 | + defaults :route_prefix => 'admin' | |
| 123 | + end | |
| 124 | + | |
| 125 | +Then your named routes will be: 'admin_people_url', 'admin_person_url' instead | |
| 126 | +of 'administrators_people_url' and 'administrators_person_url'. | |
| 127 | + | |
| 128 | +If you want to customize how resources are retrieved you can overwrite | |
| 129 | +collection and resource methods. The first is called on index action and the | |
| 130 | +second on all other actions. Let's suppose you want to add pagination to your | |
| 131 | +projects collection: | |
| 132 | + | |
| 133 | + class ProjectsController < InheritedResources::Base | |
| 134 | + protected | |
| 135 | + def collection | |
| 136 | + @projects ||= end_of_association_chain.paginate(params[:page]).all | |
| 137 | + end | |
| 138 | + end | |
| 139 | + | |
| 140 | +The end_of_association_chain returns your resource after nesting all associations | |
| 141 | +and scopes (more about this below). | |
| 142 | + | |
| 143 | +InheritedResources also introduces another method called begin_of_association_chain. | |
| 144 | +It's mostly used when you want to create resources based on the @current_user and | |
| 145 | +you have urls like "account/projects". In such cases, you have to do | |
| 146 | +@current_user.projects.find or @current_user.projects.build in your actions. | |
| 147 | + | |
| 148 | +You can deal with it just doing: | |
| 149 | + | |
| 150 | + class ProjectsController < InheritedResources::Base | |
| 151 | + protected | |
| 152 | + def begin_of_association_chain | |
| 153 | + @current_user | |
| 154 | + end | |
| 155 | + end | |
| 156 | + | |
| 157 | +Overwriting actions | |
| 158 | +------------------- | |
| 159 | + | |
| 160 | +Let's suppose that after destroying a project you want to redirect to your | |
| 161 | +root url instead of redirecting to projects url. You just have to do: | |
| 162 | + | |
| 163 | + class ProjectsController < InheritedResources::Base | |
| 164 | + def destroy | |
| 165 | + super do |format| | |
| 166 | + format.html { redirect_to root_url } | |
| 167 | + end | |
| 168 | + end | |
| 169 | + end | |
| 170 | + | |
| 171 | +You are opening your action and giving the parent action a new behavior. No | |
| 172 | +tricks, no DSL, just Ruby. | |
| 173 | + | |
| 174 | +On the other hand, I have to agree that calling super is not very readable. | |
| 175 | +That's why all methods have aliases. So this is equivalent: | |
| 176 | + | |
| 177 | + class ProjectsController < InheritedResources::Base | |
| 178 | + def destroy | |
| 179 | + destroy! do |format| | |
| 180 | + format.html { redirect_to root_url } | |
| 181 | + end | |
| 182 | + end | |
| 183 | + end | |
| 184 | + | |
| 185 | +Even more, since most of the times when you change a create, update or destroy | |
| 186 | +action is because you want to to change to where it redirects, a shortcut is | |
| 187 | +provided. So you can do: | |
| 188 | + | |
| 189 | + class ProjectsController < InheritedResources::Base | |
| 190 | + def destroy | |
| 191 | + destroy!{ root_url } | |
| 192 | + end | |
| 193 | + end | |
| 194 | + | |
| 195 | +Now let's suppose that before create a project you have to do something special | |
| 196 | +but you don't want to create a before filter for it: | |
| 197 | + | |
| 198 | + class ProjectsController < InheritedResources::Base | |
| 199 | + def create | |
| 200 | + @project = Project.new(params[:project]) | |
| 201 | + @project.something_special! | |
| 202 | + create! | |
| 203 | + end | |
| 204 | + end | |
| 205 | + | |
| 206 | +Yes, that simple! The nice part is since you already set the instance variable | |
| 207 | +@project, it will not build a project again. | |
| 208 | + | |
| 209 | +Before we finish this topic, we should talk about one more thing: "success/failure | |
| 210 | +blocks". Let's suppose that when we update our project, in case of failure, we | |
| 211 | +want to redirect to the project url instead of re-rendering the edit template. | |
| 212 | + | |
| 213 | +Our first attempt to do this would be: | |
| 214 | + | |
| 215 | + class ProjectsController < InheritedResources::Base | |
| 216 | + def update | |
| 217 | + update! do |format| | |
| 218 | + unless @project.errors.empty? # failure | |
| 219 | + format.html { redirect_to project_url(@project) } | |
| 220 | + end | |
| 221 | + end | |
| 222 | + end | |
| 223 | + end | |
| 224 | + | |
| 225 | +Looks to verbose, right? We can actually do: | |
| 226 | + | |
| 227 | + class ProjectsController < InheritedResources::Base | |
| 228 | + def update | |
| 229 | + update! do |success, failure| | |
| 230 | + failure.html { redirect_to project_url(@project) } | |
| 231 | + end | |
| 232 | + end | |
| 233 | + end | |
| 234 | + | |
| 235 | +Much better! So explaining everything: when you give a block which expects one | |
| 236 | +argument it will be executed in both scenarios: success and failure. But If you | |
| 237 | +give a block that expects two arguments, the first will be executed only in | |
| 238 | +success scenarios and the second in failure scenarios. You keep everything | |
| 239 | +clean and organized inside the same action. | |
| 240 | + | |
| 241 | +Flash messages and I18n | |
| 242 | +----------------------- | |
| 243 | + | |
| 244 | +Flash messages are powered by I18n api. It checks for messages in the following | |
| 245 | +order: | |
| 246 | + | |
| 247 | + flash.controller_name.action_name.status | |
| 248 | + flash.actions.action_name.status | |
| 249 | + | |
| 250 | +If none is available, a default message in english set. In a create action | |
| 251 | +on projects controller, it will search for: | |
| 252 | + | |
| 253 | + flash.projects.create.status | |
| 254 | + flash.actions.create.status | |
| 255 | + | |
| 256 | +The status can be :notice (when the object can be created, updated | |
| 257 | +or destroyed with success) or :error (when the objecy cannot be created | |
| 258 | +or updated). | |
| 259 | + | |
| 260 | +Those messages are interpolated by using the resource class human name, which | |
| 261 | +is also localized and it means you can set: | |
| 262 | + | |
| 263 | + flash: | |
| 264 | + actions: | |
| 265 | + create: | |
| 266 | + notice: "Hooray! {{resource_name}} was successfully created!" | |
| 267 | + | |
| 268 | +It will replace {{resource_name}} by the human name of the resource class, | |
| 269 | +which is "Project" in this case. | |
| 270 | + | |
| 271 | +But sometimes, flash messages are not that simple. Sometimes you want to say | |
| 272 | +the title of the project while updating a project. Well, that's easy also: | |
| 273 | + | |
| 274 | + flash: | |
| 275 | + projects: | |
| 276 | + update: | |
| 277 | + notice: "Hooray! The project "{{project_title}}" was updated!" | |
| 278 | + | |
| 279 | +Since :project_title is not available for interpolation by default, you have | |
| 280 | +to overwrite interpolation_options. | |
| 281 | + | |
| 282 | + def interpolation_options | |
| 283 | + { :project_title => @project.title } | |
| 284 | + end | |
| 285 | + | |
| 286 | +Then you will finally have: | |
| 287 | + | |
| 288 | + "Hooray! The project "Plataforma" was updated!" | |
| 289 | + | |
| 290 | +By default, resource name is capitalized. If you want to make it lower case, you | |
| 291 | +can add to your application controller: | |
| 292 | + | |
| 293 | + def interpolation_options | |
| 294 | + { :resource_name => resource_class.human_name.downcase } | |
| 295 | + end | |
| 296 | + | |
| 297 | +Finally, if your controller is namespaced, for example Admin::ProjectsController, | |
| 298 | +the messages will be checked in the following order: | |
| 299 | + | |
| 300 | + flash.admin.projects.create.notice | |
| 301 | + flash.admin.actions.create.notice | |
| 302 | + flash.projects.create.notice | |
| 303 | + flash.actions.create.notice | |
| 304 | + | |
| 305 | +Has Scope | |
| 306 | +--------- | |
| 307 | + | |
| 308 | +InheritedResources tries to integrate nicely with your model. In order to do so, | |
| 309 | +it also is named_scope fluent. Let's suppose our Project model with the scopes: | |
| 310 | + | |
| 311 | + class ProjectsController < ActiveRecord::Base | |
| 312 | + named_scope :featured, :conditions => { :featured => true } | |
| 313 | + named_scope :by_methodology, proc {|methodology| { :conditions => { :methodology => methodology } } } | |
| 314 | + named_scope :limit, proc{|limit| :limit => limit.to_i } | |
| 315 | + end | |
| 316 | + | |
| 317 | +Your controller: | |
| 318 | + | |
| 319 | + class ProjectsController < InheritedResources::Base | |
| 320 | + has_scope :featured, :boolean => true, :only => :index | |
| 321 | + has_scope :by_methodology | |
| 322 | + has_scope :limit, :default => 10 | |
| 323 | + end | |
| 324 | + | |
| 325 | +Then for each request: | |
| 326 | + | |
| 327 | + /projects | |
| 328 | + #=> acts like a normal request, but returning 10 projects | |
| 329 | + | |
| 330 | + /projects?featured=true | |
| 331 | + #=> calls the featured named scope and bring 10 featured projects | |
| 332 | + | |
| 333 | + /projects?featured=true&by_methodology=agile&limit=20 | |
| 334 | + #=> brings 20 featured projects with methodology agile | |
| 335 | + | |
| 336 | +You can retrieve the current scopes in use with :current_scopes method. | |
| 337 | +In the last case, it would return: | |
| 338 | + | |
| 339 | + { :featured => "true", :by_methodology => "agile", :limit => "20" } | |
| 340 | + | |
| 341 | +Finally, let's suppose you store on the session how many projects the user sees | |
| 342 | +per page. In such cases, you can give a proc as default value: | |
| 343 | + | |
| 344 | + has_scope :limit, :default => proc{|c| c.session[:limit] || 10 } | |
| 345 | + | |
| 346 | +Belongs to | |
| 347 | +---------- | |
| 348 | + | |
| 349 | +Finally, our Projects are going to get some Tasks. Then you create a | |
| 350 | +TasksController and do: | |
| 351 | + | |
| 352 | + class TasksController < InheritedResources::Base | |
| 353 | + belongs_to :project | |
| 354 | + end | |
| 355 | + | |
| 356 | +belongs_to accepts several options to be able to configure the association. | |
| 357 | +For example, if you want urls like /projects/:project_title/tasks, you can | |
| 358 | +customize how InheritedResources find your projects: | |
| 359 | + | |
| 360 | + class TasksController < InheritedResources::Base | |
| 361 | + belongs_to :project, :finder => :find_by_title!, :param => :project_title | |
| 362 | + end | |
| 363 | + | |
| 364 | +It also accepts :route_name, :parent_class and :instance_name as options. | |
| 365 | +Check the lib/inherited_resources/class_methods.rb for more. | |
| 366 | + | |
| 367 | +Nested belongs to | |
| 368 | +----------------- | |
| 369 | + | |
| 370 | +Now, our Tasks get some Comments and you need to nest even deeper. Good | |
| 371 | +practices says that you should never nest more than two resources, but sometimes | |
| 372 | +you have to for security reasons. So this is an example of how you can do it: | |
| 373 | + | |
| 374 | + class CommentsController < InheritedResources::Base | |
| 375 | + nested_belongs_to :project, :task | |
| 376 | + end | |
| 377 | + | |
| 378 | +If you need to configure any of these belongs to, you can nested them using blocks: | |
| 379 | + | |
| 380 | + class CommentsController < InheritedResources::Base | |
| 381 | + belongs_to :project, :finder => :find_by_title!, :param => :project_title do | |
| 382 | + belongs_to :task | |
| 383 | + end | |
| 384 | + end | |
| 385 | + | |
| 386 | +Warning: calling several belongs_to is the same as nesting them: | |
| 387 | + | |
| 388 | + class CommentsConroller < InheritedResources::Base | |
| 389 | + belongs_to :project | |
| 390 | + belongs_to :task | |
| 391 | + end | |
| 392 | + | |
| 393 | +In other words, the code above is the same as calling nested_belongs_to. | |
| 394 | + | |
| 395 | +Polymorphic belongs to | |
| 396 | +---------------------- | |
| 397 | + | |
| 398 | +We can go even further. Let's suppose our Projects can now have Files, Messages | |
| 399 | +and Tasks, and they are all commentable. In this case, the best solution is to | |
| 400 | +use polymorphism: | |
| 401 | + | |
| 402 | + class CommentsController < InheritedResources::Base | |
| 403 | + belongs_to :task, :file, :message, :polymorphic => true | |
| 404 | + # polymorphic_belongs_to :task, :file, :message | |
| 405 | + end | |
| 406 | + | |
| 407 | +You can even use it with nested resources: | |
| 408 | + | |
| 409 | + class CommentsController < InheritedResources::Base | |
| 410 | + belongs_to :project do | |
| 411 | + belongs_to :task, :file, :message, :polymorphic => true | |
| 412 | + end | |
| 413 | + end | |
| 414 | + | |
| 415 | +The url in such cases can be: | |
| 416 | + | |
| 417 | + /project/1/task/13/comments | |
| 418 | + /project/1/file/11/comments | |
| 419 | + /project/1/message/9/comments | |
| 420 | + | |
| 421 | +When using polymorphic associations, you get some free helpers: | |
| 422 | + | |
| 423 | + parent? #=> true | |
| 424 | + parent_type #=> :task | |
| 425 | + parent_class #=> Task | |
| 426 | + parent #=> @task | |
| 427 | + | |
| 428 | +Optional belongs to | |
| 429 | +------------------- | |
| 430 | + | |
| 431 | +Later you decide to create a view to show all comments, independent if they belong | |
| 432 | +to a task, file or message. You can reuse your polymorphic controller just doing: | |
| 433 | + | |
| 434 | + class ProjectsController < InheritedResources::Base | |
| 435 | + belongs_to :task, :file, :message, :optional => true | |
| 436 | + # optional_belongs_to :task, :file, :message | |
| 437 | + end | |
| 438 | + | |
| 439 | +This will handle all those urls properly: | |
| 440 | + | |
| 441 | + /comment/1 | |
| 442 | + /tasks/2/comment/5 | |
| 443 | + /files/10/comment/3 | |
| 444 | + /messages/13/comment/11 | |
| 445 | + | |
| 446 | +This is treated as a special type of polymorphic associations, thus all helpers | |
| 447 | +are available. As you expect, when no parent is found, the helpers return: | |
| 448 | + | |
| 449 | + parent? #=> false | |
| 450 | + parent_type #=> nil | |
| 451 | + parent_class #=> nil | |
| 452 | + parent #=> nil | |
| 453 | + | |
| 454 | +Singletons | |
| 455 | +---------- | |
| 456 | + | |
| 457 | +Now we are going to add manager to projects. We say that Manager is a singleton | |
| 458 | +resource because a Project has just one manager. You should declare it as | |
| 459 | +has_one (or resource) in your routes. | |
| 460 | + | |
| 461 | +To declare an association as singleton, you just have to give the :singleton | |
| 462 | +option. | |
| 463 | + | |
| 464 | + class ManagersController < InheritedResources::Base | |
| 465 | + belongs_to :project, :singleton => true | |
| 466 | + # singleton_belongs_to :project | |
| 467 | + end | |
| 468 | + | |
| 469 | +It will deal with everything again and hide the action :index from you. | |
| 470 | + | |
| 471 | +URL Helpers | |
| 472 | +----------- | |
| 473 | + | |
| 474 | +When you use InheritedResources it creates some URL helpers. | |
| 475 | +And they handle everything for you. :) | |
| 476 | + | |
| 477 | + # /posts/1/comments | |
| 478 | + resource_url # => /posts/1/comments/#{@comment.to_param} | |
| 479 | + resource_url(comment) # => /posts/1/comments/#{comment.to_param} | |
| 480 | + new_resource_url # => /posts/1/comments/new | |
| 481 | + edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit | |
| 482 | + edit_resource_url(comment) #=> /posts/1/comments/#{comment.to_param}/edit | |
| 483 | + collection_url # => /posts/1/comments | |
| 484 | + | |
| 485 | + # /projects/1/tasks | |
| 486 | + resource_url # => /projects/1/tasks/#{@task.to_param} | |
| 487 | + resource_url(task) # => /projects/1/tasks/#{task.to_param} | |
| 488 | + new_resource_url # => /projects/1/tasks/new | |
| 489 | + edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit | |
| 490 | + edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit | |
| 491 | + collection_url # => /projects/1/tasks | |
| 492 | + | |
| 493 | + # /users | |
| 494 | + resource_url # => /users/#{@user.to_param} | |
| 495 | + resource_url(user) # => /users/#{user.to_param} | |
| 496 | + new_resource_url # => /users/new | |
| 497 | + edit_resource_url # => /users/#{@user.to_param}/edit | |
| 498 | + edit_resource_url(user) # => /users/#{user.to_param}/edit | |
| 499 | + collection_url # => /users | |
| 500 | + | |
| 501 | +Those urls helpers also accepts a hash as options, just as in named routes. | |
| 502 | + | |
| 503 | + # /projects/1/tasks | |
| 504 | + collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10 | |
| 505 | + | |
| 506 | +Another nice thing is that those urls are not guessed during runtime. They are | |
| 507 | +all created when your application is loaded (except for polymorphic | |
| 508 | +associations, that relies on Rails polymorphic_url). | |
| 509 | + | |
| 510 | +Bugs and Feedback | |
| 511 | +----------------- | |
| 512 | + | |
| 513 | +If you discover any bugs, please send an e-mail to jose.valim@gmail.com | |
| 514 | +If you just want to give some positive feedback or drop a line, that's fine too! | |
| 515 | + | |
| 516 | +Copyright (c) 2009 José Valim | |
| 517 | +http://josevalim.blogspot.com/ | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile
0 → 100644
| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | +require 'rake' | |
| 2 | +require 'rake/testtask' | |
| 3 | +require 'rake/rdoctask' | |
| 4 | + | |
| 5 | +begin | |
| 6 | + require 'jeweler' | |
| 7 | + Jeweler::Tasks.new do |s| | |
| 8 | + s.name = "inherited_resources" | |
| 9 | + s.rubyforge_project = "inherited_resources" | |
| 10 | + s.summary = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important." | |
| 11 | + s.email = "jose.valim@gmail.com" | |
| 12 | + s.homepage = "http://github.com/josevalim/inherited_resources" | |
| 13 | + s.description = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important." | |
| 14 | + s.authors = ['José Valim'] | |
| 15 | + s.files = FileList["[A-Z]*", "{lib}/**/*"] | |
| 16 | + end | |
| 17 | +rescue LoadError | |
| 18 | + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" | |
| 19 | +end | |
| 20 | + | |
| 21 | +desc 'Run tests for InheritedResources.' | |
| 22 | +Rake::TestTask.new(:test) do |t| | |
| 23 | + t.pattern = 'test/**/*_test.rb' | |
| 24 | + t.verbose = true | |
| 25 | +end | |
| 26 | + | |
| 27 | +desc 'Generate documentation for InheritedResources.' | |
| 28 | +Rake::RDocTask.new(:rdoc) do |rdoc| | |
| 29 | + rdoc.rdoc_dir = 'rdoc' | |
| 30 | + rdoc.title = 'InheritedResources' | |
| 31 | + rdoc.options << '--line-numbers' << '--inline-source' | |
| 32 | + rdoc.rdoc_files.include('README') | |
| 33 | + rdoc.rdoc_files.include('MIT-LICENSE') | |
| 34 | + rdoc.rdoc_files.include('lib/**/*.rb') | |
| 35 | +end | ... | ... |
| ... | ... | @@ -0,0 +1 @@ |
| 1 | +0.8.5 | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb
0 → 100644
| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | +# respond_to is the only file that should be loaded before hand. All others | |
| 2 | +# are loaded on demand. | |
| 3 | +# | |
| 4 | +require File.join(File.dirname(__FILE__), 'inherited_resources', 'respond_to') | |
| 5 | + | |
| 6 | +module InheritedResources; end | |
| 7 | + | |
| 8 | +class ActionController::Base | |
| 9 | + # If you cannot inherit from InheritedResources::Base you can call | |
| 10 | + # inherit_resource in your controller to have all the required modules and | |
| 11 | + # funcionality included. | |
| 12 | + # | |
| 13 | + def self.inherit_resources | |
| 14 | + InheritedResources::Base.inherit_resources(self) | |
| 15 | + initialize_resources_class_accessors! | |
| 16 | + create_resources_url_helpers! | |
| 17 | + end | |
| 18 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb
0 → 100644
| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | +module InheritedResources | |
| 2 | + RESOURCES_ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:RESOURCES_ACTIONS) | |
| 3 | + | |
| 4 | + # Holds all default actions for InheritedResouces. | |
| 5 | + module Actions | |
| 6 | + | |
| 7 | + # GET /resources | |
| 8 | + def index(&block) | |
| 9 | + respond_to(:with => collection, &block) | |
| 10 | + end | |
| 11 | + alias :index! :index | |
| 12 | + | |
| 13 | + # GET /resources/1 | |
| 14 | + def show(&block) | |
| 15 | + respond_to(:with => resource, &block) | |
| 16 | + end | |
| 17 | + alias :show! :show | |
| 18 | + | |
| 19 | + # GET /resources/new | |
| 20 | + def new(&block) | |
| 21 | + respond_to(:with => build_resource, &block) | |
| 22 | + end | |
| 23 | + alias :new! :new | |
| 24 | + | |
| 25 | + # GET /resources/1/edit | |
| 26 | + def edit(&block) | |
| 27 | + respond_to(:with => resource, &block) | |
| 28 | + end | |
| 29 | + alias :edit! :edit | |
| 30 | + | |
| 31 | + # POST /resources | |
| 32 | + def create(&block) | |
| 33 | + object = build_resource | |
| 34 | + respond_block, redirect_block = select_block_by_arity(block) | |
| 35 | + | |
| 36 | + if object.save | |
| 37 | + set_flash_message!(:notice, '{{resource_name}} was successfully created.') | |
| 38 | + options = { :with => object, :status => :created, :location => (resource_url rescue nil) } | |
| 39 | + | |
| 40 | + respond_to_with_dual_blocks(true, respond_block, options) do |format| | |
| 41 | + format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) } | |
| 42 | + end | |
| 43 | + else | |
| 44 | + set_flash_message!(:error) | |
| 45 | + options = { :with => object.errors, :status => :unprocessable_entity } | |
| 46 | + | |
| 47 | + respond_to_with_dual_blocks(false, respond_block, options) do |format| | |
| 48 | + format.html { render :action => 'new' } | |
| 49 | + end | |
| 50 | + end | |
| 51 | + end | |
| 52 | + alias :create! :create | |
| 53 | + | |
| 54 | + # PUT /resources/1 | |
| 55 | + def update(&block) | |
| 56 | + object = resource | |
| 57 | + respond_block, redirect_block = select_block_by_arity(block) | |
| 58 | + | |
| 59 | + if object.update_attributes(params[resource_instance_name]) | |
| 60 | + set_flash_message!(:notice, '{{resource_name}} was successfully updated.') | |
| 61 | + | |
| 62 | + respond_to_with_dual_blocks(true, block) do |format| | |
| 63 | + format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) } | |
| 64 | + format.all { head :ok } | |
| 65 | + end | |
| 66 | + else | |
| 67 | + set_flash_message!(:error) | |
| 68 | + | |
| 69 | + options = { :with => object.errors, :status => :unprocessable_entity } | |
| 70 | + | |
| 71 | + respond_to_with_dual_blocks(false, block, options) do |format| | |
| 72 | + format.html { render :action => 'edit' } | |
| 73 | + end | |
| 74 | + end | |
| 75 | + end | |
| 76 | + alias :update! :update | |
| 77 | + | |
| 78 | + # DELETE /resources/1 | |
| 79 | + def destroy(&block) | |
| 80 | + resource.destroy | |
| 81 | + respond_block, redirect_block = select_block_by_arity(block) | |
| 82 | + | |
| 83 | + set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.') | |
| 84 | + | |
| 85 | + respond_to_with_dual_blocks(nil, respond_block) do |format| | |
| 86 | + format.html { redirect_to(redirect_block ? redirect_block.call : collection_url) } | |
| 87 | + format.all { head :ok } | |
| 88 | + end | |
| 89 | + end | |
| 90 | + alias :destroy! :destroy | |
| 91 | + | |
| 92 | + # Make aliases protected | |
| 93 | + protected :index!, :show!, :new!, :create!, :edit!, :update!, :destroy! | |
| 94 | + | |
| 95 | + end | |
| 96 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb
0 → 100644
| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | +module InheritedResources | |
| 2 | + # = Base | |
| 3 | + # | |
| 4 | + # This is the base class that holds all actions. If you see the code for each | |
| 5 | + # action, they are quite similar to Rails default scaffold. | |
| 6 | + # | |
| 7 | + # To change your base behavior, you can overwrite your actions and call super, | |
| 8 | + # call <tt>default</tt> class method, call <<tt>actions</tt> class method | |
| 9 | + # or overwrite some helpers in the base_helpers.rb file. | |
| 10 | + # | |
| 11 | + class Base < ::ApplicationController | |
| 12 | + unloadable | |
| 13 | + | |
| 14 | + # Overwrite inherit_resources to add specific InheritedResources behavior. | |
| 15 | + # | |
| 16 | + def self.inherit_resources(base) | |
| 17 | + base.class_eval do | |
| 18 | + include InheritedResources::Actions | |
| 19 | + include InheritedResources::BaseHelpers | |
| 20 | + extend InheritedResources::ClassMethods | |
| 21 | + extend InheritedResources::UrlHelpers | |
| 22 | + | |
| 23 | + helper_method :collection_url, :collection_path, :resource_url, :resource_path, | |
| 24 | + :new_resource_url, :new_resource_path, :edit_resource_url, :edit_resource_path, | |
| 25 | + :resource, :collection, :resource_class | |
| 26 | + | |
| 27 | + base.with_options :instance_writer => false do |c| | |
| 28 | + c.class_inheritable_accessor :resource_class | |
| 29 | + c.class_inheritable_array :parents_symbols | |
| 30 | + c.class_inheritable_hash :resources_configuration, :scopes_configuration | |
| 31 | + end | |
| 32 | + | |
| 33 | + protected :resource_class, :parents_symbols, :resources_configuration, :scopes_configuration | |
| 34 | + end | |
| 35 | + end | |
| 36 | + | |
| 37 | + inherit_resources(self) | |
| 38 | + end | |
| 39 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,329 @@ |
| 1 | +# Whenever base is required load the dumb responder since it's used inside actions. | |
| 2 | +require File.dirname(__FILE__) + '/dumb_responder.rb' | |
| 3 | + | |
| 4 | +module InheritedResources | |
| 5 | + # Base helpers for InheritedResource work. Some methods here can be overwriten | |
| 6 | + # and you will need to do that to customize your controllers from time to time. | |
| 7 | + # | |
| 8 | + module BaseHelpers | |
| 9 | + | |
| 10 | + protected | |
| 11 | + | |
| 12 | + # This is how the collection is loaded. | |
| 13 | + # | |
| 14 | + # You might want to overwrite this method if you want to add pagination | |
| 15 | + # for example. When you do that, don't forget to cache the result in an | |
| 16 | + # instance_variable: | |
| 17 | + # | |
| 18 | + # def collection | |
| 19 | + # @projects ||= end_of_association_chain.paginate(params[:page]).all | |
| 20 | + # end | |
| 21 | + # | |
| 22 | + def collection | |
| 23 | + get_collection_ivar || set_collection_ivar(end_of_association_chain.find(:all)) | |
| 24 | + end | |
| 25 | + | |
| 26 | + # This is how the resource is loaded. | |
| 27 | + # | |
| 28 | + # You might want to overwrite this method when you are using permalink. | |
| 29 | + # When you do that, don't forget to cache the result in an | |
| 30 | + # instance_variable: | |
| 31 | + # | |
| 32 | + # def resource | |
| 33 | + # @project ||= end_of_association_chain.find_by_permalink!(params[:id]) | |
| 34 | + # end | |
| 35 | + # | |
| 36 | + # You also might want to add the exclamation mark at the end of the method | |
| 37 | + # because it will raise a 404 if nothing can be found. Otherwise it will | |
| 38 | + # probably render a 500 error message. | |
| 39 | + # | |
| 40 | + def resource | |
| 41 | + get_resource_ivar || set_resource_ivar(end_of_association_chain.find(params[:id])) | |
| 42 | + end | |
| 43 | + | |
| 44 | + # This method is responsable for building the object on :new and :create | |
| 45 | + # methods. If you overwrite it, don't forget to cache the result in an | |
| 46 | + # instance variable. | |
| 47 | + # | |
| 48 | + def build_resource | |
| 49 | + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, params[resource_instance_name])) | |
| 50 | + end | |
| 51 | + | |
| 52 | + # This class allows you to set a instance variable to begin your | |
| 53 | + # association chain. For example, usually your projects belongs to users | |
| 54 | + # and that means that they belong to the current logged in user. So you | |
| 55 | + # could do this: | |
| 56 | + # | |
| 57 | + # def begin_of_association_chain | |
| 58 | + # @current_user | |
| 59 | + # end | |
| 60 | + # | |
| 61 | + # So every time we instantiate a project, we will do: | |
| 62 | + # | |
| 63 | + # @current_user.projects.build(params[:project]) | |
| 64 | + # @current_user.projects.find(params[:id]) | |
| 65 | + # | |
| 66 | + # The variable set in begin_of_association_chain is not sent when building | |
| 67 | + # urls, so this is never going to happen when calling resource_url: | |
| 68 | + # | |
| 69 | + # project_url(@current_user, @project) | |
| 70 | + # | |
| 71 | + # If the user actually scopes the url, you should use belongs_to method | |
| 72 | + # and declare that projects belong to user. | |
| 73 | + # | |
| 74 | + def begin_of_association_chain | |
| 75 | + nil | |
| 76 | + end | |
| 77 | + | |
| 78 | + # Returns if the controller has a parent. When only base helpers are loaded, | |
| 79 | + # it's always false and should not be overwriten. | |
| 80 | + # | |
| 81 | + def parent? | |
| 82 | + false | |
| 83 | + end | |
| 84 | + | |
| 85 | + # Overwrite this method to provide other interpolation options when | |
| 86 | + # the flash message is going to be set. | |
| 87 | + # | |
| 88 | + # def interpolation_options | |
| 89 | + # { } | |
| 90 | + # end | |
| 91 | + | |
| 92 | + private | |
| 93 | + | |
| 94 | + # Fast accessor to resource_collection_name | |
| 95 | + # | |
| 96 | + def resource_collection_name #:nodoc: | |
| 97 | + self.resources_configuration[:self][:collection_name] | |
| 98 | + end | |
| 99 | + | |
| 100 | + # Fast accessor to resource_instance_name | |
| 101 | + # | |
| 102 | + def resource_instance_name #:nodoc: | |
| 103 | + self.resources_configuration[:self][:instance_name] | |
| 104 | + end | |
| 105 | + | |
| 106 | + # This methods gets your begin_of_association_chain, join it with your | |
| 107 | + # parents chain and returns the scoped association. | |
| 108 | + # | |
| 109 | + def end_of_association_chain #:nodoc: | |
| 110 | + chain = symbols_for_association_chain.inject(begin_of_association_chain) do |chain, symbol| | |
| 111 | + evaluate_parent(symbol, resources_configuration[symbol], chain) | |
| 112 | + end | |
| 113 | + | |
| 114 | + if chain | |
| 115 | + if method_for_association_chain | |
| 116 | + apply_scope_to(chain.send(method_for_association_chain)) | |
| 117 | + else | |
| 118 | + # This only happens when we specify begin_of_association_chain in | |
| 119 | + # a singletion controller without parents. In this case, the chain | |
| 120 | + # is exactly the begin_of_association_chain which is already an | |
| 121 | + # instance and then not scopable. | |
| 122 | + chain | |
| 123 | + end | |
| 124 | + else | |
| 125 | + apply_scope_to(resource_class) | |
| 126 | + end | |
| 127 | + end | |
| 128 | + | |
| 129 | + # Returns the appropriated method to build the resource. | |
| 130 | + # | |
| 131 | + def method_for_build #:nodoc: | |
| 132 | + (begin_of_association_chain || parent?) ? method_for_association_build : :new | |
| 133 | + end | |
| 134 | + | |
| 135 | + # Returns the name of the method used for build the resource in cases | |
| 136 | + # where we have a parent. This is overwritten in singleton scenarios. | |
| 137 | + # | |
| 138 | + def method_for_association_build | |
| 139 | + :build | |
| 140 | + end | |
| 141 | + | |
| 142 | + # Returns the name of the method to be called, before returning the end | |
| 143 | + # of the association chain. This is overwriten by singleton cases | |
| 144 | + # where no method for association chain is called. | |
| 145 | + # | |
| 146 | + def method_for_association_chain #:nodoc: | |
| 147 | + resource_collection_name | |
| 148 | + end | |
| 149 | + | |
| 150 | + # Get resource ivar based on the current resource controller. | |
| 151 | + # | |
| 152 | + def get_resource_ivar #:nodoc: | |
| 153 | + instance_variable_get("@#{resource_instance_name}") | |
| 154 | + end | |
| 155 | + | |
| 156 | + # Set resource ivar based on the current resource controller. | |
| 157 | + # | |
| 158 | + def set_resource_ivar(resource) #:nodoc: | |
| 159 | + instance_variable_set("@#{resource_instance_name}", resource) | |
| 160 | + end | |
| 161 | + | |
| 162 | + # Get collection ivar based on the current resource controller. | |
| 163 | + # | |
| 164 | + def get_collection_ivar #:nodoc: | |
| 165 | + instance_variable_get("@#{resource_collection_name}") | |
| 166 | + end | |
| 167 | + | |
| 168 | + # Set collection ivar based on the current resource controller. | |
| 169 | + # | |
| 170 | + def set_collection_ivar(collection) #:nodoc: | |
| 171 | + instance_variable_set("@#{resource_collection_name}", collection) | |
| 172 | + end | |
| 173 | + | |
| 174 | + # Helper to set flash messages. It's powered by I18n API. | |
| 175 | + # It checks for messages in the following order: | |
| 176 | + # | |
| 177 | + # flash.controller_name.action_name.status | |
| 178 | + # flash.actions.action_name.status | |
| 179 | + # | |
| 180 | + # If none is available, a default message is set. So, if you have | |
| 181 | + # a CarsController, create action, it will check for: | |
| 182 | + # | |
| 183 | + # flash.cars.create.status | |
| 184 | + # flash.actions.create.status | |
| 185 | + # | |
| 186 | + # The statuses can be :notice (when the object can be created, updated | |
| 187 | + # or destroyed with success) or :error (when the objecy cannot be created | |
| 188 | + # or updated). | |
| 189 | + # | |
| 190 | + # Those messages are interpolated by using the resource class human name. | |
| 191 | + # This means you can set: | |
| 192 | + # | |
| 193 | + # flash: | |
| 194 | + # actions: | |
| 195 | + # create: | |
| 196 | + # notice: "Hooray! {{resource_name}} was successfully created!" | |
| 197 | + # | |
| 198 | + # But sometimes, flash messages are not that simple. Going back | |
| 199 | + # to cars example, you might want to say the brand of the car when it's | |
| 200 | + # updated. Well, that's easy also: | |
| 201 | + # | |
| 202 | + # flash: | |
| 203 | + # cars: | |
| 204 | + # update: | |
| 205 | + # notice: "Hooray! You just tuned your {{car_brand}}!" | |
| 206 | + # | |
| 207 | + # Since :car_name is not available for interpolation by default, you have | |
| 208 | + # to overwrite interpolation_options. | |
| 209 | + # | |
| 210 | + # def interpolation_options | |
| 211 | + # { :car_brand => @car.brand } | |
| 212 | + # end | |
| 213 | + # | |
| 214 | + # Then you will finally have: | |
| 215 | + # | |
| 216 | + # 'Hooray! You just tuned your Aston Martin!' | |
| 217 | + # | |
| 218 | + # If your controller is namespaced, for example Admin::CarsController, | |
| 219 | + # the messages will be checked in the following order: | |
| 220 | + # | |
| 221 | + # flash.admin.cars.create.status | |
| 222 | + # flash.admin.actions.create.status | |
| 223 | + # flash.cars.create.status | |
| 224 | + # flash.actions.create.status | |
| 225 | + # | |
| 226 | + def set_flash_message!(status, default_message=nil) | |
| 227 | + return flash[status] = default_message unless defined?(::I18n) | |
| 228 | + | |
| 229 | + resource_name = if resource_class | |
| 230 | + if resource_class.respond_to?(:human_name) | |
| 231 | + resource_class.human_name | |
| 232 | + else | |
| 233 | + resource_class.name.humanize | |
| 234 | + end | |
| 235 | + else | |
| 236 | + "Resource" | |
| 237 | + end | |
| 238 | + | |
| 239 | + given_options = if self.respond_to?(:interpolation_options) | |
| 240 | + interpolation_options | |
| 241 | + else | |
| 242 | + {} | |
| 243 | + end | |
| 244 | + | |
| 245 | + options = { | |
| 246 | + :default => default_message || '', | |
| 247 | + :resource_name => resource_name | |
| 248 | + }.merge(given_options) | |
| 249 | + | |
| 250 | + defaults = [] | |
| 251 | + slices = controller_path.split('/') | |
| 252 | + | |
| 253 | + while slices.size > 0 | |
| 254 | + defaults << :"flash.#{slices.fill(controller_name, -1).join('.')}.#{action_name}.#{status}" | |
| 255 | + defaults << :"flash.#{slices.fill(:actions, -1).join('.')}.#{action_name}.#{status}" | |
| 256 | + slices.shift | |
| 257 | + end | |
| 258 | + | |
| 259 | + options[:default] = defaults.push(options[:default]) | |
| 260 | + options[:default].flatten! | |
| 261 | + | |
| 262 | + message = ::I18n.t options[:default].shift, options | |
| 263 | + flash[status] = message unless message.blank? | |
| 264 | + end | |
| 265 | + | |
| 266 | + # Used to allow to specify success and failure within just one block: | |
| 267 | + # | |
| 268 | + # def create | |
| 269 | + # create! do |success, failure| | |
| 270 | + # failure.html { redirect_to root_url } | |
| 271 | + # end | |
| 272 | + # end | |
| 273 | + # | |
| 274 | + def respond_to_with_dual_blocks(success, dual_block, options={}, &block) #:nodoc: | |
| 275 | + responder = ActionController::MimeResponds::Responder.new(self) | |
| 276 | + | |
| 277 | + if dual_block | |
| 278 | + if dual_block.arity == 2 | |
| 279 | + dumb_responder = InheritedResources::DumbResponder.new | |
| 280 | + if success | |
| 281 | + dual_block.call(responder, dumb_responder) | |
| 282 | + else | |
| 283 | + dual_block.call(dumb_responder, responder) | |
| 284 | + end | |
| 285 | + else | |
| 286 | + dual_block.call(responder) | |
| 287 | + end | |
| 288 | + | |
| 289 | + # Try to respond with the block given | |
| 290 | + responder.respond_except_any | |
| 291 | + end | |
| 292 | + | |
| 293 | + respond_to(options.merge!(:responder => responder, :prioritize => :html), &block) unless performed? | |
| 294 | + end | |
| 295 | + | |
| 296 | + # Hook to apply scopes. By default returns only the target_object given. | |
| 297 | + # It's extend by HasScopeHelpers. | |
| 298 | + # | |
| 299 | + def apply_scope_to(target_object) #:nodoc: | |
| 300 | + target_object | |
| 301 | + end | |
| 302 | + | |
| 303 | + # Symbols chain in base helpers return nothing. This is later overwriten | |
| 304 | + # by belongs_to and can be complex in polymorphic cases. | |
| 305 | + # | |
| 306 | + def symbols_for_association_chain #:nodoc: | |
| 307 | + [] | |
| 308 | + end | |
| 309 | + | |
| 310 | + # Holds InheritedResources block structure. It returns two blocks: the first | |
| 311 | + # is used in respond_to blocks and the second is the redirect_to url. | |
| 312 | + # | |
| 313 | + def select_block_by_arity(block) #:nodoc | |
| 314 | + if block | |
| 315 | + case block.arity | |
| 316 | + when 2, 1 | |
| 317 | + [block, nil] | |
| 318 | + when 0, -1 | |
| 319 | + [nil, block] | |
| 320 | + else | |
| 321 | + raise ScriptError, "InheritedResources does not know how to handle blocks with arity #{block.arity}" | |
| 322 | + end | |
| 323 | + else | |
| 324 | + [nil, nil] | |
| 325 | + end | |
| 326 | + end | |
| 327 | + | |
| 328 | + end | |
| 329 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,89 @@ |
| 1 | +module InheritedResources | |
| 2 | + | |
| 3 | + # = belongs_to | |
| 4 | + # | |
| 5 | + # Let's suppose that we have some tasks that belongs to projects. To specify | |
| 6 | + # this assoication in your controllers, just do: | |
| 7 | + # | |
| 8 | + # class TasksController < InheritedResources::Base | |
| 9 | + # belongs_to :project | |
| 10 | + # end | |
| 11 | + # | |
| 12 | + # belongs_to accepts several options to be able to configure the association. | |
| 13 | + # For example, if you want urls like /projects/:project_title/tasks, you | |
| 14 | + # can customize how InheritedResources find your projects: | |
| 15 | + # | |
| 16 | + # class TasksController < InheritedResources::Base | |
| 17 | + # belongs_to :project, :finder => :find_by_title!, :param => :project_title | |
| 18 | + # end | |
| 19 | + # | |
| 20 | + # It also accepts :route_name, :parent_class and :instance_name as options. | |
| 21 | + # Check the lib/inherited_resources/class_methods.rb for more. | |
| 22 | + # | |
| 23 | + # = nested_belongs_to | |
| 24 | + # | |
| 25 | + # Now, our Tasks get some Comments and you need to nest even deeper. Good | |
| 26 | + # practices says that you should never nest more than two resources, but sometimes | |
| 27 | + # you have to for security reasons. So this is an example of how you can do it: | |
| 28 | + # | |
| 29 | + # class CommentsController < InheritedResources::Base | |
| 30 | + # nested_belongs_to :project, :task | |
| 31 | + # end | |
| 32 | + # | |
| 33 | + # If you need to configure any of these belongs to, you can nested them using blocks: | |
| 34 | + # | |
| 35 | + # class CommentsController < InheritedResources::Base | |
| 36 | + # belongs_to :project, :finder => :find_by_title!, :param => :project_title do | |
| 37 | + # belongs_to :task | |
| 38 | + # end | |
| 39 | + # end | |
| 40 | + # | |
| 41 | + # Warning: calling several belongs_to is the same as nesting them: | |
| 42 | + # | |
| 43 | + # class CommentsController < InheritedResources::Base | |
| 44 | + # belongs_to :project | |
| 45 | + # belongs_to :task | |
| 46 | + # end | |
| 47 | + # | |
| 48 | + # In other words, the code above is the same as calling nested_belongs_to. | |
| 49 | + # | |
| 50 | + module BelongsToHelpers | |
| 51 | + | |
| 52 | + protected | |
| 53 | + | |
| 54 | + # Parent is always true when belongs_to is called. | |
| 55 | + # | |
| 56 | + def parent? | |
| 57 | + true | |
| 58 | + end | |
| 59 | + | |
| 60 | + private | |
| 61 | + | |
| 62 | + # Evaluate the parent given. This is used to nest parents in the | |
| 63 | + # association chain. | |
| 64 | + # | |
| 65 | + def evaluate_parent(parent_symbol, parent_config, chain = nil) #:nodoc: | |
| 66 | + instantiated_object = instance_variable_get("@#{parent_config[:instance_name]}") | |
| 67 | + return instantiated_object if instantiated_object | |
| 68 | + | |
| 69 | + parent = if chain | |
| 70 | + chain.send(parent_config[:collection_name]) | |
| 71 | + else | |
| 72 | + parent_config[:parent_class] | |
| 73 | + end | |
| 74 | + | |
| 75 | + parent = parent.send(parent_config[:finder], params[parent_config[:param]]) | |
| 76 | + | |
| 77 | + instance_variable_set("@#{parent_config[:instance_name]}", parent) | |
| 78 | + end | |
| 79 | + | |
| 80 | + # Maps parents_symbols to build association chain. In this case, it | |
| 81 | + # simply return the parent_symbols, however on polymorphic belongs to, | |
| 82 | + # it has some customization. | |
| 83 | + # | |
| 84 | + def symbols_for_association_chain #:nodoc: | |
| 85 | + parents_symbols | |
| 86 | + end | |
| 87 | + | |
| 88 | + end | |
| 89 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb
0 → 100644
| ... | ... | @@ -0,0 +1,328 @@ |
| 1 | +module InheritedResources | |
| 2 | + module ClassMethods | |
| 3 | + | |
| 4 | + protected | |
| 5 | + | |
| 6 | + # Used to overwrite the default assumptions InheritedResources do. Whenever | |
| 7 | + # this method is called, it should be on the top of your controller, since | |
| 8 | + # almost other methods depends on the values given to <<tt>>defaults</tt>. | |
| 9 | + # | |
| 10 | + # == Options | |
| 11 | + # | |
| 12 | + # * <tt>:resource_class</tt> - The resource class which by default is guessed | |
| 13 | + # by the controller name. Defaults to Project in | |
| 14 | + # ProjectsController. | |
| 15 | + # | |
| 16 | + # * <tt>:collection_name</tt> - The name of the collection instance variable which | |
| 17 | + # is set on the index action. Defaults to :projects in | |
| 18 | + # ProjectsController. | |
| 19 | + # | |
| 20 | + # * <tt>:instance_name</tt> - The name of the singular instance variable which | |
| 21 | + # is set on all actions besides index action. Defaults to | |
| 22 | + # :project in ProjectsController. | |
| 23 | + # | |
| 24 | + # * <tt>:route_collection_name</tt> - The name of the collection route. Defaults to :collection_name. | |
| 25 | + # | |
| 26 | + # * <tt>:route_instance_name</tt> - The name of the singular route. Defaults to :instance_name. | |
| 27 | + # | |
| 28 | + # * <tt>:route_prefix</tt> - The route prefix which is automically set in namespaced | |
| 29 | + # controllers. Default to :admin on Admin::ProjectsController. | |
| 30 | + # | |
| 31 | + # * <tt>:singleton</tt> - Tells if this controller is singleton or not. | |
| 32 | + # | |
| 33 | + def defaults(options) | |
| 34 | + raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash | |
| 35 | + | |
| 36 | + options.symbolize_keys! | |
| 37 | + options.assert_valid_keys(:resource_class, :collection_name, :instance_name, | |
| 38 | + :class_name, :route_prefix, :route_collection_name, | |
| 39 | + :route_instance_name, :singleton) | |
| 40 | + | |
| 41 | + self.resource_class = options.delete(:resource_class) if options.key?(:resource_class) | |
| 42 | + self.resource_class = options.delete(:class_name).constantize if options.key?(:class_name) | |
| 43 | + | |
| 44 | + acts_as_singleton! if options.delete(:singleton) | |
| 45 | + | |
| 46 | + config = self.resources_configuration[:self] | |
| 47 | + config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix) | |
| 48 | + | |
| 49 | + options.each do |key, value| | |
| 50 | + config[key] = value.to_sym | |
| 51 | + end | |
| 52 | + | |
| 53 | + create_resources_url_helpers! | |
| 54 | + end | |
| 55 | + | |
| 56 | + # Defines wich actions to keep from the inherited controller. | |
| 57 | + # Syntax is borrowed from resource_controller. | |
| 58 | + # | |
| 59 | + # actions :index, :show, :edit | |
| 60 | + # actions :all, :except => :index | |
| 61 | + # | |
| 62 | + def actions(*actions_to_keep) | |
| 63 | + raise ArgumentError, 'Wrong number of arguments. You have to provide which actions you want to keep.' if actions_to_keep.empty? | |
| 64 | + | |
| 65 | + options = actions_to_keep.extract_options! | |
| 66 | + actions_to_keep.map!{ |a| a.to_s } | |
| 67 | + | |
| 68 | + actions_to_remove = Array(options[:except]) | |
| 69 | + actions_to_remove.map!{ |a| a.to_s } | |
| 70 | + | |
| 71 | + actions_to_remove += RESOURCES_ACTIONS.map{|a| a.to_s } - actions_to_keep unless actions_to_keep.first == 'all' | |
| 72 | + actions_to_remove.uniq! | |
| 73 | + | |
| 74 | + (instance_methods & actions_to_remove).each do |action| | |
| 75 | + undef_method action, "#{action}!" | |
| 76 | + end | |
| 77 | + end | |
| 78 | + | |
| 79 | + # Detects params from url and apply as scopes to your classes. | |
| 80 | + # | |
| 81 | + # Your model: | |
| 82 | + # | |
| 83 | + # class Graduation < ActiveRecord::Base | |
| 84 | + # named_scope :featured, :conditions => { :featured => true } | |
| 85 | + # named_scope :by_degree, proc {|degree| { :conditions => { :degree => degree } } } | |
| 86 | + # end | |
| 87 | + # | |
| 88 | + # Your controller: | |
| 89 | + # | |
| 90 | + # class GraduationsController < InheritedResources::Base | |
| 91 | + # has_scope :featured, :boolean => true, :only => :index | |
| 92 | + # has_scope :by_degree, :only => :index | |
| 93 | + # end | |
| 94 | + # | |
| 95 | + # Then for each request: | |
| 96 | + # | |
| 97 | + # /graduations | |
| 98 | + # #=> acts like a normal request | |
| 99 | + # | |
| 100 | + # /graduations?featured=true | |
| 101 | + # #=> calls the named scope and bring featured graduations | |
| 102 | + # | |
| 103 | + # /graduations?featured=true&by_degree=phd | |
| 104 | + # #=> brings featured graduations with phd degree | |
| 105 | + # | |
| 106 | + # You can retrieve the current scopes in use with <tt>current_scopes</tt> | |
| 107 | + # method. In the last case, it would return: { :featured => "true", :by_degree => "phd" } | |
| 108 | + # | |
| 109 | + # == Options | |
| 110 | + # | |
| 111 | + # * <tt>:boolean</tt> - When set to true, call the scope only when the params is true or 1, | |
| 112 | + # and does not send the value as argument. | |
| 113 | + # | |
| 114 | + # * <tt>:only</tt> - In each actions the scope is applied. By default is :all. | |
| 115 | + # | |
| 116 | + # * <tt>:except</tt> - In each actions the scope is not applied. By default is :none. | |
| 117 | + # | |
| 118 | + # * <tt>:key</tt> - The key in the params hash expected to find the scope. | |
| 119 | + # Defaults to the scope name. | |
| 120 | + # | |
| 121 | + # * <tt>:default</tt> - Default value for the scope. Whenever supplied the scope | |
| 122 | + # is always called. This is useful to add easy pagination! | |
| 123 | + # | |
| 124 | + def has_scope(*scopes) | |
| 125 | + options = scopes.extract_options! | |
| 126 | + | |
| 127 | + options.symbolize_keys! | |
| 128 | + options.assert_valid_keys(:boolean, :key, :only, :except, :default) | |
| 129 | + | |
| 130 | + if self.scopes_configuration.empty? | |
| 131 | + include HasScopeHelpers | |
| 132 | + helper_method :current_scopes | |
| 133 | + end | |
| 134 | + | |
| 135 | + scopes.each do |scope| | |
| 136 | + self.scopes_configuration[scope] ||= {} | |
| 137 | + self.scopes_configuration[scope][:key] = options[:key] || scope | |
| 138 | + self.scopes_configuration[scope][:only] = Array(options[:only]) | |
| 139 | + self.scopes_configuration[scope][:except] = Array(options[:except]) | |
| 140 | + self.scopes_configuration[scope][:boolean] = options[:boolean] if options.key?(:boolean) | |
| 141 | + self.scopes_configuration[scope][:default] = options[:default] if options.key?(:default) | |
| 142 | + end | |
| 143 | + end | |
| 144 | + | |
| 145 | + # Defines that this controller belongs to another resource. | |
| 146 | + # | |
| 147 | + # belongs_to :projects | |
| 148 | + # | |
| 149 | + # == Options | |
| 150 | + # | |
| 151 | + # * <tt>:parent_class</tt> - Allows you to specify what is the parent class. | |
| 152 | + # | |
| 153 | + # belongs_to :project, :parent_class => AdminProject | |
| 154 | + # | |
| 155 | + # * <tt>:class_name</tt> - Also allows you to specify the parent class, but you should | |
| 156 | + # give a string. Added for ActiveRecord belongs to compatibility. | |
| 157 | + # | |
| 158 | + # * <tt>:instance_name</tt> - The instance variable name. By default is the name of the association. | |
| 159 | + # | |
| 160 | + # belongs_to :project, :instance_name => :my_project | |
| 161 | + # | |
| 162 | + # * <tt>:finder</tt> - Specifies which method should be called to instantiate the parent. | |
| 163 | + # | |
| 164 | + # belongs_to :project, :finder => :find_by_title! | |
| 165 | + # | |
| 166 | + # This will make your projects be instantiated as: | |
| 167 | + # | |
| 168 | + # Project.find_by_title!(params[:project_id]) | |
| 169 | + # | |
| 170 | + # Instead of: | |
| 171 | + # | |
| 172 | + # Project.find(params[:project_id]) | |
| 173 | + # | |
| 174 | + # * <tt>:param</tt> - Allows you to specify params key to retrieve the id. | |
| 175 | + # Default is :association_id, which in this case is :project_id. | |
| 176 | + # | |
| 177 | + # * <tt>:route_name</tt> - Allows you to specify what is the route name in your url | |
| 178 | + # helper. By default is association name. | |
| 179 | + # | |
| 180 | + # * <tt>:collection_name</tt> - Tell how to retrieve the next collection. Let's | |
| 181 | + # suppose you have Tasks which belongs to Projects | |
| 182 | + # which belongs to companies. This will do somewhere | |
| 183 | + # down the road: | |
| 184 | + # | |
| 185 | + # @company.projects | |
| 186 | + # | |
| 187 | + # But if you want to retrieve instead: | |
| 188 | + # | |
| 189 | + # @company.admin_projects | |
| 190 | + # | |
| 191 | + # You supply the collection name. | |
| 192 | + # | |
| 193 | + # * <tt>:polymorphic</tt> - Tell the association is polymorphic. | |
| 194 | + # | |
| 195 | + # * <tt>:singleton</tt> - Tell it's a singleton association. | |
| 196 | + # | |
| 197 | + # * <tt>:optional</tt> - Tell the association is optional (it's a special | |
| 198 | + # type of polymorphic association) | |
| 199 | + # | |
| 200 | + def belongs_to(*symbols, &block) | |
| 201 | + options = symbols.extract_options! | |
| 202 | + | |
| 203 | + options.symbolize_keys! | |
| 204 | + options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param, | |
| 205 | + :finder, :route_name, :collection_name, :singleton, | |
| 206 | + :polymorphic, :optional) | |
| 207 | + | |
| 208 | + optional = options.delete(:optional) | |
| 209 | + singleton = options.delete(:singleton) | |
| 210 | + polymorphic = options.delete(:polymorphic) | |
| 211 | + | |
| 212 | + include BelongsToHelpers if self.parents_symbols.empty? | |
| 213 | + | |
| 214 | + acts_as_singleton! if singleton | |
| 215 | + acts_as_polymorphic! if polymorphic || optional | |
| 216 | + | |
| 217 | + raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty? | |
| 218 | + raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty? | |
| 219 | + | |
| 220 | + symbols.each do |symbol| | |
| 221 | + symbol = symbol.to_sym | |
| 222 | + | |
| 223 | + if polymorphic || optional | |
| 224 | + self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic) | |
| 225 | + self.resources_configuration[:polymorphic][:symbols] << symbol | |
| 226 | + self.resources_configuration[:polymorphic][:optional] ||= optional | |
| 227 | + else | |
| 228 | + self.parents_symbols << symbol | |
| 229 | + end | |
| 230 | + | |
| 231 | + config = self.resources_configuration[symbol] = {} | |
| 232 | + config[:parent_class] = options.delete(:parent_class) | |
| 233 | + config[:parent_class] ||= (options.delete(:class_name) || symbol).to_s.classify.constantize rescue nil | |
| 234 | + config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym | |
| 235 | + config[:instance_name] = options.delete(:instance_name) || symbol | |
| 236 | + config[:param] = options.delete(:param) || :"#{symbol}_id" | |
| 237 | + config[:finder] = options.delete(:finder) || :find | |
| 238 | + config[:route_name] = options.delete(:route_name) || symbol | |
| 239 | + end | |
| 240 | + | |
| 241 | + if block_given? | |
| 242 | + class_eval(&block) | |
| 243 | + else | |
| 244 | + create_resources_url_helpers! | |
| 245 | + end | |
| 246 | + end | |
| 247 | + alias :nested_belongs_to :belongs_to | |
| 248 | + | |
| 249 | + # A quick method to declare polymorphic belongs to. | |
| 250 | + # | |
| 251 | + def polymorphic_belongs_to(*symbols, &block) | |
| 252 | + options = symbols.extract_options! | |
| 253 | + options.merge!(:polymorphic => true) | |
| 254 | + belongs_to(*symbols << options, &block) | |
| 255 | + end | |
| 256 | + | |
| 257 | + # A quick method to declare singleton belongs to. | |
| 258 | + # | |
| 259 | + def singleton_belongs_to(*symbols, &block) | |
| 260 | + options = symbols.extract_options! | |
| 261 | + options.merge!(:singleton => true) | |
| 262 | + belongs_to(*symbols << options, &block) | |
| 263 | + end | |
| 264 | + | |
| 265 | + # A quick method to declare optional belongs to. | |
| 266 | + # | |
| 267 | + def optional_belongs_to(*symbols, &block) | |
| 268 | + options = symbols.extract_options! | |
| 269 | + options.merge!(:optional => true) | |
| 270 | + belongs_to(*symbols << options, &block) | |
| 271 | + end | |
| 272 | + | |
| 273 | + private | |
| 274 | + | |
| 275 | + def acts_as_singleton! #:nodoc: | |
| 276 | + unless self.resources_configuration[:self][:singleton] | |
| 277 | + self.resources_configuration[:self][:singleton] = true | |
| 278 | + include SingletonHelpers | |
| 279 | + actions :all, :except => :index | |
| 280 | + end | |
| 281 | + end | |
| 282 | + | |
| 283 | + def acts_as_polymorphic! #:nodoc: | |
| 284 | + unless self.parents_symbols.include?(:polymorphic) | |
| 285 | + include PolymorphicHelpers | |
| 286 | + helper_method :parent, :parent_type, :parent_class, :parent? | |
| 287 | + end | |
| 288 | + end | |
| 289 | + | |
| 290 | + # Initialize resources class accessors and set their default values. | |
| 291 | + # | |
| 292 | + def initialize_resources_class_accessors! #:nodoc: | |
| 293 | + # Initialize resource class | |
| 294 | + self.resource_class = begin | |
| 295 | + self.controller_name.classify.constantize | |
| 296 | + rescue NameError | |
| 297 | + nil | |
| 298 | + end | |
| 299 | + | |
| 300 | + # Initialize resources configuration hash | |
| 301 | + self.resources_configuration ||= {} | |
| 302 | + config = self.resources_configuration[:self] = {} | |
| 303 | + config[:collection_name] = self.controller_name.to_sym | |
| 304 | + config[:instance_name] = self.controller_name.singularize.to_sym | |
| 305 | + | |
| 306 | + config[:route_collection_name] = config[:collection_name] | |
| 307 | + config[:route_instance_name] = config[:instance_name] | |
| 308 | + | |
| 309 | + # Deal with namespaced controllers | |
| 310 | + namespaces = self.controller_path.split('/')[0..-2] | |
| 311 | + config[:route_prefix] = namespaces.join('_') unless namespaces.empty? | |
| 312 | + | |
| 313 | + # Initialize polymorphic, singleton, scopes and belongs_to parameters | |
| 314 | + self.parents_symbols ||= [] | |
| 315 | + self.scopes_configuration ||= {} | |
| 316 | + self.resources_configuration[:polymorphic] ||= { :symbols => [], :optional => false } | |
| 317 | + end | |
| 318 | + | |
| 319 | + # Hook called on inheritance. | |
| 320 | + # | |
| 321 | + def inherited(base) #:nodoc: | |
| 322 | + super(base) | |
| 323 | + base.send :initialize_resources_class_accessors! | |
| 324 | + base.send :create_resources_url_helpers! | |
| 325 | + end | |
| 326 | + | |
| 327 | + end | |
| 328 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb
0 → 100644
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +module InheritedResources | |
| 2 | + # = Dumb Responder | |
| 3 | + # | |
| 4 | + # This responder discards all messages sent to him. | |
| 5 | + # | |
| 6 | + class DumbResponder | |
| 7 | + | |
| 8 | + instance_methods.each do |m| | |
| 9 | + undef_method m unless m =~ /^__/ | |
| 10 | + end | |
| 11 | + | |
| 12 | + # This is like a good husband, he will just listen everything that his wife | |
| 13 | + # says (which is a lot) without complaining. :) | |
| 14 | + # | |
| 15 | + def method_missing(*args) | |
| 16 | + nil | |
| 17 | + end | |
| 18 | + | |
| 19 | + end | |
| 20 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | +module InheritedResources | |
| 2 | + | |
| 3 | + # = has_scopes | |
| 4 | + # | |
| 5 | + # This module in included in your controller when has_scope is called for the | |
| 6 | + # first time. | |
| 7 | + # | |
| 8 | + module HasScopeHelpers | |
| 9 | + TRUE_VALUES = ["true", true, "1", 1] unless self.const_defined?(:TRUE_VALUES) | |
| 10 | + | |
| 11 | + protected | |
| 12 | + | |
| 13 | + # Overwrites apply to scope to implement default scope logic. | |
| 14 | + # | |
| 15 | + def apply_scope_to(target_object) #:nodoc: | |
| 16 | + @current_scopes ||= {} | |
| 17 | + | |
| 18 | + self.scopes_configuration.each do |scope, options| | |
| 19 | + next unless apply_scope_to_action?(options) | |
| 20 | + key = options[:key] | |
| 21 | + | |
| 22 | + if params.key?(key) | |
| 23 | + value, call_scope = params[key], true | |
| 24 | + elsif options.key?(:default) | |
| 25 | + value, call_scope = options[:default], true | |
| 26 | + value = value.call(self) if value.is_a?(Proc) | |
| 27 | + end | |
| 28 | + | |
| 29 | + if call_scope | |
| 30 | + @current_scopes[key] = value | |
| 31 | + | |
| 32 | + if options[:boolean] | |
| 33 | + target_object = target_object.send(scope) if TRUE_VALUES.include?(value) | |
| 34 | + else | |
| 35 | + target_object = target_object.send(scope, value) | |
| 36 | + end | |
| 37 | + end | |
| 38 | + end | |
| 39 | + | |
| 40 | + target_object | |
| 41 | + end | |
| 42 | + | |
| 43 | + # Given an options with :only and :except arrays, check if the scope | |
| 44 | + # can be performed in the current action. | |
| 45 | + # | |
| 46 | + def apply_scope_to_action?(options) #:nodoc: | |
| 47 | + if options[:only].empty? | |
| 48 | + if options[:except].empty? | |
| 49 | + true | |
| 50 | + else | |
| 51 | + !options[:except].include?(action_name.to_sym) | |
| 52 | + end | |
| 53 | + else | |
| 54 | + options[:only].include?(action_name.to_sym) | |
| 55 | + end | |
| 56 | + end | |
| 57 | + | |
| 58 | + # Returns the scopes used in this action. | |
| 59 | + # | |
| 60 | + def current_scopes | |
| 61 | + @current_scopes || {} | |
| 62 | + end | |
| 63 | + | |
| 64 | + end | |
| 65 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,156 @@ |
| 1 | +module InheritedResources | |
| 2 | + | |
| 3 | + # = polymorphic associations | |
| 4 | + # | |
| 5 | + # In some cases you have a resource that belongs to two different resources | |
| 6 | + # but not at the same time. For example, let's suppose you have File, Message | |
| 7 | + # and Task as resources and they are all commentable. | |
| 8 | + # | |
| 9 | + # Polymorphic associations allows you to create just one controller that will | |
| 10 | + # deal with each case. | |
| 11 | + # | |
| 12 | + # class Comment < InheritedResources::Base | |
| 13 | + # belongs_to :file, :message, :task, :polymorphic => true | |
| 14 | + # end | |
| 15 | + # | |
| 16 | + # Your routes should be something like: | |
| 17 | + # | |
| 18 | + # m.resources :files, :has_many => :comments #=> /files/13/comments | |
| 19 | + # m.resources :tasks, :has_many => :comments #=> /tasks/17/comments | |
| 20 | + # m.resources :messages, :has_many => :comments #=> /messages/11/comments | |
| 21 | + # | |
| 22 | + # When using polymorphic associations, you get some free helpers: | |
| 23 | + # | |
| 24 | + # parent? #=> true | |
| 25 | + # parent_type #=> :task | |
| 26 | + # parent_class #=> Task | |
| 27 | + # parent #=> @task | |
| 28 | + # | |
| 29 | + # This polymorphic controllers thing is a great idea by James Golick and he | |
| 30 | + # built it in resource_controller. Here is just a re-implementation. | |
| 31 | + # | |
| 32 | + # = optional polymorphic associations | |
| 33 | + # | |
| 34 | + # Let's take another break from ProjectsController. Let's suppose we are | |
| 35 | + # building a store, which sell products. | |
| 36 | + # | |
| 37 | + # On the website, we can show all products, but also products scoped to | |
| 38 | + # categories, brands, users. In this case case, the association is optional, and | |
| 39 | + # we deal with it in the following way: | |
| 40 | + # | |
| 41 | + # class ProductsController < InheritedResources::Base | |
| 42 | + # belongs_to :category, :brand, :user, :polymorphic => true, :optional => true | |
| 43 | + # end | |
| 44 | + # | |
| 45 | + # This will handle all those urls properly: | |
| 46 | + # | |
| 47 | + # /products/1 | |
| 48 | + # /categories/2/products/5 | |
| 49 | + # /brands/10/products/3 | |
| 50 | + # /user/13/products/11 | |
| 51 | + # | |
| 52 | + # = nested polymorphic associations | |
| 53 | + # | |
| 54 | + # You can have polymorphic associations with nested resources. Let's suppose | |
| 55 | + # that our File, Task and Message resources in the previous example belongs to | |
| 56 | + # a project. | |
| 57 | + # | |
| 58 | + # This way we can have: | |
| 59 | + # | |
| 60 | + # class CommentsController < InheritedResources::Base | |
| 61 | + # belongs_to :project { | |
| 62 | + # belongs_to :file, :message, :task, :polymorphic => true | |
| 63 | + # } | |
| 64 | + # end | |
| 65 | + # | |
| 66 | + # Or: | |
| 67 | + # | |
| 68 | + # class CommentsController < InheritedResources::Base | |
| 69 | + # nested_belongs_to :project | |
| 70 | + # nested_belongs_to :file, :message, :task, :polymorphic => true | |
| 71 | + # end | |
| 72 | + # | |
| 73 | + # Choose the syntax that makes more sense to you. :) | |
| 74 | + # | |
| 75 | + # Finally your routes should be something like: | |
| 76 | + # | |
| 77 | + # map.resources :projects do |m| | |
| 78 | + # m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments | |
| 79 | + # m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments | |
| 80 | + # m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments | |
| 81 | + # end | |
| 82 | + # | |
| 83 | + # The helpers work in the same way as above. | |
| 84 | + # | |
| 85 | + module PolymorphicHelpers | |
| 86 | + | |
| 87 | + protected | |
| 88 | + | |
| 89 | + # Returns the parent type. A Comments class can have :task, :file, :note | |
| 90 | + # as parent types. | |
| 91 | + # | |
| 92 | + def parent_type | |
| 93 | + @parent_type | |
| 94 | + end | |
| 95 | + | |
| 96 | + def parent_class | |
| 97 | + parent.class if @parent_type | |
| 98 | + end | |
| 99 | + | |
| 100 | + # Returns the parent object. They are also available with the instance | |
| 101 | + # variable name: @task, @file, @note... | |
| 102 | + # | |
| 103 | + def parent | |
| 104 | + instance_variable_get("@#{@parent_type}") if @parent_type | |
| 105 | + end | |
| 106 | + | |
| 107 | + # If the polymorphic association is optional, we might not have a parent. | |
| 108 | + # | |
| 109 | + def parent? | |
| 110 | + if resources_configuration[:polymorphic][:optional] | |
| 111 | + parents_symbols.size > 1 || !@parent_type.nil? | |
| 112 | + else | |
| 113 | + true | |
| 114 | + end | |
| 115 | + end | |
| 116 | + | |
| 117 | + private | |
| 118 | + | |
| 119 | + # Maps parents_symbols to build association chain. | |
| 120 | + # | |
| 121 | + # If the parents_symbols find :polymorphic, it goes through the | |
| 122 | + # params keys to see which polymorphic parent matches the given params. | |
| 123 | + # | |
| 124 | + # When optional is given, it does not raise errors if the polymorphic | |
| 125 | + # params are missing. | |
| 126 | + # | |
| 127 | + def symbols_for_association_chain #:nodoc: | |
| 128 | + polymorphic_config = resources_configuration[:polymorphic] | |
| 129 | + | |
| 130 | + parents_symbols.map do |symbol| | |
| 131 | + if symbol == :polymorphic | |
| 132 | + params_keys = params.keys | |
| 133 | + | |
| 134 | + key = polymorphic_config[:symbols].find do |poly| | |
| 135 | + params_keys.include? resources_configuration[poly][:param].to_s | |
| 136 | + end | |
| 137 | + | |
| 138 | + if key.nil? | |
| 139 | + raise ScriptError, "Could not find param for polymorphic association. | |
| 140 | + The request params keys are #{params.keys.inspect} | |
| 141 | + and the polymorphic associations are | |
| 142 | + #{polymorphic_symbols.inspect}." unless polymorphic_config[:optional] | |
| 143 | + | |
| 144 | + nil | |
| 145 | + else | |
| 146 | + @parent_type = key.to_sym | |
| 147 | + end | |
| 148 | + else | |
| 149 | + symbol | |
| 150 | + end | |
| 151 | + end.compact | |
| 152 | + end | |
| 153 | + | |
| 154 | + end | |
| 155 | +end | |
| 156 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb
0 → 100644
| ... | ... | @@ -0,0 +1,339 @@ |
| 1 | +module ActionController | |
| 2 | + # Provides an extension for Rails respond_to by expading MimeResponds::Responder | |
| 3 | + # and adding respond_to class method and respond_with instance method. | |
| 4 | + # | |
| 5 | + class Base | |
| 6 | + | |
| 7 | + protected | |
| 8 | + # Defines respond_to method to store formats that are rendered by default. | |
| 9 | + # | |
| 10 | + # Examples: | |
| 11 | + # | |
| 12 | + # respond_to :html, :xml, :json | |
| 13 | + # | |
| 14 | + # All actions on your controller will respond to :html, :xml and :json. | |
| 15 | + # But if you want to specify it based on your actions, you can use only and | |
| 16 | + # except: | |
| 17 | + # | |
| 18 | + # respond_to :html | |
| 19 | + # respond_to :xml, :json, :except => [ :edit ] | |
| 20 | + # | |
| 21 | + # The definition above explicits that all actions respond to :html. And all | |
| 22 | + # actions except :edit respond to :xml and :json. | |
| 23 | + # | |
| 24 | + # You can specify also only parameters: | |
| 25 | + # | |
| 26 | + # respond_to :rjs, :only => :create | |
| 27 | + # | |
| 28 | + # Which would be the same as: | |
| 29 | + # | |
| 30 | + # respond_to :rjs => :create | |
| 31 | + # | |
| 32 | + def self.respond_to(*formats) | |
| 33 | + options = formats.extract_options! | |
| 34 | + formats_hash = {} | |
| 35 | + | |
| 36 | + only_actions = Array(options.delete(:only)) | |
| 37 | + except_actions = Array(options.delete(:except)) | |
| 38 | + | |
| 39 | + only_actions.map!{ |a| a.to_sym } | |
| 40 | + except_actions.map!{ |a| a.to_sym } | |
| 41 | + | |
| 42 | + formats.each do |format| | |
| 43 | + formats_hash[format.to_sym] = {} | |
| 44 | + formats_hash[format.to_sym][:only] = only_actions unless only_actions.empty? | |
| 45 | + formats_hash[format.to_sym][:except] = except_actions unless except_actions.empty? | |
| 46 | + end | |
| 47 | + | |
| 48 | + options.each do |format, actions| | |
| 49 | + formats_hash[format.to_sym] = {} | |
| 50 | + next if actions == :all || actions == 'all' | |
| 51 | + | |
| 52 | + actions = Array(actions) | |
| 53 | + actions.map!{ |a| a.to_sym } | |
| 54 | + | |
| 55 | + formats_hash[format.to_sym][:only] = actions unless actions.empty? | |
| 56 | + end | |
| 57 | + | |
| 58 | + write_inheritable_hash(:formats_for_respond_to, formats_hash) | |
| 59 | + end | |
| 60 | + class_inheritable_reader :formats_for_respond_to | |
| 61 | + | |
| 62 | + # Method to clear all respond_to declared until the current controller. | |
| 63 | + # This is like freeing the controller from the inheritance chain. :) | |
| 64 | + # | |
| 65 | + def self.clear_respond_to! | |
| 66 | + formats = formats_for_respond_to | |
| 67 | + formats.each { |k,v| formats[k] = { :only => [] } } | |
| 68 | + write_inheritable_hash(:formats_for_respond_to, formats) | |
| 69 | + end | |
| 70 | + | |
| 71 | + # By default, responds only to :html | |
| 72 | + respond_to :html | |
| 73 | + | |
| 74 | + # If ApplicationController is already defined around here, we recriate | |
| 75 | + # the formats_for_respond_to hash. Since we respond only to :html by | |
| 76 | + # default, this is as easy as settings the :formats_for_respond_to key | |
| 77 | + # to {:html=>{}}. | |
| 78 | + # | |
| 79 | + if defined?(ApplicationController) | |
| 80 | + if inheritable = ApplicationController.instance_variable_get("@inheritable_attributes") | |
| 81 | + inheritable.merge!(:formats_for_respond_to => {:html => {}}) if inheritable | |
| 82 | + end | |
| 83 | + end | |
| 84 | + | |
| 85 | + # respond_with accepts an object and tries to render a view based in the | |
| 86 | + # controller and actions that called respond_with. If the view cannot be | |
| 87 | + # found, it will try to call :to_format in the object. | |
| 88 | + # | |
| 89 | + # class ProjectsController < ApplicationController | |
| 90 | + # respond_to :html, :xml | |
| 91 | + # | |
| 92 | + # def show | |
| 93 | + # @project = Project.find(:id) | |
| 94 | + # respond_with(@project) | |
| 95 | + # end | |
| 96 | + # end | |
| 97 | + # | |
| 98 | + # When the client request a xml, we will check first for projects/show.xml | |
| 99 | + # if it can't be found, we will call :to_xml in the object @project. If the | |
| 100 | + # object eventually doesn't respond to :to_xml it will render 404. | |
| 101 | + # | |
| 102 | + # If you want to overwrite the formats specified in the class, you can | |
| 103 | + # send your new formats using the options :to. | |
| 104 | + # | |
| 105 | + # def show | |
| 106 | + # @project = Project.find(:id) | |
| 107 | + # respond_with(@project, :to => :json) | |
| 108 | + # end | |
| 109 | + # | |
| 110 | + # That means that this action will ONLY reply to json requests. | |
| 111 | + # | |
| 112 | + # All other options sent will be forwarded to the render method. So you can | |
| 113 | + # do: | |
| 114 | + # | |
| 115 | + # def create | |
| 116 | + # # ... | |
| 117 | + # if @project.save | |
| 118 | + # respond_with(@project, :status => :ok, :location => @project) | |
| 119 | + # else | |
| 120 | + # respond_with(@project.errors, :status => :unprocessable_entity) | |
| 121 | + # end | |
| 122 | + # end | |
| 123 | + # | |
| 124 | + # respond_with does not accept blocks, if you want advanced configurations | |
| 125 | + # check respond_to method sending :with => @object as option. | |
| 126 | + # | |
| 127 | + # Returns true if anything is rendered. Returns false otherwise. | |
| 128 | + # | |
| 129 | + def respond_with(object, options = {}) | |
| 130 | + attempt_to_respond = false | |
| 131 | + | |
| 132 | + responder = options.delete(:responder) || Responder.new(self) | |
| 133 | + skip_not_acceptable = options.delete(:skip_not_acceptable) | |
| 134 | + skip_default_template = options.delete(:skip_default_template) | |
| 135 | + | |
| 136 | + mime_types = Array(options.delete(:to)) | |
| 137 | + mime_types.map!{ |mime| mime.to_sym } | |
| 138 | + | |
| 139 | + for priority in responder.mime_type_priority | |
| 140 | + if !skip_default_template && priority == Mime::ALL && respond_to_default_template?(responder) | |
| 141 | + render options.merge(:action => action_name) | |
| 142 | + return true | |
| 143 | + | |
| 144 | + elsif responder.action_respond_to_format?(priority.to_sym, mime_types) | |
| 145 | + attempt_to_respond = true | |
| 146 | + response.template.template_format = priority.to_sym | |
| 147 | + response.content_type = priority.to_s | |
| 148 | + | |
| 149 | + if template_exists? | |
| 150 | + render options.merge(:action => action_name) | |
| 151 | + return true | |
| 152 | + elsif object.respond_to?(:"to_#{priority.to_sym}") | |
| 153 | + render options.merge(:text => object.send(:"to_#{priority.to_sym}")) | |
| 154 | + return true | |
| 155 | + end | |
| 156 | + end | |
| 157 | + end | |
| 158 | + | |
| 159 | + # If we got here we could not render the object. But if attempted to | |
| 160 | + # render (this means, the format sent by the client was valid) we should | |
| 161 | + # render a 404. | |
| 162 | + # | |
| 163 | + # If we even didn't attempt to respond, we respond :not_acceptable | |
| 164 | + # unless is told otherwise. | |
| 165 | + # | |
| 166 | + if attempt_to_respond | |
| 167 | + render :text => '404 Not Found', :status => 404 | |
| 168 | + return true | |
| 169 | + elsif !skip_not_acceptable | |
| 170 | + head :not_acceptable | |
| 171 | + return false | |
| 172 | + end | |
| 173 | + | |
| 174 | + return false | |
| 175 | + end | |
| 176 | + | |
| 177 | + # Extends respond_to behaviour. | |
| 178 | + # | |
| 179 | + # You can now pass objects using the options :with. | |
| 180 | + # | |
| 181 | + # respond_to(:html, :xml, :rjs, :with => @project) | |
| 182 | + # | |
| 183 | + # If you pass an object and send any block, it's exactly the same as: | |
| 184 | + # | |
| 185 | + # respond_with(@project, :to => [:html, :xml, :rjs]) | |
| 186 | + # | |
| 187 | + # But the main difference of respond_to and respond_with is that the first | |
| 188 | + # allows further customizations: | |
| 189 | + # | |
| 190 | + # respond_to(:html, :with => @project) do |format| | |
| 191 | + # format.xml { render :xml => @project.errors } | |
| 192 | + # end | |
| 193 | + # | |
| 194 | + # It's the same as: | |
| 195 | + # | |
| 196 | + # 1. When responding to html, execute respond_with(@object). | |
| 197 | + # 2. When accessing a xml, execute the block given. | |
| 198 | + # | |
| 199 | + # Formats defined in blocks have precedence to formats sent as arguments. | |
| 200 | + # In other words, if you pass a format as argument and as block, the block | |
| 201 | + # will always be executed. | |
| 202 | + # | |
| 203 | + # And as in respond_with, all extra options sent will be forwarded to | |
| 204 | + # the render method: | |
| 205 | + # | |
| 206 | + # respond_to(:with => @projects.errors, :status => :unprocessable_entity) do |format| | |
| 207 | + # format.html { render :template => 'new' } | |
| 208 | + # end | |
| 209 | + # | |
| 210 | + # It also accepts an option called prioritize. It allows you to put a | |
| 211 | + # format as first, and then when Mime::ALL is sent, it will be the one | |
| 212 | + # used as response. | |
| 213 | + # | |
| 214 | + def respond_to(*types, &block) | |
| 215 | + options = types.extract_options! | |
| 216 | + | |
| 217 | + object = options.delete(:with) | |
| 218 | + responder = options.delete(:responder) || Responder.new(self) | |
| 219 | + prioritize = options.delete(:prioritize) | |
| 220 | + | |
| 221 | + if object.nil? | |
| 222 | + block ||= lambda { |responder| types.each { |type| responder.send(type) } } | |
| 223 | + block.call(responder) | |
| 224 | + responder.respond | |
| 225 | + return true | |
| 226 | + else | |
| 227 | + # Even if Mime::ALL is sent by the client, we do not respond_to it now. | |
| 228 | + # This is done using calling :respond_except_any instead of :respond. | |
| 229 | + # | |
| 230 | + if block_given? | |
| 231 | + block.call(responder) | |
| 232 | + return true if responder.respond_except_any | |
| 233 | + end | |
| 234 | + | |
| 235 | + # If the block includes the default template format, we don't render | |
| 236 | + # the default template (which uses the default_template_format). | |
| 237 | + options.merge!(:to => types, :responder => responder, :skip_not_acceptable => true, | |
| 238 | + :skip_default_template => responder.order.include?(default_template_format)) | |
| 239 | + | |
| 240 | + if respond_with(object, options) | |
| 241 | + return true | |
| 242 | + elsif block_given? | |
| 243 | + responder.prioritize(prioritize) if prioritize | |
| 244 | + return true if responder.respond_any | |
| 245 | + end | |
| 246 | + end | |
| 247 | + | |
| 248 | + head :not_acceptable | |
| 249 | + return false | |
| 250 | + end | |
| 251 | + | |
| 252 | + private | |
| 253 | + | |
| 254 | + unless ActionController::Base.private_instance_methods.include?('template_exists?') || | |
| 255 | + ActionController::Base.private_instance_methods.include?(:template_exists?) | |
| 256 | + | |
| 257 | + # Define template_exists? for Rails 2.3 | |
| 258 | + def template_exists? | |
| 259 | + default_template ? true : false | |
| 260 | + rescue ActionView::MissingTemplate | |
| 261 | + false | |
| 262 | + end | |
| 263 | + end | |
| 264 | + | |
| 265 | + # We respond to the default template if it's a valid format AND the template | |
| 266 | + # exists. | |
| 267 | + # | |
| 268 | + def respond_to_default_template?(responder) #:nodoc: | |
| 269 | + responder.action_respond_to_format?(default_template_format) && template_exists? | |
| 270 | + end | |
| 271 | + | |
| 272 | + end | |
| 273 | + | |
| 274 | + module MimeResponds #:nodoc: | |
| 275 | + class Responder #:nodoc: | |
| 276 | + | |
| 277 | + attr_reader :mime_type_priority, :order | |
| 278 | + | |
| 279 | + # Similar as respond but if we can't find a valid mime type, we do not | |
| 280 | + # send :not_acceptable message as head and it does not respond to | |
| 281 | + # Mime::ALL in any case. | |
| 282 | + # | |
| 283 | + def respond_except_any | |
| 284 | + for priority in @mime_type_priority | |
| 285 | + next if priority == Mime::ALL | |
| 286 | + | |
| 287 | + if @responses[priority] | |
| 288 | + @responses[priority].call | |
| 289 | + return true | |
| 290 | + end | |
| 291 | + end | |
| 292 | + | |
| 293 | + false | |
| 294 | + end | |
| 295 | + | |
| 296 | + # Respond to the first format given if Mime::ALL is included in the | |
| 297 | + # mime type priorites. This is the behaviour expected when the client | |
| 298 | + # sends "*/*" as mime type. | |
| 299 | + # | |
| 300 | + def respond_any | |
| 301 | + any = @responses[@order.include?(Mime::ALL) ? Mime::ALL : @order.first] | |
| 302 | + | |
| 303 | + if any && @mime_type_priority.include?(Mime::ALL) | |
| 304 | + any.call | |
| 305 | + return true | |
| 306 | + end | |
| 307 | + end | |
| 308 | + | |
| 309 | + # Receives an format and checks if the current action responds to | |
| 310 | + # the given format. If additional mimes are sent, only them are checked. | |
| 311 | + # | |
| 312 | + def action_respond_to_format?(format, additional_mimes = []) | |
| 313 | + if !additional_mimes.blank? | |
| 314 | + additional_mimes.include?(format.to_sym) | |
| 315 | + elsif formats = @controller.formats_for_respond_to[format.to_sym] | |
| 316 | + if formats[:only] | |
| 317 | + formats[:only].include?(@controller.action_name.to_sym) | |
| 318 | + elsif formats[:except] | |
| 319 | + !formats[:except].include?(@controller.action_name.to_sym) | |
| 320 | + else | |
| 321 | + true | |
| 322 | + end | |
| 323 | + else | |
| 324 | + false | |
| 325 | + end | |
| 326 | + end | |
| 327 | + | |
| 328 | + # Makes a given format the first in the @order array. | |
| 329 | + # | |
| 330 | + def prioritize(format) | |
| 331 | + if index = @order.index(format) | |
| 332 | + @order.unshift(@order.delete_at(index)) | |
| 333 | + end | |
| 334 | + @order | |
| 335 | + end | |
| 336 | + | |
| 337 | + end | |
| 338 | + end | |
| 339 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,95 @@ |
| 1 | +module InheritedResources | |
| 2 | + | |
| 3 | + # = singleton | |
| 4 | + # | |
| 5 | + # Singletons are usually used in associations which are related through has_one | |
| 6 | + # and belongs_to. You declare those associations like this: | |
| 7 | + # | |
| 8 | + # class ManagersController < InheritedResources::Base | |
| 9 | + # belongs_to :project, :singleton => true | |
| 10 | + # end | |
| 11 | + # | |
| 12 | + # But in some cases, like an AccountsController, you have a singleton object | |
| 13 | + # that is not necessarily associated with another: | |
| 14 | + # | |
| 15 | + # class AccountsController < InheritedResources::Base | |
| 16 | + # defaults :singleton => true | |
| 17 | + # end | |
| 18 | + # | |
| 19 | + # Besides that, you should overwrite the methods :resource and :build_resource | |
| 20 | + # to make it work properly: | |
| 21 | + # | |
| 22 | + # class AccountsController < InheritedResources::Base | |
| 23 | + # defaults :singleton => true | |
| 24 | + # | |
| 25 | + # protected | |
| 26 | + # def resource | |
| 27 | + # @current_user.account | |
| 28 | + # end | |
| 29 | + # | |
| 30 | + # def build_resource(attributes = {}) | |
| 31 | + # Account.new(attributes) | |
| 32 | + # end | |
| 33 | + # end | |
| 34 | + # | |
| 35 | + # When you have a singleton controller, the action index is removed. | |
| 36 | + # | |
| 37 | + module SingletonHelpers | |
| 38 | + | |
| 39 | + protected | |
| 40 | + | |
| 41 | + # Singleton methods does not deal with collections. | |
| 42 | + # | |
| 43 | + def collection | |
| 44 | + nil | |
| 45 | + end | |
| 46 | + | |
| 47 | + # Overwrites how singleton deals with resource. | |
| 48 | + # | |
| 49 | + # If you are going to overwrite it, you should notice that the | |
| 50 | + # end_of_association_chain here is not the same as in default belongs_to. | |
| 51 | + # | |
| 52 | + # class TasksController < InheritedResources::Base | |
| 53 | + # belongs_to :project | |
| 54 | + # end | |
| 55 | + # | |
| 56 | + # In this case, the association chain would be: | |
| 57 | + # | |
| 58 | + # Project.find(params[:project_id]).tasks | |
| 59 | + # | |
| 60 | + # So you would just have to call find(:all) at the end of association | |
| 61 | + # chain. And this is what happened. | |
| 62 | + # | |
| 63 | + # In singleton controllers: | |
| 64 | + # | |
| 65 | + # class ManagersController < InheritedResources::Base | |
| 66 | + # belongs_to :project, :singleton => true | |
| 67 | + # end | |
| 68 | + # | |
| 69 | + # The association chain will be: | |
| 70 | + # | |
| 71 | + # Project.find(params[:project_id]) | |
| 72 | + # | |
| 73 | + # So we have to call manager on it, not find. | |
| 74 | + # | |
| 75 | + def resource | |
| 76 | + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(resource_instance_name)) | |
| 77 | + end | |
| 78 | + | |
| 79 | + private | |
| 80 | + | |
| 81 | + # Returns the appropriated method to build the resource. | |
| 82 | + # | |
| 83 | + def method_for_association_build #:nodoc: | |
| 84 | + :"build_#{resource_instance_name}" | |
| 85 | + end | |
| 86 | + | |
| 87 | + # Sets the method_for_association_chain to nil. See <tt>resource</tt> | |
| 88 | + # above for more information. | |
| 89 | + # | |
| 90 | + def method_for_association_chain #:nodoc: | |
| 91 | + nil | |
| 92 | + end | |
| 93 | + | |
| 94 | + end | |
| 95 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,173 @@ |
| 1 | +module InheritedResources | |
| 2 | + # = URLHelpers | |
| 3 | + # | |
| 4 | + # When you use InheritedResources it creates some UrlHelpers for you. | |
| 5 | + # And they handle everything for you. | |
| 6 | + # | |
| 7 | + # # /posts/1/comments | |
| 8 | + # resource_url # => /posts/1/comments/#{@comment.to_param} | |
| 9 | + # resource_url(comment) # => /posts/1/comments/#{comment.to_param} | |
| 10 | + # new_resource_url # => /posts/1/comments/new | |
| 11 | + # edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit | |
| 12 | + # collection_url # => /posts/1/comments | |
| 13 | + # | |
| 14 | + # # /projects/1/tasks | |
| 15 | + # resource_url # => /products/1/tasks/#{@task.to_param} | |
| 16 | + # resource_url(task) # => /products/1/tasks/#{task.to_param} | |
| 17 | + # new_resource_url # => /products/1/tasks/new | |
| 18 | + # edit_resource_url # => /products/1/tasks/#{@task.to_param}/edit | |
| 19 | + # collection_url # => /products/1/tasks | |
| 20 | + # | |
| 21 | + # # /users | |
| 22 | + # resource_url # => /users/#{@user.to_param} | |
| 23 | + # resource_url(user) # => /users/#{user.to_param} | |
| 24 | + # new_resource_url # => /users/new | |
| 25 | + # edit_resource_url # => /users/#{@user.to_param}/edit | |
| 26 | + # collection_url # => /users | |
| 27 | + # | |
| 28 | + # The nice thing is that those urls are not guessed during runtime. They are | |
| 29 | + # all created when you inherit. | |
| 30 | + # | |
| 31 | + module UrlHelpers | |
| 32 | + | |
| 33 | + # This method hard code url helpers in the class. | |
| 34 | + # | |
| 35 | + # We are doing this because is cheaper than guessing them when our action | |
| 36 | + # is being processed (and even more cheaper when we are using nested | |
| 37 | + # resources). | |
| 38 | + # | |
| 39 | + # When we are using polymorphic associations, those helpers rely on | |
| 40 | + # polymorphic_url Rails helper. | |
| 41 | + # | |
| 42 | + def create_resources_url_helpers! | |
| 43 | + resource_segments, resource_ivars = [], [] | |
| 44 | + resource_config = self.resources_configuration[:self] | |
| 45 | + | |
| 46 | + singleton = self.resources_configuration[:self][:singleton] | |
| 47 | + polymorphic = self.parents_symbols.include?(:polymorphic) | |
| 48 | + | |
| 49 | + # Add route_prefix if any. | |
| 50 | + unless resource_config[:route_prefix].blank? | |
| 51 | + if polymorphic | |
| 52 | + resource_ivars << resource_config[:route_prefix].to_s.inspect | |
| 53 | + else | |
| 54 | + resource_segments << resource_config[:route_prefix] | |
| 55 | + end | |
| 56 | + end | |
| 57 | + | |
| 58 | + # Deal with belongs_to associations and polymorphic associations. | |
| 59 | + # Remember that we don't have to build the segments in polymorphic cases, | |
| 60 | + # because the url will be polymorphic_url. | |
| 61 | + # | |
| 62 | + self.parents_symbols.each do |symbol| | |
| 63 | + if symbol == :polymorphic | |
| 64 | + resource_ivars << :parent | |
| 65 | + else | |
| 66 | + config = self.resources_configuration[symbol] | |
| 67 | + resource_segments << config[:route_name] | |
| 68 | + resource_ivars << :"@#{config[:instance_name]}" | |
| 69 | + end | |
| 70 | + end | |
| 71 | + | |
| 72 | + collection_ivars = resource_ivars.dup | |
| 73 | + collection_segments = resource_segments.dup | |
| 74 | + | |
| 75 | + # This is the default route configuration, later we have to deal with | |
| 76 | + # exception from polymorphic and singleton cases. | |
| 77 | + # | |
| 78 | + collection_segments << resource_config[:route_collection_name] | |
| 79 | + resource_segments << resource_config[:route_instance_name] | |
| 80 | + resource_ivars << :"@#{resource_config[:instance_name]}" | |
| 81 | + | |
| 82 | + # In singleton cases, we do not send the current element instance variable | |
| 83 | + # because the id is not in the URL. For example, we should call: | |
| 84 | + # | |
| 85 | + # project_manager_url(@project) | |
| 86 | + # | |
| 87 | + # Instead of: | |
| 88 | + # | |
| 89 | + # project_manager_url(@project, @manager) | |
| 90 | + # | |
| 91 | + # Another exception in singleton cases is that collection url does not | |
| 92 | + # exist. In such cases, we create the parent collection url. So in the | |
| 93 | + # manager case above, the collection url will be: | |
| 94 | + # | |
| 95 | + # project_url(@project) | |
| 96 | + # | |
| 97 | + # If the singleton does not have a parent, it will default to root_url. | |
| 98 | + # | |
| 99 | + # Finally, polymorphic cases we have to give hints to the polymorphic url | |
| 100 | + # builder. This works by attaching new ivars as symbols or records. | |
| 101 | + # | |
| 102 | + if singleton | |
| 103 | + collection_segments.pop | |
| 104 | + resource_ivars.pop | |
| 105 | + | |
| 106 | + if polymorphic | |
| 107 | + resource_ivars << resource_config[:instance_name].inspect | |
| 108 | + new_ivars = resource_ivars | |
| 109 | + end | |
| 110 | + elsif polymorphic | |
| 111 | + collection_ivars << '(@_resource_class_new ||= resource_class.new)' | |
| 112 | + end | |
| 113 | + | |
| 114 | + generate_url_and_path_helpers nil, :collection, collection_segments, collection_ivars | |
| 115 | + generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars | |
| 116 | + generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars | |
| 117 | + generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars | |
| 118 | + end | |
| 119 | + | |
| 120 | + def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc: | |
| 121 | + ivars = resource_ivars.dup | |
| 122 | + | |
| 123 | + singleton = self.resources_configuration[:self][:singleton] | |
| 124 | + polymorphic = self.parents_symbols.include?(:polymorphic) | |
| 125 | + | |
| 126 | + # If it's not a singleton, ivars are not empty, not a collection or | |
| 127 | + # not a "new" named route, we can pass a resource as argument. | |
| 128 | + # | |
| 129 | + unless singleton || ivars.empty? || name == :collection || prefix == :new | |
| 130 | + ivars.push "(given_args.first || #{ivars.pop})" | |
| 131 | + end | |
| 132 | + | |
| 133 | + # In collection in polymorphic cases, allow an argument to be given as a | |
| 134 | + # replacemente for the parent. | |
| 135 | + # | |
| 136 | + if name == :collection && polymorphic | |
| 137 | + index = ivars.index(:parent) | |
| 138 | + ivars.insert index, "(given_args.first || parent)" | |
| 139 | + ivars.delete(:parent) | |
| 140 | + end | |
| 141 | + | |
| 142 | + # When polymorphic is true, the segments must be replace by :polymorphic | |
| 143 | + # and ivars should be gathered into an array, which is compacted when | |
| 144 | + # optional. | |
| 145 | + # | |
| 146 | + if polymorphic | |
| 147 | + segments = :polymorphic | |
| 148 | + ivars = "[#{ivars.join(', ')}]" | |
| 149 | + ivars << '.compact' if self.resources_configuration[:polymorphic][:optional] | |
| 150 | + else | |
| 151 | + segments = resource_segments.empty? ? 'root' : resource_segments.join('_') | |
| 152 | + ivars = ivars.join(', ') | |
| 153 | + end | |
| 154 | + | |
| 155 | + prefix = prefix ? "#{prefix}_" : '' | |
| 156 | + ivars << (ivars.empty? ? 'given_options' : ', given_options') | |
| 157 | + | |
| 158 | + class_eval <<-URL_HELPERS, __FILE__, __LINE__ | |
| 159 | + protected | |
| 160 | + def #{prefix}#{name}_path(*given_args) | |
| 161 | + given_options = given_args.extract_options! | |
| 162 | + #{prefix}#{segments}_path(#{ivars}) | |
| 163 | + end | |
| 164 | + | |
| 165 | + def #{prefix}#{name}_url(*given_args) | |
| 166 | + given_options = given_args.extract_options! | |
| 167 | + #{prefix}#{segments}_url(#{ivars}) | |
| 168 | + end | |
| 169 | + URL_HELPERS | |
| 170 | + end | |
| 171 | + | |
| 172 | + end | |
| 173 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,134 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Student; | |
| 4 | + def self.human_name; 'Student'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class StudentsController < ApplicationController | |
| 8 | + inherit_resources | |
| 9 | + | |
| 10 | + def edit | |
| 11 | + edit! do |format| | |
| 12 | + format.xml { render :text => 'Render XML' } | |
| 13 | + end | |
| 14 | + end | |
| 15 | + | |
| 16 | + def new | |
| 17 | + @something = 'magical' | |
| 18 | + new! | |
| 19 | + end | |
| 20 | + | |
| 21 | + def create | |
| 22 | + create! do |success, failure| | |
| 23 | + success.html { render :text => "I won't redirect!" } | |
| 24 | + failure.xml { render :text => "I shouldn't be rendered" } | |
| 25 | + end | |
| 26 | + end | |
| 27 | + | |
| 28 | + def update | |
| 29 | + update! do |success, failure| | |
| 30 | + success.html { redirect_to(resource_url) } | |
| 31 | + failure.html { render :text => "I won't render!" } | |
| 32 | + end | |
| 33 | + end | |
| 34 | + | |
| 35 | + def destroy | |
| 36 | + destroy! do |format| | |
| 37 | + format.html { render :text => "Destroyed!" } | |
| 38 | + end | |
| 39 | + end | |
| 40 | + | |
| 41 | +end | |
| 42 | + | |
| 43 | +class AliasesTest < ActionController::TestCase | |
| 44 | + tests StudentsController | |
| 45 | + | |
| 46 | + def test_assignments_before_calling_alias | |
| 47 | + Student.stubs(:new).returns(mock_student) | |
| 48 | + get :new | |
| 49 | + assert_response :success | |
| 50 | + assert_equal 'magical', assigns(:something) | |
| 51 | + end | |
| 52 | + | |
| 53 | + def test_controller_should_render_new | |
| 54 | + Student.stubs(:new).returns(mock_student) | |
| 55 | + get :new | |
| 56 | + assert_response :success | |
| 57 | + assert_equal 'New HTML', @response.body.strip | |
| 58 | + end | |
| 59 | + | |
| 60 | + def test_expose_the_resquested_user_on_edit | |
| 61 | + Student.expects(:find).with('42').returns(mock_student) | |
| 62 | + get :edit, :id => '42' | |
| 63 | + assert_equal mock_student, assigns(:student) | |
| 64 | + assert_response :success | |
| 65 | + end | |
| 66 | + | |
| 67 | + def test_controller_should_render_edit | |
| 68 | + Student.stubs(:find).returns(mock_student) | |
| 69 | + get :edit | |
| 70 | + assert_response :success | |
| 71 | + assert_equal 'Edit HTML', @response.body.strip | |
| 72 | + end | |
| 73 | + | |
| 74 | + def test_render_xml_when_it_is_given_as_a_block | |
| 75 | + @request.accept = 'application/xml' | |
| 76 | + Student.stubs(:find).returns(mock_student) | |
| 77 | + get :edit | |
| 78 | + assert_response :success | |
| 79 | + assert_equal 'Render XML', @response.body | |
| 80 | + end | |
| 81 | + | |
| 82 | + def test_is_not_redirected_on_create_with_success_if_success_block_is_given | |
| 83 | + Student.stubs(:new).returns(mock_student(:save => true)) | |
| 84 | + @controller.stubs(:resource_url).returns('http://test.host/') | |
| 85 | + post :create | |
| 86 | + assert_response :success | |
| 87 | + assert_equal "I won't redirect!", @response.body | |
| 88 | + end | |
| 89 | + | |
| 90 | + def test_dumb_responder_quietly_receives_everything_on_failure | |
| 91 | + @request.accept = 'text/html' | |
| 92 | + Student.stubs(:new).returns(mock_student(:save => false, :errors => [])) | |
| 93 | + @controller.stubs(:resource_url).returns('http://test.host/') | |
| 94 | + post :create | |
| 95 | + assert_response :success | |
| 96 | + assert_equal "New HTML", @response.body.strip | |
| 97 | + end | |
| 98 | + | |
| 99 | + def test_html_is_the_default_when_only_xml_is_overwriten | |
| 100 | + @request.accept = '*/*' | |
| 101 | + Student.stubs(:new).returns(mock_student(:save => false, :errors => [])) | |
| 102 | + @controller.stubs(:resource_url).returns('http://test.host/') | |
| 103 | + post :create | |
| 104 | + assert_response :success | |
| 105 | + assert_equal "New HTML", @response.body.strip | |
| 106 | + end | |
| 107 | + | |
| 108 | + def test_wont_render_edit_template_on_update_with_failure_if_failure_block_is_given | |
| 109 | + Student.stubs(:find).returns(mock_student(:update_attributes => false, :errors => [])) | |
| 110 | + put :update | |
| 111 | + assert_response :success | |
| 112 | + assert_equal "I won't render!", @response.body | |
| 113 | + end | |
| 114 | + | |
| 115 | + def test_dumb_responder_quietly_receives_everything_on_success | |
| 116 | + Student.stubs(:find).returns(mock_student(:update_attributes => true)) | |
| 117 | + @controller.stubs(:resource_url).returns('http://test.host/') | |
| 118 | + put :update, :id => '42', :student => {:these => 'params'} | |
| 119 | + assert_equal mock_student, assigns(:student) | |
| 120 | + end | |
| 121 | + | |
| 122 | + def test_block_is_called_when_student_is_destroyed | |
| 123 | + Student.stubs(:find).returns(mock_student(:destroy => true)) | |
| 124 | + delete :destroy | |
| 125 | + assert_response :success | |
| 126 | + assert_equal "Destroyed!", @response.body | |
| 127 | + end | |
| 128 | + | |
| 129 | + protected | |
| 130 | + def mock_student(stubs={}) | |
| 131 | + @mock_student ||= mock(stubs) | |
| 132 | + end | |
| 133 | +end | |
| 134 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Pet | |
| 4 | + def self.human_name; 'Pet'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class PetsController < InheritedResources::Base | |
| 8 | + attr_accessor :current_user | |
| 9 | + | |
| 10 | + def edit | |
| 11 | + @pet = 'new pet' | |
| 12 | + edit! | |
| 13 | + end | |
| 14 | + | |
| 15 | + protected | |
| 16 | + def collection | |
| 17 | + @pets ||= end_of_association_chain.all | |
| 18 | + end | |
| 19 | + | |
| 20 | + def begin_of_association_chain | |
| 21 | + @current_user | |
| 22 | + end | |
| 23 | +end | |
| 24 | + | |
| 25 | +class AssociationChainBaseHelpersTest < ActionController::TestCase | |
| 26 | + tests PetsController | |
| 27 | + | |
| 28 | + def setup | |
| 29 | + @controller.current_user = mock() | |
| 30 | + end | |
| 31 | + | |
| 32 | + def test_begin_of_association_chain_is_called_on_index | |
| 33 | + @controller.current_user.expects(:pets).returns(Pet) | |
| 34 | + Pet.expects(:all).returns(mock_pet) | |
| 35 | + get :index | |
| 36 | + assert_response :success | |
| 37 | + assert 'Index HTML', @response.body.strip | |
| 38 | + end | |
| 39 | + | |
| 40 | + def test_begin_of_association_chain_is_called_on_new | |
| 41 | + @controller.current_user.expects(:pets).returns(Pet) | |
| 42 | + Pet.expects(:build).returns(mock_pet) | |
| 43 | + get :new | |
| 44 | + assert_response :success | |
| 45 | + assert 'New HTML', @response.body.strip | |
| 46 | + end | |
| 47 | + | |
| 48 | + def test_begin_of_association_chain_is_called_on_show | |
| 49 | + @controller.current_user.expects(:pets).returns(Pet) | |
| 50 | + Pet.expects(:find).with('47').returns(mock_pet) | |
| 51 | + get :show, :id => '47' | |
| 52 | + assert_response :success | |
| 53 | + assert 'Show HTML', @response.body.strip | |
| 54 | + end | |
| 55 | + | |
| 56 | + def test_instance_variable_should_not_be_set_if_already_defined | |
| 57 | + @controller.current_user.expects(:pets).never | |
| 58 | + Pet.expects(:find).never | |
| 59 | + get :edit | |
| 60 | + assert_response :success | |
| 61 | + assert_equal 'new pet', assigns(:pet) | |
| 62 | + end | |
| 63 | + | |
| 64 | + protected | |
| 65 | + def mock_pet(stubs={}) | |
| 66 | + @mock_pet ||= mock(stubs) | |
| 67 | + end | |
| 68 | + | |
| 69 | +end | |
| 70 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,219 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class User | |
| 4 | + def self.human_name; 'User'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class AccountsController < InheritedResources::Base | |
| 8 | +end | |
| 9 | + | |
| 10 | +class UsersController < AccountsController | |
| 11 | + respond_to :html, :xml | |
| 12 | +end | |
| 13 | + | |
| 14 | +module UserTestHelper | |
| 15 | + def setup | |
| 16 | + @controller = UsersController.new | |
| 17 | + @controller.request = @request = ActionController::TestRequest.new | |
| 18 | + @controller.response = @response = ActionController::TestResponse.new | |
| 19 | + end | |
| 20 | + | |
| 21 | + protected | |
| 22 | + def mock_user(stubs={}) | |
| 23 | + @mock_user ||= mock(stubs) | |
| 24 | + end | |
| 25 | +end | |
| 26 | + | |
| 27 | +class IndexActionBaseTest < ActionController::TestCase | |
| 28 | + include UserTestHelper | |
| 29 | + | |
| 30 | + def test_expose_all_users_as_instance_variable | |
| 31 | + User.expects(:find).with(:all).returns([mock_user]) | |
| 32 | + get :index | |
| 33 | + assert_equal [mock_user], assigns(:users) | |
| 34 | + end | |
| 35 | + | |
| 36 | + def test_controller_should_render_index | |
| 37 | + User.stubs(:find).returns([mock_user]) | |
| 38 | + get :index | |
| 39 | + assert_response :success | |
| 40 | + assert_equal 'Index HTML', @response.body.strip | |
| 41 | + end | |
| 42 | + | |
| 43 | + def test_render_all_users_as_xml_when_mime_type_is_xml | |
| 44 | + @request.accept = 'application/xml' | |
| 45 | + User.expects(:find).with(:all).returns(mock_user) | |
| 46 | + mock_user.expects(:to_xml).returns('Generated XML') | |
| 47 | + get :index | |
| 48 | + assert_response :success | |
| 49 | + assert_equal 'Generated XML', @response.body | |
| 50 | + end | |
| 51 | +end | |
| 52 | + | |
| 53 | +class ShowActionBaseTest < ActionController::TestCase | |
| 54 | + include UserTestHelper | |
| 55 | + | |
| 56 | + def test_expose_the_resquested_user | |
| 57 | + User.expects(:find).with('42').returns(mock_user) | |
| 58 | + get :show, :id => '42' | |
| 59 | + assert_equal mock_user, assigns(:user) | |
| 60 | + end | |
| 61 | + | |
| 62 | + def test_controller_should_render_show | |
| 63 | + User.stubs(:find).returns(mock_user) | |
| 64 | + get :show | |
| 65 | + assert_response :success | |
| 66 | + assert_equal 'Show HTML', @response.body.strip | |
| 67 | + end | |
| 68 | + | |
| 69 | + def test_render_exposed_user_as_xml_when_mime_type_is_xml | |
| 70 | + @request.accept = 'application/xml' | |
| 71 | + User.expects(:find).with('42').returns(mock_user) | |
| 72 | + mock_user.expects(:to_xml).returns("Generated XML") | |
| 73 | + get :show, :id => '42' | |
| 74 | + assert_response :success | |
| 75 | + assert_equal 'Generated XML', @response.body | |
| 76 | + end | |
| 77 | +end | |
| 78 | + | |
| 79 | +class NewActionBaseTest < ActionController::TestCase | |
| 80 | + include UserTestHelper | |
| 81 | + | |
| 82 | + def test_expose_a_new_user | |
| 83 | + User.expects(:new).returns(mock_user) | |
| 84 | + get :new | |
| 85 | + assert_equal mock_user, assigns(:user) | |
| 86 | + end | |
| 87 | + | |
| 88 | + def test_controller_should_render_new | |
| 89 | + User.stubs(:new).returns(mock_user) | |
| 90 | + get :new | |
| 91 | + assert_response :success | |
| 92 | + assert_equal 'New HTML', @response.body.strip | |
| 93 | + end | |
| 94 | + | |
| 95 | + def test_render_exposed_a_new_user_as_xml_when_mime_type_is_xml | |
| 96 | + @request.accept = 'application/xml' | |
| 97 | + User.expects(:new).returns(mock_user) | |
| 98 | + mock_user.expects(:to_xml).returns("Generated XML") | |
| 99 | + get :new | |
| 100 | + assert_response :success | |
| 101 | + assert_equal 'Generated XML', @response.body | |
| 102 | + end | |
| 103 | +end | |
| 104 | + | |
| 105 | +class EditActionBaseTest < ActionController::TestCase | |
| 106 | + include UserTestHelper | |
| 107 | + | |
| 108 | + def test_expose_the_resquested_user | |
| 109 | + User.expects(:find).with('42').returns(mock_user) | |
| 110 | + get :edit, :id => '42' | |
| 111 | + assert_response :success | |
| 112 | + assert_equal mock_user, assigns(:user) | |
| 113 | + end | |
| 114 | + | |
| 115 | + def test_controller_should_render_edit | |
| 116 | + User.stubs(:find).returns(mock_user) | |
| 117 | + get :edit | |
| 118 | + assert_response :success | |
| 119 | + assert_equal 'Edit HTML', @response.body.strip | |
| 120 | + end | |
| 121 | +end | |
| 122 | + | |
| 123 | +class CreateActionBaseTest < ActionController::TestCase | |
| 124 | + include UserTestHelper | |
| 125 | + | |
| 126 | + def test_expose_a_newly_create_user_when_saved_with_success | |
| 127 | + User.expects(:new).with({'these' => 'params'}).returns(mock_user(:save => true)) | |
| 128 | + post :create, :user => {:these => 'params'} | |
| 129 | + assert_equal mock_user, assigns(:user) | |
| 130 | + end | |
| 131 | + | |
| 132 | + def test_redirect_to_the_created_user | |
| 133 | + User.stubs(:new).returns(mock_user(:save => true)) | |
| 134 | + @controller.expects(:resource_url).returns('http://test.host/').times(2) | |
| 135 | + post :create | |
| 136 | + assert_redirected_to 'http://test.host/' | |
| 137 | + end | |
| 138 | + | |
| 139 | + def test_show_flash_message_when_success | |
| 140 | + User.stubs(:new).returns(mock_user(:save => true)) | |
| 141 | + post :create | |
| 142 | + assert_equal flash[:notice], 'User was successfully created.' | |
| 143 | + end | |
| 144 | + | |
| 145 | + def test_render_new_template_when_user_cannot_be_saved | |
| 146 | + User.stubs(:new).returns(mock_user(:save => false, :errors => [])) | |
| 147 | + post :create | |
| 148 | + assert_response :success | |
| 149 | + assert_template :new | |
| 150 | + end | |
| 151 | + | |
| 152 | + def test_dont_show_flash_message_when_user_cannot_be_saved | |
| 153 | + User.stubs(:new).returns(mock_user(:save => false, :errors => [])) | |
| 154 | + post :create | |
| 155 | + assert flash.empty? | |
| 156 | + end | |
| 157 | +end | |
| 158 | + | |
| 159 | +class UpdateActionBaseTest < ActionController::TestCase | |
| 160 | + include UserTestHelper | |
| 161 | + | |
| 162 | + def test_update_the_requested_object | |
| 163 | + User.expects(:find).with('42').returns(mock_user) | |
| 164 | + mock_user.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 165 | + put :update, :id => '42', :user => {:these => 'params'} | |
| 166 | + assert_equal mock_user, assigns(:user) | |
| 167 | + end | |
| 168 | + | |
| 169 | + def test_redirect_to_the_created_user | |
| 170 | + User.stubs(:find).returns(mock_user(:update_attributes => true)) | |
| 171 | + @controller.expects(:resource_url).returns('http://test.host/') | |
| 172 | + put :update | |
| 173 | + assert_redirected_to 'http://test.host/' | |
| 174 | + end | |
| 175 | + | |
| 176 | + def test_show_flash_message_when_success | |
| 177 | + User.stubs(:find).returns(mock_user(:update_attributes => true)) | |
| 178 | + put :update | |
| 179 | + assert_equal flash[:notice], 'User was successfully updated.' | |
| 180 | + end | |
| 181 | + | |
| 182 | + def test_render_edit_template_when_user_cannot_be_saved | |
| 183 | + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => [])) | |
| 184 | + put :update | |
| 185 | + assert_response :success | |
| 186 | + assert_template :edit | |
| 187 | + end | |
| 188 | + | |
| 189 | + def test_dont_show_flash_message_when_user_cannot_be_saved | |
| 190 | + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => [])) | |
| 191 | + put :update | |
| 192 | + assert flash.empty? | |
| 193 | + end | |
| 194 | +end | |
| 195 | + | |
| 196 | +class DestroyActionBaseTest < ActionController::TestCase | |
| 197 | + include UserTestHelper | |
| 198 | + | |
| 199 | + def test_the_resquested_user_is_destroyed | |
| 200 | + User.expects(:find).with('42').returns(mock_user) | |
| 201 | + mock_user.expects(:destroy) | |
| 202 | + delete :destroy, :id => '42' | |
| 203 | + assert_equal mock_user, assigns(:user) | |
| 204 | + end | |
| 205 | + | |
| 206 | + def test_show_flash_message | |
| 207 | + User.stubs(:find).returns(mock_user(:destroy => true)) | |
| 208 | + delete :destroy | |
| 209 | + assert_equal flash[:notice], 'User was successfully destroyed.' | |
| 210 | + end | |
| 211 | + | |
| 212 | + def test_redirects_to_users_list | |
| 213 | + User.stubs(:find).returns(mock_user(:destroy => true)) | |
| 214 | + @controller.expects(:collection_url).returns('http://test.host/') | |
| 215 | + delete :destroy | |
| 216 | + assert_redirected_to 'http://test.host/' | |
| 217 | + end | |
| 218 | +end | |
| 219 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Post | |
| 4 | +end | |
| 5 | + | |
| 6 | +class Comment | |
| 7 | + def self.human_name; 'Comment'; end | |
| 8 | +end | |
| 9 | + | |
| 10 | +class CommentsController < InheritedResources::Base | |
| 11 | + belongs_to :post | |
| 12 | +end | |
| 13 | + | |
| 14 | +class BelongsToTest < ActionController::TestCase | |
| 15 | + tests CommentsController | |
| 16 | + | |
| 17 | + def setup | |
| 18 | + Post.expects(:find).with('37').returns(mock_post) | |
| 19 | + mock_post.expects(:comments).returns(Comment) | |
| 20 | + | |
| 21 | + @controller.stubs(:resource_url).returns('/') | |
| 22 | + @controller.stubs(:collection_url).returns('/') | |
| 23 | + end | |
| 24 | + | |
| 25 | + def test_expose_all_comments_as_instance_variable_on_index | |
| 26 | + Comment.expects(:find).with(:all).returns([mock_comment]) | |
| 27 | + get :index, :post_id => '37' | |
| 28 | + assert_equal mock_post, assigns(:post) | |
| 29 | + assert_equal [mock_comment], assigns(:comments) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def test_expose_the_resquested_comment_on_show | |
| 33 | + Comment.expects(:find).with('42').returns(mock_comment) | |
| 34 | + get :show, :id => '42', :post_id => '37' | |
| 35 | + assert_equal mock_post, assigns(:post) | |
| 36 | + assert_equal mock_comment, assigns(:comment) | |
| 37 | + end | |
| 38 | + | |
| 39 | + def test_expose_a_new_comment_on_new | |
| 40 | + Comment.expects(:build).returns(mock_comment) | |
| 41 | + get :new, :post_id => '37' | |
| 42 | + assert_equal mock_post, assigns(:post) | |
| 43 | + assert_equal mock_comment, assigns(:comment) | |
| 44 | + end | |
| 45 | + | |
| 46 | + def test_expose_the_resquested_comment_on_edit | |
| 47 | + Comment.expects(:find).with('42').returns(mock_comment) | |
| 48 | + get :edit, :id => '42', :post_id => '37' | |
| 49 | + assert_equal mock_post, assigns(:post) | |
| 50 | + assert_equal mock_comment, assigns(:comment) | |
| 51 | + end | |
| 52 | + | |
| 53 | + def test_expose_a_newly_create_comment_on_create | |
| 54 | + Comment.expects(:build).with({'these' => 'params'}).returns(mock_comment(:save => true)) | |
| 55 | + post :create, :post_id => '37', :comment => {:these => 'params'} | |
| 56 | + assert_equal mock_post, assigns(:post) | |
| 57 | + assert_equal mock_comment, assigns(:comment) | |
| 58 | + end | |
| 59 | + | |
| 60 | + def test_update_the_requested_object_on_update | |
| 61 | + Comment.expects(:find).with('42').returns(mock_comment) | |
| 62 | + mock_comment.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 63 | + put :update, :id => '42', :post_id => '37', :comment => {:these => 'params'} | |
| 64 | + assert_equal mock_post, assigns(:post) | |
| 65 | + assert_equal mock_comment, assigns(:comment) | |
| 66 | + end | |
| 67 | + | |
| 68 | + def test_the_resquested_comment_is_destroyed_on_destroy | |
| 69 | + Comment.expects(:find).with('42').returns(mock_comment) | |
| 70 | + mock_comment.expects(:destroy) | |
| 71 | + delete :destroy, :id => '42', :post_id => '37' | |
| 72 | + assert_equal mock_post, assigns(:post) | |
| 73 | + assert_equal mock_comment, assigns(:comment) | |
| 74 | + end | |
| 75 | + | |
| 76 | + protected | |
| 77 | + | |
| 78 | + def mock_post(stubs={}) | |
| 79 | + @mock_post ||= mock(stubs) | |
| 80 | + end | |
| 81 | + | |
| 82 | + def mock_comment(stubs={}) | |
| 83 | + @mock_comment ||= mock(stubs) | |
| 84 | + end | |
| 85 | + | |
| 86 | +end | |
| 87 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,137 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Book; end | |
| 4 | +class Folder; end | |
| 5 | + | |
| 6 | +class BooksController < InheritedResources::Base | |
| 7 | + actions :index, :show | |
| 8 | +end | |
| 9 | + | |
| 10 | +class ReadersController < InheritedResources::Base | |
| 11 | + actions :all, :except => [ :edit, :update ] | |
| 12 | +end | |
| 13 | + | |
| 14 | +class FoldersController < InheritedResources::Base | |
| 15 | +end | |
| 16 | + | |
| 17 | +class Dean | |
| 18 | + def self.human_name; 'Dean'; end | |
| 19 | +end | |
| 20 | + | |
| 21 | +class SchoolsController < InheritedResources::Base | |
| 22 | + has_scope :by_city | |
| 23 | + has_scope :featured, :boolean => true, :only => :index, :key => :by_featured | |
| 24 | +end | |
| 25 | + | |
| 26 | +class DeansController < InheritedResources::Base | |
| 27 | + belongs_to :school | |
| 28 | +end | |
| 29 | + | |
| 30 | + | |
| 31 | +class ActionsClassMethodTest < ActiveSupport::TestCase | |
| 32 | + def test_actions_are_undefined | |
| 33 | + action_methods = BooksController.send(:action_methods) | |
| 34 | + assert_equal 2, action_methods.size | |
| 35 | + | |
| 36 | + ['index', 'show'].each do |action| | |
| 37 | + assert action_methods.include? action | |
| 38 | + end | |
| 39 | + end | |
| 40 | + | |
| 41 | + def test_actions_are_undefined_when_except_option_is_given | |
| 42 | + action_methods = ReadersController.send(:action_methods) | |
| 43 | + assert_equal 5, action_methods.size | |
| 44 | + | |
| 45 | + ['index', 'new', 'show', 'create', 'destroy'].each do |action| | |
| 46 | + assert action_methods.include? action | |
| 47 | + end | |
| 48 | + end | |
| 49 | +end | |
| 50 | + | |
| 51 | + | |
| 52 | +class DefaultsClassMethodTest < ActiveSupport::TestCase | |
| 53 | + def test_resource_class_is_set_to_nil_when_resource_model_cannot_be_found | |
| 54 | + assert_nil ReadersController.send(:resource_class) | |
| 55 | + end | |
| 56 | + | |
| 57 | + def test_defaults_are_set | |
| 58 | + assert Folder, FoldersController.send(:resource_class) | |
| 59 | + assert :folder, FoldersController.send(:resources_configuration)[:self][:instance_name] | |
| 60 | + assert :folders, FoldersController.send(:resources_configuration)[:self][:collection_name] | |
| 61 | + end | |
| 62 | + | |
| 63 | + def test_defaults_can_be_overwriten | |
| 64 | + BooksController.send(:defaults, :resource_class => String, :instance_name => 'string', :collection_name => 'strings') | |
| 65 | + | |
| 66 | + assert String, BooksController.send(:resource_class) | |
| 67 | + assert :string, BooksController.send(:resources_configuration)[:self][:instance_name] | |
| 68 | + assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name] | |
| 69 | + | |
| 70 | + BooksController.send(:defaults, :class_name => 'Fixnum', :instance_name => :fixnum, :collection_name => :fixnums) | |
| 71 | + | |
| 72 | + assert String, BooksController.send(:resource_class) | |
| 73 | + assert :string, BooksController.send(:resources_configuration)[:self][:instance_name] | |
| 74 | + assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name] | |
| 75 | + end | |
| 76 | + | |
| 77 | + def test_defaults_raises_invalid_key | |
| 78 | + assert_raise ArgumentError do | |
| 79 | + BooksController.send(:defaults, :boom => String) | |
| 80 | + end | |
| 81 | + end | |
| 82 | + | |
| 83 | + def test_url_helpers_are_recreated_when_defaults_change | |
| 84 | + BooksController.expects(:create_resources_url_helpers!).returns(true).once | |
| 85 | + BooksController.send(:defaults, :instance_name => 'string', :collection_name => 'strings') | |
| 86 | + end | |
| 87 | +end | |
| 88 | + | |
| 89 | +class BelongsToErrorsTest < ActiveSupport::TestCase | |
| 90 | + def test_belongs_to_raise_errors_with_invalid_arguments | |
| 91 | + assert_raise ArgumentError do | |
| 92 | + DeansController.send(:belongs_to) | |
| 93 | + end | |
| 94 | + | |
| 95 | + assert_raise ArgumentError do | |
| 96 | + DeansController.send(:belongs_to, :nice, :invalid_key => '') | |
| 97 | + end | |
| 98 | + end | |
| 99 | + | |
| 100 | + def test_belongs_to_raises_an_error_when_multiple_associations_are_given_with_options | |
| 101 | + assert_raise ArgumentError do | |
| 102 | + DeansController.send(:belongs_to, :arguments, :with_options, :parent_class => Professor) | |
| 103 | + end | |
| 104 | + end | |
| 105 | + | |
| 106 | + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_block | |
| 107 | + DeansController.expects(:create_resources_url_helpers!).returns(true).once | |
| 108 | + DeansController.send(:belongs_to, :school) do | |
| 109 | + belongs_to :association | |
| 110 | + end | |
| 111 | + ensure | |
| 112 | + DeansController.send(:parents_symbols=, [:school]) | |
| 113 | + end | |
| 114 | + | |
| 115 | + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_multiple_blocks | |
| 116 | + DeansController.expects(:create_resources_url_helpers!).returns(true).once | |
| 117 | + DeansController.send(:belongs_to, :school) do | |
| 118 | + belongs_to :association do | |
| 119 | + belongs_to :nested | |
| 120 | + end | |
| 121 | + end | |
| 122 | + ensure | |
| 123 | + DeansController.send(:parents_symbols=, [:school]) | |
| 124 | + end | |
| 125 | +end | |
| 126 | + | |
| 127 | +class HasScopeClassMethods < ActiveSupport::TestCase | |
| 128 | + def test_scope_configuration_is_stored_as_hashes | |
| 129 | + config = SchoolsController.send(:scopes_configuration) | |
| 130 | + | |
| 131 | + assert config.key?(:by_city) | |
| 132 | + assert config.key?(:featured) | |
| 133 | + | |
| 134 | + assert_equal config[:by_city], { :key => :by_city, :only => [], :except => [] } | |
| 135 | + assert_equal config[:featured], { :key => :by_featured, :only => [ :index ], :except => [], :boolean => true } | |
| 136 | + end | |
| 137 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,76 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class GreatSchool | |
| 4 | +end | |
| 5 | + | |
| 6 | +class Professor | |
| 7 | + def self.human_name; 'Professor'; end | |
| 8 | +end | |
| 9 | + | |
| 10 | +class ProfessorsController < InheritedResources::Base | |
| 11 | + belongs_to :school, :parent_class => GreatSchool, :instance_name => :great_school, | |
| 12 | + :finder => :find_by_title!, :param => :school_title | |
| 13 | +end | |
| 14 | + | |
| 15 | +class CustomizedBelongsToTest < ActionController::TestCase | |
| 16 | + tests ProfessorsController | |
| 17 | + | |
| 18 | + def setup | |
| 19 | + GreatSchool.expects(:find_by_title!).with('nice').returns(mock_school(:professors => Professor)) | |
| 20 | + @controller.stubs(:resource_url).returns('/') | |
| 21 | + @controller.stubs(:collection_url).returns('/') | |
| 22 | + end | |
| 23 | + | |
| 24 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_index | |
| 25 | + Professor.stubs(:find).returns([mock_professor]) | |
| 26 | + get :index, :school_title => 'nice' | |
| 27 | + assert_equal mock_school, assigns(:great_school) | |
| 28 | + end | |
| 29 | + | |
| 30 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_show | |
| 31 | + Professor.stubs(:find).returns(mock_professor) | |
| 32 | + get :show, :school_title => 'nice' | |
| 33 | + assert_equal mock_school, assigns(:great_school) | |
| 34 | + end | |
| 35 | + | |
| 36 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_new | |
| 37 | + Professor.stubs(:build).returns(mock_professor) | |
| 38 | + get :new, :school_title => 'nice' | |
| 39 | + assert_equal mock_school, assigns(:great_school) | |
| 40 | + end | |
| 41 | + | |
| 42 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_edit | |
| 43 | + Professor.stubs(:find).returns(mock_professor) | |
| 44 | + get :edit, :school_title => 'nice' | |
| 45 | + assert_equal mock_school, assigns(:great_school) | |
| 46 | + end | |
| 47 | + | |
| 48 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_create | |
| 49 | + Professor.stubs(:build).returns(mock_professor(:save => true)) | |
| 50 | + post :create, :school_title => 'nice' | |
| 51 | + assert_equal mock_school, assigns(:great_school) | |
| 52 | + end | |
| 53 | + | |
| 54 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_update | |
| 55 | + Professor.stubs(:find).returns(mock_professor(:update_attributes => true)) | |
| 56 | + put :update, :school_title => 'nice' | |
| 57 | + assert_equal mock_school, assigns(:great_school) | |
| 58 | + end | |
| 59 | + | |
| 60 | + def test_expose_the_resquested_school_with_chosen_instance_variable_on_destroy | |
| 61 | + Professor.stubs(:find).returns(mock_professor(:destroy => true)) | |
| 62 | + delete :destroy, :school_title => 'nice' | |
| 63 | + assert_equal mock_school, assigns(:great_school) | |
| 64 | + end | |
| 65 | + | |
| 66 | + protected | |
| 67 | + | |
| 68 | + def mock_school(stubs={}) | |
| 69 | + @mock_school ||= mock(stubs) | |
| 70 | + end | |
| 71 | + | |
| 72 | + def mock_professor(stubs={}) | |
| 73 | + @mock_professor ||= mock(stubs) | |
| 74 | + end | |
| 75 | +end | |
| 76 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Malarz | |
| 4 | + def self.human_name; 'Painter'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class PaintersController < InheritedResources::Base | |
| 8 | + defaults :instance_name => 'malarz', :collection_name => 'malarze', | |
| 9 | + :resource_class => Malarz, :route_prefix => nil | |
| 10 | +end | |
| 11 | + | |
| 12 | +class DefaultsTest < ActionController::TestCase | |
| 13 | + tests PaintersController | |
| 14 | + | |
| 15 | + def setup | |
| 16 | + @controller.stubs(:resource_url).returns('/') | |
| 17 | + @controller.stubs(:collection_url).returns('/') | |
| 18 | + end | |
| 19 | + | |
| 20 | + def test_expose_all_painters_as_instance_variable | |
| 21 | + Malarz.expects(:find).with(:all).returns([mock_painter]) | |
| 22 | + get :index | |
| 23 | + assert_equal [mock_painter], assigns(:malarze) | |
| 24 | + end | |
| 25 | + | |
| 26 | + def test_expose_the_resquested_painter_on_show | |
| 27 | + Malarz.expects(:find).with('42').returns(mock_painter) | |
| 28 | + get :show, :id => '42' | |
| 29 | + assert_equal mock_painter, assigns(:malarz) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def test_expose_a_new_painter | |
| 33 | + Malarz.expects(:new).returns(mock_painter) | |
| 34 | + get :new | |
| 35 | + assert_equal mock_painter, assigns(:malarz) | |
| 36 | + end | |
| 37 | + | |
| 38 | + def test_expose_the_resquested_painter_on_edit | |
| 39 | + Malarz.expects(:find).with('42').returns(mock_painter) | |
| 40 | + get :edit, :id => '42' | |
| 41 | + assert_response :success | |
| 42 | + assert_equal mock_painter, assigns(:malarz) | |
| 43 | + end | |
| 44 | + | |
| 45 | + def test_expose_a_newly_create_painter_when_saved_with_success | |
| 46 | + Malarz.expects(:new).with({'these' => 'params'}).returns(mock_painter(:save => true)) | |
| 47 | + post :create, :malarz => {:these => 'params'} | |
| 48 | + assert_equal mock_painter, assigns(:malarz) | |
| 49 | + end | |
| 50 | + | |
| 51 | + def test_update_the_requested_object | |
| 52 | + Malarz.expects(:find).with('42').returns(mock_painter) | |
| 53 | + mock_painter.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 54 | + put :update, :id => '42', :malarz => {:these => 'params'} | |
| 55 | + assert_equal mock_painter, assigns(:malarz) | |
| 56 | + end | |
| 57 | + | |
| 58 | + def test_the_resquested_painter_is_destroyed | |
| 59 | + Malarz.expects(:find).with('42').returns(mock_painter) | |
| 60 | + mock_painter.expects(:destroy) | |
| 61 | + delete :destroy, :id => '42' | |
| 62 | + assert_equal mock_painter, assigns(:malarz) | |
| 63 | + end | |
| 64 | + | |
| 65 | + protected | |
| 66 | + def mock_painter(stubs={}) | |
| 67 | + @mock_painter ||= mock(stubs) | |
| 68 | + end | |
| 69 | +end | |
| 70 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,83 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Address | |
| 4 | + def self.human_name; 'Address'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class AddressesController < InheritedResources::Base | |
| 8 | + protected | |
| 9 | + def interpolation_options | |
| 10 | + { :reference => 'Ocean Avenue' } | |
| 11 | + end | |
| 12 | +end | |
| 13 | + | |
| 14 | +module Admin; end | |
| 15 | +class Admin::AddressesController < InheritedResources::Base | |
| 16 | + protected | |
| 17 | + def interpolation_options | |
| 18 | + { :reference => 'Ocean Avenue' } | |
| 19 | + end | |
| 20 | +end | |
| 21 | + | |
| 22 | +class FlashBaseHelpersTest < ActionController::TestCase | |
| 23 | + tests AddressesController | |
| 24 | + | |
| 25 | + def setup | |
| 26 | + @request.accept = 'application/xml' | |
| 27 | + end | |
| 28 | + | |
| 29 | + def test_success_flash_message_on_create_with_yml | |
| 30 | + Address.stubs(:new).returns(mock_address(:save => true)) | |
| 31 | + @controller.stubs(:address_url) | |
| 32 | + post :create | |
| 33 | + assert_equal 'You created a new address close to <b>Ocean Avenue</b>.', flash[:notice] | |
| 34 | + end | |
| 35 | + | |
| 36 | + def test_success_flash_message_on_create_with_namespaced_controller | |
| 37 | + @controller = Admin::AddressesController.new | |
| 38 | + Address.stubs(:new).returns(mock_address(:save => true)) | |
| 39 | + @controller.stubs(:address_url) | |
| 40 | + post :create | |
| 41 | + assert_equal 'Admin, you created a new address close to <b>Ocean Avenue</b>.', flash[:notice] | |
| 42 | + end | |
| 43 | + | |
| 44 | + def test_failure_flash_message_on_create_with_namespaced_controller_actions | |
| 45 | + @controller = Admin::AddressesController.new | |
| 46 | + Address.stubs(:new).returns(mock_address(:save => false)) | |
| 47 | + @controller.stubs(:address_url) | |
| 48 | + post :create | |
| 49 | + assert_equal 'Admin error message.', flash[:error] | |
| 50 | + end | |
| 51 | + | |
| 52 | + def test_inherited_success_flash_message_on_update_on_namespaced_controllers | |
| 53 | + @controller = Admin::AddressesController.new | |
| 54 | + Address.stubs(:find).returns(mock_address(:update_attributes => true)) | |
| 55 | + put :update | |
| 56 | + assert_response :success | |
| 57 | + assert_equal 'Nice! Address was updated with success!', flash[:notice] | |
| 58 | + end | |
| 59 | + | |
| 60 | + def test_success_flash_message_on_update | |
| 61 | + Address.stubs(:find).returns(mock_address(:update_attributes => true)) | |
| 62 | + put :update | |
| 63 | + assert_response :success | |
| 64 | + assert_equal 'Nice! Address was updated with success!', flash[:notice] | |
| 65 | + end | |
| 66 | + | |
| 67 | + def test_failure_flash_message_on_update | |
| 68 | + Address.stubs(:find).returns(mock_address(:update_attributes => false, :errors => [])) | |
| 69 | + put :update | |
| 70 | + assert_equal 'Oh no! We could not update your address!', flash[:error] | |
| 71 | + end | |
| 72 | + | |
| 73 | + def test_success_flash_message_on_destroy | |
| 74 | + Address.stubs(:find).returns(mock_address(:destroy => true)) | |
| 75 | + delete :destroy | |
| 76 | + assert_equal 'Address was successfully destroyed.', flash[:notice] | |
| 77 | + end | |
| 78 | + | |
| 79 | + protected | |
| 80 | + def mock_address(stubs={}) | |
| 81 | + @mock_address ||= mock(stubs) | |
| 82 | + end | |
| 83 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,112 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Tree | |
| 4 | + def self.human_name; 'Tree'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class TreesController < InheritedResources::Base | |
| 8 | + has_scope :color | |
| 9 | + has_scope :only_tall, :boolean => true, :only => :index | |
| 10 | + has_scope :shadown_range, :default => 10, :except => [ :index, :show, :destroy, :new ] | |
| 11 | + has_scope :root_type, :key => :root | |
| 12 | + has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new | |
| 13 | +end | |
| 14 | + | |
| 15 | +class HasScopeTest < ActionController::TestCase | |
| 16 | + tests TreesController | |
| 17 | + | |
| 18 | + def setup | |
| 19 | + @controller.stubs(:resource_url).returns('/') | |
| 20 | + @controller.stubs(:collection_url).returns('/') | |
| 21 | + end | |
| 22 | + | |
| 23 | + def test_boolean_scope_is_called_when_boolean_param_is_true | |
| 24 | + Tree.expects(:only_tall).with().returns(Tree).in_sequence | |
| 25 | + Tree.expects(:find).with(:all).returns([mock_tree]).in_sequence | |
| 26 | + get :index, :only_tall => 'true' | |
| 27 | + assert_equal([mock_tree], assigns(:trees)) | |
| 28 | + assert_equal({ :only_tall => 'true' }, assigns(:current_scopes)) | |
| 29 | + end | |
| 30 | + | |
| 31 | + def test_boolean_scope_is_called_when_boolean_param_is_false | |
| 32 | + Tree.expects(:only_tall).never | |
| 33 | + Tree.expects(:find).with(:all).returns([mock_tree]) | |
| 34 | + get :index, :only_tall => 'false' | |
| 35 | + assert_equal([mock_tree], assigns(:trees)) | |
| 36 | + assert_equal({ :only_tall => 'false' }, assigns(:current_scopes)) | |
| 37 | + end | |
| 38 | + | |
| 39 | + def test_scope_is_called_only_on_index | |
| 40 | + Tree.expects(:only_tall).never | |
| 41 | + Tree.expects(:find).with('42').returns(mock_tree) | |
| 42 | + get :show, :only_tall => 'true', :id => '42' | |
| 43 | + assert_equal(mock_tree, assigns(:tree)) | |
| 44 | + assert_equal({ }, assigns(:current_scopes)) | |
| 45 | + end | |
| 46 | + | |
| 47 | + def test_scope_is_called_except_on_index | |
| 48 | + Tree.expects(:shadown_range).with().never | |
| 49 | + Tree.expects(:find).with(:all).returns([mock_tree]) | |
| 50 | + get :index, :shadown_range => 20 | |
| 51 | + assert_equal([mock_tree], assigns(:trees)) | |
| 52 | + assert_equal({ }, assigns(:current_scopes)) | |
| 53 | + end | |
| 54 | + | |
| 55 | + def test_scope_is_called_with_arguments | |
| 56 | + Tree.expects(:color).with('blue').returns(Tree).in_sequence | |
| 57 | + Tree.expects(:find).with(:all).returns([mock_tree]).in_sequence | |
| 58 | + get :index, :color => 'blue' | |
| 59 | + assert_equal([mock_tree], assigns(:trees)) | |
| 60 | + assert_equal({ :color => 'blue' }, assigns(:current_scopes)) | |
| 61 | + end | |
| 62 | + | |
| 63 | + def test_multiple_scopes_are_called | |
| 64 | + Tree.expects(:only_tall).with().returns(Tree) | |
| 65 | + Tree.expects(:color).with('blue').returns(Tree) | |
| 66 | + Tree.expects(:find).with(:all).returns([mock_tree]) | |
| 67 | + get :index, :color => 'blue', :only_tall => 'true' | |
| 68 | + assert_equal([mock_tree], assigns(:trees)) | |
| 69 | + assert_equal({ :color => 'blue', :only_tall => 'true' }, assigns(:current_scopes)) | |
| 70 | + end | |
| 71 | + | |
| 72 | + def test_scope_is_called_with_default_value | |
| 73 | + Tree.expects(:shadown_range).with(10).returns(Tree).in_sequence | |
| 74 | + Tree.expects(:find).with('42').returns(mock_tree).in_sequence | |
| 75 | + get :edit, :id => '42' | |
| 76 | + assert_equal(mock_tree, assigns(:tree)) | |
| 77 | + assert_equal({ :shadown_range => 10 }, assigns(:current_scopes)) | |
| 78 | + end | |
| 79 | + | |
| 80 | + def test_default_scope_value_can_be_overwritten | |
| 81 | + Tree.expects(:shadown_range).with('20').returns(Tree).in_sequence | |
| 82 | + Tree.expects(:find).with('42').returns(mock_tree).in_sequence | |
| 83 | + get :edit, :id => '42', :shadown_range => '20' | |
| 84 | + assert_equal(mock_tree, assigns(:tree)) | |
| 85 | + assert_equal({ :shadown_range => '20' }, assigns(:current_scopes)) | |
| 86 | + end | |
| 87 | + | |
| 88 | + def test_scope_with_different_key | |
| 89 | + Tree.expects(:root_type).with('outside').returns(Tree).in_sequence | |
| 90 | + Tree.expects(:find).with('42').returns(mock_tree).in_sequence | |
| 91 | + get :show, :id => '42', :root => 'outside' | |
| 92 | + assert_equal(mock_tree, assigns(:tree)) | |
| 93 | + assert_equal({ :root => 'outside' }, assigns(:current_scopes)) | |
| 94 | + end | |
| 95 | + | |
| 96 | + def test_scope_with_default_value_as_proc | |
| 97 | + session[:height] = 100 | |
| 98 | + Tree.expects(:calculate_height).with(100).returns(Tree).in_sequence | |
| 99 | + Tree.expects(:new).returns(mock_tree).in_sequence | |
| 100 | + get :new | |
| 101 | + assert_equal(mock_tree, assigns(:tree)) | |
| 102 | + assert_equal({ :calculate_height => 100 }, assigns(:current_scopes)) | |
| 103 | + end | |
| 104 | + | |
| 105 | + protected | |
| 106 | + | |
| 107 | + def mock_tree(stubs={}) | |
| 108 | + @mock_tree ||= mock(stubs) | |
| 109 | + end | |
| 110 | + | |
| 111 | +end | |
| 112 | + | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,108 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Country | |
| 4 | +end | |
| 5 | + | |
| 6 | +class State | |
| 7 | +end | |
| 8 | + | |
| 9 | +class City | |
| 10 | + def self.human_name; 'City'; end | |
| 11 | +end | |
| 12 | + | |
| 13 | +class CitiesController < InheritedResources::Base | |
| 14 | + belongs_to :country, :state | |
| 15 | +end | |
| 16 | + | |
| 17 | +class NestedBelongsToTest < ActionController::TestCase | |
| 18 | + tests CitiesController | |
| 19 | + | |
| 20 | + def setup | |
| 21 | + Country.expects(:find).with('13').returns(mock_country) | |
| 22 | + mock_country.expects(:states).returns(State) | |
| 23 | + State.expects(:find).with('37').returns(mock_state) | |
| 24 | + mock_state.expects(:cities).returns(City) | |
| 25 | + | |
| 26 | + @controller.stubs(:resource_url).returns('/') | |
| 27 | + @controller.stubs(:collection_url).returns('/') | |
| 28 | + end | |
| 29 | + | |
| 30 | + def test_assigns_country_and_state_and_city_on_create | |
| 31 | + City.expects(:find).with(:all).returns([mock_city]) | |
| 32 | + get :index, :state_id => '37', :country_id => '13' | |
| 33 | + | |
| 34 | + assert_equal mock_country, assigns(:country) | |
| 35 | + assert_equal mock_state, assigns(:state) | |
| 36 | + assert_equal [mock_city], assigns(:cities) | |
| 37 | + end | |
| 38 | + | |
| 39 | + def test_assigns_country_and_state_and_city_on_show | |
| 40 | + City.expects(:find).with('42').returns(mock_city) | |
| 41 | + get :show, :id => '42', :state_id => '37', :country_id => '13' | |
| 42 | + | |
| 43 | + assert_equal mock_country, assigns(:country) | |
| 44 | + assert_equal mock_state, assigns(:state) | |
| 45 | + assert_equal mock_city, assigns(:city) | |
| 46 | + end | |
| 47 | + | |
| 48 | + def test_assigns_country_and_state_and_city_on_new | |
| 49 | + City.expects(:build).returns(mock_city) | |
| 50 | + get :new, :state_id => '37', :country_id => '13' | |
| 51 | + | |
| 52 | + assert_equal mock_country, assigns(:country) | |
| 53 | + assert_equal mock_state, assigns(:state) | |
| 54 | + assert_equal mock_city, assigns(:city) | |
| 55 | + end | |
| 56 | + | |
| 57 | + def test_assigns_country_and_state_and_city_on_edit | |
| 58 | + City.expects(:find).with('42').returns(mock_city) | |
| 59 | + get :edit, :id => '42', :state_id => '37', :country_id => '13' | |
| 60 | + | |
| 61 | + assert_equal mock_country, assigns(:country) | |
| 62 | + assert_equal mock_state, assigns(:state) | |
| 63 | + assert_equal mock_city, assigns(:city) | |
| 64 | + end | |
| 65 | + | |
| 66 | + def test_assigns_country_and_state_and_city_on_create | |
| 67 | + City.expects(:build).with({'these' => 'params'}).returns(mock_city) | |
| 68 | + mock_city.expects(:save).returns(true) | |
| 69 | + post :create, :state_id => '37', :country_id => '13', :city => {:these => 'params'} | |
| 70 | + | |
| 71 | + assert_equal mock_country, assigns(:country) | |
| 72 | + assert_equal mock_state, assigns(:state) | |
| 73 | + assert_equal mock_city, assigns(:city) | |
| 74 | + end | |
| 75 | + | |
| 76 | + def test_assigns_country_and_state_and_city_on_update | |
| 77 | + City.expects(:find).with('42').returns(mock_city) | |
| 78 | + mock_city.expects(:update_attributes).returns(true) | |
| 79 | + put :update, :id => '42', :state_id => '37', :country_id => '13', :city => {:these => 'params'} | |
| 80 | + | |
| 81 | + assert_equal mock_country, assigns(:country) | |
| 82 | + assert_equal mock_state, assigns(:state) | |
| 83 | + assert_equal mock_city, assigns(:city) | |
| 84 | + end | |
| 85 | + | |
| 86 | + def test_assigns_country_and_state_and_city_on_destroy | |
| 87 | + City.expects(:find).with('42').returns(mock_city) | |
| 88 | + mock_city.expects(:destroy) | |
| 89 | + delete :destroy, :id => '42', :state_id => '37', :country_id => '13' | |
| 90 | + | |
| 91 | + assert_equal mock_country, assigns(:country) | |
| 92 | + assert_equal mock_state, assigns(:state) | |
| 93 | + assert_equal mock_city, assigns(:city) | |
| 94 | + end | |
| 95 | + | |
| 96 | + protected | |
| 97 | + def mock_country(stubs={}) | |
| 98 | + @mock_country ||= mock(stubs) | |
| 99 | + end | |
| 100 | + | |
| 101 | + def mock_state(stubs={}) | |
| 102 | + @mock_state ||= mock(stubs) | |
| 103 | + end | |
| 104 | + | |
| 105 | + def mock_city(stubs={}) | |
| 106 | + @mock_city ||= mock(stubs) | |
| 107 | + end | |
| 108 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,164 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Brands; end | |
| 4 | +class Category; end | |
| 5 | + | |
| 6 | +class Product | |
| 7 | + def self.human_name; 'Product'; end | |
| 8 | +end | |
| 9 | + | |
| 10 | +class ProductsController < InheritedResources::Base | |
| 11 | + belongs_to :brand, :category, :polymorphic => true, :optional => true | |
| 12 | +end | |
| 13 | + | |
| 14 | +class OptionalTest < ActionController::TestCase | |
| 15 | + tests ProductsController | |
| 16 | + | |
| 17 | + def setup | |
| 18 | + @controller.stubs(:resource_url).returns('/') | |
| 19 | + @controller.stubs(:collection_url).returns('/') | |
| 20 | + end | |
| 21 | + | |
| 22 | + def test_expose_all_products_as_instance_variable_with_category | |
| 23 | + Category.expects(:find).with('37').returns(mock_category) | |
| 24 | + mock_category.expects(:products).returns(Product) | |
| 25 | + Product.expects(:find).with(:all).returns([mock_product]) | |
| 26 | + get :index, :category_id => '37' | |
| 27 | + assert_equal mock_category, assigns(:category) | |
| 28 | + assert_equal [mock_product], assigns(:products) | |
| 29 | + end | |
| 30 | + | |
| 31 | + def test_expose_all_products_as_instance_variable_without_category | |
| 32 | + Product.expects(:find).with(:all).returns([mock_product]) | |
| 33 | + get :index | |
| 34 | + assert_equal nil, assigns(:category) | |
| 35 | + assert_equal [mock_product], assigns(:products) | |
| 36 | + end | |
| 37 | + | |
| 38 | + def test_expose_the_resquested_product_with_category | |
| 39 | + Category.expects(:find).with('37').returns(mock_category) | |
| 40 | + mock_category.expects(:products).returns(Product) | |
| 41 | + Product.expects(:find).with('42').returns(mock_product) | |
| 42 | + get :show, :id => '42', :category_id => '37' | |
| 43 | + assert_equal mock_category, assigns(:category) | |
| 44 | + assert_equal mock_product, assigns(:product) | |
| 45 | + end | |
| 46 | + | |
| 47 | + def test_expose_the_resquested_product_without_category | |
| 48 | + Product.expects(:find).with('42').returns(mock_product) | |
| 49 | + get :show, :id => '42' | |
| 50 | + assert_equal nil, assigns(:category) | |
| 51 | + assert_equal mock_product, assigns(:product) | |
| 52 | + end | |
| 53 | + | |
| 54 | + def test_expose_a_new_product_with_category | |
| 55 | + Category.expects(:find).with('37').returns(mock_category) | |
| 56 | + mock_category.expects(:products).returns(Product) | |
| 57 | + Product.expects(:build).returns(mock_product) | |
| 58 | + get :new, :category_id => '37' | |
| 59 | + assert_equal mock_category, assigns(:category) | |
| 60 | + assert_equal mock_product, assigns(:product) | |
| 61 | + end | |
| 62 | + | |
| 63 | + def test_expose_a_new_product_without_category | |
| 64 | + Product.expects(:new).returns(mock_product) | |
| 65 | + get :new | |
| 66 | + assert_equal nil, assigns(:category) | |
| 67 | + assert_equal mock_product, assigns(:product) | |
| 68 | + end | |
| 69 | + | |
| 70 | + def test_expose_the_resquested_product_for_edition_with_category | |
| 71 | + Category.expects(:find).with('37').returns(mock_category) | |
| 72 | + mock_category.expects(:products).returns(Product) | |
| 73 | + Product.expects(:find).with('42').returns(mock_product) | |
| 74 | + get :edit, :id => '42', :category_id => '37' | |
| 75 | + assert_equal mock_category, assigns(:category) | |
| 76 | + assert_equal mock_product, assigns(:product) | |
| 77 | + end | |
| 78 | + | |
| 79 | + def test_expose_the_resquested_product_for_edition_without_category | |
| 80 | + Product.expects(:find).with('42').returns(mock_product) | |
| 81 | + get :edit, :id => '42' | |
| 82 | + assert_equal nil, assigns(:category) | |
| 83 | + assert_equal mock_product, assigns(:product) | |
| 84 | + end | |
| 85 | + | |
| 86 | + def test_expose_a_newly_create_product_with_category | |
| 87 | + Category.expects(:find).with('37').returns(mock_category) | |
| 88 | + mock_category.expects(:products).returns(Product) | |
| 89 | + Product.expects(:build).with({'these' => 'params'}).returns(mock_product(:save => true)) | |
| 90 | + post :create, :category_id => '37', :product => {:these => 'params'} | |
| 91 | + assert_equal mock_category, assigns(:category) | |
| 92 | + assert_equal mock_product, assigns(:product) | |
| 93 | + end | |
| 94 | + | |
| 95 | + def test_expose_a_newly_create_product_without_category | |
| 96 | + Product.expects(:new).with({'these' => 'params'}).returns(mock_product(:save => true)) | |
| 97 | + post :create, :product => {:these => 'params'} | |
| 98 | + assert_equal nil, assigns(:category) | |
| 99 | + assert_equal mock_product, assigns(:product) | |
| 100 | + end | |
| 101 | + | |
| 102 | + def test_update_the_requested_object_with_category | |
| 103 | + Category.expects(:find).with('37').returns(mock_category) | |
| 104 | + mock_category.expects(:products).returns(Product) | |
| 105 | + Product.expects(:find).with('42').returns(mock_product) | |
| 106 | + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 107 | + | |
| 108 | + put :update, :id => '42', :category_id => '37', :product => {:these => 'params'} | |
| 109 | + assert_equal mock_category, assigns(:category) | |
| 110 | + assert_equal mock_product, assigns(:product) | |
| 111 | + end | |
| 112 | + | |
| 113 | + def test_update_the_requested_object_without_category | |
| 114 | + Product.expects(:find).with('42').returns(mock_product) | |
| 115 | + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 116 | + | |
| 117 | + put :update, :id => '42', :product => {:these => 'params'} | |
| 118 | + assert_equal nil, assigns(:category) | |
| 119 | + assert_equal mock_product, assigns(:product) | |
| 120 | + end | |
| 121 | + | |
| 122 | + def test_the_resquested_product_is_destroyed_with_category | |
| 123 | + Category.expects(:find).with('37').returns(mock_category) | |
| 124 | + mock_category.expects(:products).returns(Product) | |
| 125 | + Product.expects(:find).with('42').returns(mock_product) | |
| 126 | + mock_product.expects(:destroy) | |
| 127 | + @controller.expects(:collection_url).returns('/') | |
| 128 | + | |
| 129 | + delete :destroy, :id => '42', :category_id => '37' | |
| 130 | + assert_equal mock_category, assigns(:category) | |
| 131 | + assert_equal mock_product, assigns(:product) | |
| 132 | + end | |
| 133 | + | |
| 134 | + def test_the_resquested_product_is_destroyed_without_category | |
| 135 | + Product.expects(:find).with('42').returns(mock_product) | |
| 136 | + mock_product.expects(:destroy) | |
| 137 | + @controller.expects(:collection_url).returns('/') | |
| 138 | + | |
| 139 | + delete :destroy, :id => '42' | |
| 140 | + assert_equal nil, assigns(:category) | |
| 141 | + assert_equal mock_product, assigns(:product) | |
| 142 | + end | |
| 143 | + | |
| 144 | + def test_polymorphic_helpers | |
| 145 | + Product.expects(:find).with(:all).returns([mock_product]) | |
| 146 | + get :index | |
| 147 | + | |
| 148 | + assert !@controller.send(:parent?) | |
| 149 | + assert_equal nil, assigns(:parent_type) | |
| 150 | + assert_equal nil, @controller.send(:parent_type) | |
| 151 | + assert_equal nil, @controller.send(:parent_class) | |
| 152 | + assert_equal nil, assigns(:category) | |
| 153 | + assert_equal nil, @controller.send(:parent) | |
| 154 | + end | |
| 155 | + | |
| 156 | + protected | |
| 157 | + def mock_category(stubs={}) | |
| 158 | + @mock_category ||= mock(stubs) | |
| 159 | + end | |
| 160 | + | |
| 161 | + def mock_product(stubs={}) | |
| 162 | + @mock_product ||= mock(stubs) | |
| 163 | + end | |
| 164 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,186 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Factory; end | |
| 4 | +class Company; end | |
| 5 | + | |
| 6 | +class Employee | |
| 7 | + def self.human_name; 'Employee'; end | |
| 8 | +end | |
| 9 | + | |
| 10 | +class EmployeesController < InheritedResources::Base | |
| 11 | + belongs_to :factory, :company, :polymorphic => true | |
| 12 | +end | |
| 13 | + | |
| 14 | +class PolymorphicFactoriesTest < ActionController::TestCase | |
| 15 | + tests EmployeesController | |
| 16 | + | |
| 17 | + def setup | |
| 18 | + Factory.expects(:find).with('37').returns(mock_factory) | |
| 19 | + mock_factory.expects(:employees).returns(Employee) | |
| 20 | + | |
| 21 | + @controller.stubs(:resource_url).returns('/') | |
| 22 | + @controller.stubs(:collection_url).returns('/') | |
| 23 | + end | |
| 24 | + | |
| 25 | + def test_expose_all_employees_as_instance_variable_on_index | |
| 26 | + Employee.expects(:find).with(:all).returns([mock_employee]) | |
| 27 | + get :index, :factory_id => '37' | |
| 28 | + assert_equal mock_factory, assigns(:factory) | |
| 29 | + assert_equal [mock_employee], assigns(:employees) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def test_expose_the_resquested_employee_on_show | |
| 33 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 34 | + get :show, :id => '42', :factory_id => '37' | |
| 35 | + assert_equal mock_factory, assigns(:factory) | |
| 36 | + assert_equal mock_employee, assigns(:employee) | |
| 37 | + end | |
| 38 | + | |
| 39 | + def test_expose_a_new_employee_on_new | |
| 40 | + Employee.expects(:build).returns(mock_employee) | |
| 41 | + get :new, :factory_id => '37' | |
| 42 | + assert_equal mock_factory, assigns(:factory) | |
| 43 | + assert_equal mock_employee, assigns(:employee) | |
| 44 | + end | |
| 45 | + | |
| 46 | + def test_expose_the_resquested_employee_on_edit | |
| 47 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 48 | + get :edit, :id => '42', :factory_id => '37' | |
| 49 | + assert_equal mock_factory, assigns(:factory) | |
| 50 | + assert_equal mock_employee, assigns(:employee) | |
| 51 | + assert_response :success | |
| 52 | + end | |
| 53 | + | |
| 54 | + def test_expose_a_newly_create_employee_on_create | |
| 55 | + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) | |
| 56 | + post :create, :factory_id => '37', :employee => {:these => 'params'} | |
| 57 | + assert_equal mock_factory, assigns(:factory) | |
| 58 | + assert_equal mock_employee, assigns(:employee) | |
| 59 | + end | |
| 60 | + | |
| 61 | + def test_update_the_requested_object_on_update | |
| 62 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 63 | + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 64 | + put :update, :id => '42', :factory_id => '37', :employee => {:these => 'params'} | |
| 65 | + assert_equal mock_factory, assigns(:factory) | |
| 66 | + assert_equal mock_employee, assigns(:employee) | |
| 67 | + end | |
| 68 | + | |
| 69 | + def test_the_resquested_employee_is_destroyed_on_destroy | |
| 70 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 71 | + mock_employee.expects(:destroy) | |
| 72 | + delete :destroy, :id => '42', :factory_id => '37' | |
| 73 | + assert_equal mock_factory, assigns(:factory) | |
| 74 | + assert_equal mock_employee, assigns(:employee) | |
| 75 | + end | |
| 76 | + | |
| 77 | + def test_polymorphic_helpers | |
| 78 | + mock_factory.stubs(:class).returns(Factory) | |
| 79 | + | |
| 80 | + Employee.expects(:find).with(:all).returns([mock_employee]) | |
| 81 | + get :index, :factory_id => '37' | |
| 82 | + | |
| 83 | + assert @controller.send(:parent?) | |
| 84 | + assert_equal :factory, assigns(:parent_type) | |
| 85 | + assert_equal :factory, @controller.send(:parent_type) | |
| 86 | + assert_equal Factory, @controller.send(:parent_class) | |
| 87 | + assert_equal mock_factory, assigns(:factory) | |
| 88 | + assert_equal mock_factory, @controller.send(:parent) | |
| 89 | + end | |
| 90 | + | |
| 91 | + protected | |
| 92 | + def mock_factory(stubs={}) | |
| 93 | + @mock_factory ||= mock(stubs) | |
| 94 | + end | |
| 95 | + | |
| 96 | + def mock_employee(stubs={}) | |
| 97 | + @mock_employee ||= mock(stubs) | |
| 98 | + end | |
| 99 | +end | |
| 100 | + | |
| 101 | +class PolymorphicCompanyTest < ActionController::TestCase | |
| 102 | + tests EmployeesController | |
| 103 | + | |
| 104 | + def setup | |
| 105 | + Company.expects(:find).with('37').returns(mock_company) | |
| 106 | + mock_company.expects(:employees).returns(Employee) | |
| 107 | + | |
| 108 | + @controller.stubs(:resource_url).returns('/') | |
| 109 | + @controller.stubs(:collection_url).returns('/') | |
| 110 | + end | |
| 111 | + | |
| 112 | + def test_expose_all_employees_as_instance_variable_on_index | |
| 113 | + Employee.expects(:find).with(:all).returns([mock_employee]) | |
| 114 | + get :index, :company_id => '37' | |
| 115 | + assert_equal mock_company, assigns(:company) | |
| 116 | + assert_equal [mock_employee], assigns(:employees) | |
| 117 | + end | |
| 118 | + | |
| 119 | + def test_expose_the_resquested_employee_on_show | |
| 120 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 121 | + get :show, :id => '42', :company_id => '37' | |
| 122 | + assert_equal mock_company, assigns(:company) | |
| 123 | + assert_equal mock_employee, assigns(:employee) | |
| 124 | + end | |
| 125 | + | |
| 126 | + def test_expose_a_new_employee_on_new | |
| 127 | + Employee.expects(:build).returns(mock_employee) | |
| 128 | + get :new, :company_id => '37' | |
| 129 | + assert_equal mock_company, assigns(:company) | |
| 130 | + assert_equal mock_employee, assigns(:employee) | |
| 131 | + end | |
| 132 | + | |
| 133 | + def test_expose_the_resquested_employee_on_edit | |
| 134 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 135 | + get :edit, :id => '42', :company_id => '37' | |
| 136 | + assert_equal mock_company, assigns(:company) | |
| 137 | + assert_equal mock_employee, assigns(:employee) | |
| 138 | + assert_response :success | |
| 139 | + end | |
| 140 | + | |
| 141 | + def test_expose_a_newly_create_employee_on_create | |
| 142 | + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) | |
| 143 | + post :create, :company_id => '37', :employee => {:these => 'params'} | |
| 144 | + assert_equal mock_company, assigns(:company) | |
| 145 | + assert_equal mock_employee, assigns(:employee) | |
| 146 | + end | |
| 147 | + | |
| 148 | + def test_update_the_requested_object_on_update | |
| 149 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 150 | + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 151 | + put :update, :id => '42', :company_id => '37', :employee => {:these => 'params'} | |
| 152 | + assert_equal mock_company, assigns(:company) | |
| 153 | + assert_equal mock_employee, assigns(:employee) | |
| 154 | + end | |
| 155 | + | |
| 156 | + def test_the_resquested_employee_is_destroyed_on_destroy | |
| 157 | + Employee.expects(:find).with('42').returns(mock_employee) | |
| 158 | + mock_employee.expects(:destroy) | |
| 159 | + delete :destroy, :id => '42', :company_id => '37' | |
| 160 | + assert_equal mock_company, assigns(:company) | |
| 161 | + assert_equal mock_employee, assigns(:employee) | |
| 162 | + end | |
| 163 | + | |
| 164 | + def test_polymorphic_helpers | |
| 165 | + mock_company.stubs(:class).returns(Company) | |
| 166 | + | |
| 167 | + Employee.expects(:find).with(:all).returns([mock_employee]) | |
| 168 | + get :index, :company_id => '37' | |
| 169 | + | |
| 170 | + assert @controller.send(:parent?) | |
| 171 | + assert_equal :company, assigns(:parent_type) | |
| 172 | + assert_equal :company, @controller.send(:parent_type) | |
| 173 | + assert_equal Company, @controller.send(:parent_class) | |
| 174 | + assert_equal mock_company, assigns(:company) | |
| 175 | + assert_equal mock_company, @controller.send(:parent) | |
| 176 | + end | |
| 177 | + | |
| 178 | + protected | |
| 179 | + def mock_company(stubs={}) | |
| 180 | + @mock_company ||= mock(stubs) | |
| 181 | + end | |
| 182 | + | |
| 183 | + def mock_employee(stubs={}) | |
| 184 | + @mock_employee ||= mock(stubs) | |
| 185 | + end | |
| 186 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Machine; | |
| 4 | + def self.human_name; 'Machine'; end | |
| 5 | +end | |
| 6 | + | |
| 7 | +class MachinesController < InheritedResources::Base | |
| 8 | + def create | |
| 9 | + create!{ complex_url(:create, true, true) } | |
| 10 | + end | |
| 11 | + | |
| 12 | + def update | |
| 13 | + update!{ complex_url(:update, false, false) } | |
| 14 | + end | |
| 15 | + | |
| 16 | + def destroy | |
| 17 | + destroy!{ complex_url(:destroy, true, false) } | |
| 18 | + end | |
| 19 | + | |
| 20 | + protected | |
| 21 | + def complex_url(name, arg2, arg3) | |
| 22 | + 'http://test.host/' + name.to_s | |
| 23 | + end | |
| 24 | +end | |
| 25 | + | |
| 26 | +class RedirectToWithBlockTest < ActionController::TestCase | |
| 27 | + tests MachinesController | |
| 28 | + | |
| 29 | + def test_redirect_to_the_given_url_on_create | |
| 30 | + Machine.stubs(:new).returns(mock_machine(:save => true)) | |
| 31 | + @controller.expects(:resource_url).times(0) | |
| 32 | + post :create | |
| 33 | + assert_redirected_to 'http://test.host/create' | |
| 34 | + end | |
| 35 | + | |
| 36 | + def test_redirect_to_the_given_url_on_update | |
| 37 | + Machine.stubs(:find).returns(mock_machine(:update_attributes => true)) | |
| 38 | + @controller.expects(:resource_url).times(0) | |
| 39 | + put :update | |
| 40 | + assert_redirected_to 'http://test.host/update' | |
| 41 | + end | |
| 42 | + | |
| 43 | + def test_redirect_to_the_given_url_on_destroy | |
| 44 | + Machine.stubs(:find).returns(mock_machine(:destroy => true)) | |
| 45 | + @controller.expects(:collection_url).times(0) | |
| 46 | + delete :destroy | |
| 47 | + assert_redirected_to 'http://test.host/destroy' | |
| 48 | + end | |
| 49 | + | |
| 50 | + protected | |
| 51 | + def mock_machine(stubs={}) | |
| 52 | + @mock_machine ||= mock(stubs) | |
| 53 | + end | |
| 54 | +end | |
| 55 | + | |
| 56 | + | |
| 57 | +# Use this to test blocks with multiple arity in the future. | |
| 58 | +class SuperMachinesController < InheritedResources::Base | |
| 59 | + defaults :resource_class => Machine | |
| 60 | + | |
| 61 | + def create | |
| 62 | + create! do |arg1, arg2, arg3| | |
| 63 | + # nothing | |
| 64 | + end | |
| 65 | + end | |
| 66 | +end | |
| 67 | + | |
| 68 | +class RedirectToArityTest < ActionController::TestCase | |
| 69 | + tests SuperMachinesController | |
| 70 | + | |
| 71 | + def test_redirect_to_the_given_url_on_create | |
| 72 | + Machine.stubs(:new).returns(:anything) | |
| 73 | + assert_raise ScriptError, /arity/ do | |
| 74 | + post :create | |
| 75 | + end | |
| 76 | + end | |
| 77 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,314 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Project | |
| 4 | + def to_html | |
| 5 | + 'Generated HTML' | |
| 6 | + end | |
| 7 | + | |
| 8 | + def to_xml | |
| 9 | + 'Generated XML' | |
| 10 | + end | |
| 11 | + | |
| 12 | + [:to_json, :to_rss, :to_rjs].each do |method| | |
| 13 | + undef_method method if respond_to? method | |
| 14 | + end | |
| 15 | +end | |
| 16 | + | |
| 17 | +class ProjectsController < ActionController::Base | |
| 18 | + # Inherited respond_to definition is: | |
| 19 | + # respond_to :html | |
| 20 | + respond_to :html | |
| 21 | + respond_to :xml, :except => :edit | |
| 22 | + respond_to :rjs => :edit | |
| 23 | + respond_to :rss, :only => 'index' | |
| 24 | + respond_to :json, :except => :index | |
| 25 | + respond_to :csv, :except => :index | |
| 26 | + | |
| 27 | + def index | |
| 28 | + respond_with(Project.new) | |
| 29 | + end | |
| 30 | + | |
| 31 | + def respond_with_options | |
| 32 | + respond_with(Project.new, :to => [:xml, :json], :location => 'http://test.host/') | |
| 33 | + end | |
| 34 | + | |
| 35 | + def skip_not_acceptable | |
| 36 | + respond_with(Project.new, :skip_not_acceptable => true) | |
| 37 | + render :text => 'Will not raise double render error.' | |
| 38 | + end | |
| 39 | + | |
| 40 | + def respond_to_with_resource | |
| 41 | + respond_to(:with => Project.new) | |
| 42 | + end | |
| 43 | + | |
| 44 | + def respond_to_with_resource_and_blocks | |
| 45 | + respond_to(:with => Project.new) do |format| | |
| 46 | + format.json { render :text => 'Render JSON' } | |
| 47 | + format.rss { render :text => 'Render RSS' } | |
| 48 | + end | |
| 49 | + end | |
| 50 | + | |
| 51 | + # If the user request Mime::ALL and we have a template called action.html.erb, | |
| 52 | + # the html template should be rendered *unless* html is specified inside the | |
| 53 | + # block. This tests exactly this case. | |
| 54 | + # | |
| 55 | + def respond_to_skip_default_template | |
| 56 | + respond_to(:with => Project.new) do |format| | |
| 57 | + format.html { render :text => 'Render HTML' } | |
| 58 | + end | |
| 59 | + end | |
| 60 | +end | |
| 61 | + | |
| 62 | +class SuperProjectsController < ProjectsController | |
| 63 | +end | |
| 64 | + | |
| 65 | +class RespondToUnitTest < ActionController::TestCase | |
| 66 | + tests ProjectsController | |
| 67 | + | |
| 68 | + def setup | |
| 69 | + @formats = @controller.formats_for_respond_to | |
| 70 | + @responder = ActionController::MimeResponds::Responder.new(@controller) | |
| 71 | + end | |
| 72 | + | |
| 73 | + def test_respond_to_class_method_without_options | |
| 74 | + assert_nil @formats[:html][:only] | |
| 75 | + assert_nil @formats[:html][:except] | |
| 76 | + end | |
| 77 | + | |
| 78 | + def test_respond_to_class_method_inheritance | |
| 79 | + assert_nil @formats[:xml][:only] | |
| 80 | + assert_equal [:edit], @formats[:xml][:except] | |
| 81 | + end | |
| 82 | + | |
| 83 | + def test_respond_to_class_method_with_implicit_only | |
| 84 | + assert_equal [:edit], @formats[:rjs][:only] | |
| 85 | + assert_nil @formats[:rjs][:except] | |
| 86 | + end | |
| 87 | + | |
| 88 | + def test_respond_to_class_method_with_explicit_only | |
| 89 | + assert_equal [:index], @formats[:rss][:only] | |
| 90 | + assert_nil @formats[:rss][:except] | |
| 91 | + end | |
| 92 | + | |
| 93 | + def test_respond_to_class_method_with_explicit_except | |
| 94 | + assert_nil @formats[:json][:only] | |
| 95 | + assert_equal [:index], @formats[:json][:except] | |
| 96 | + end | |
| 97 | + | |
| 98 | + def test_action_respond_to_format | |
| 99 | + @controller.action_name = 'index' | |
| 100 | + assert @responder.action_respond_to_format?('html') # defined | |
| 101 | + assert @responder.action_respond_to_format?('xml') # inherited | |
| 102 | + assert @responder.action_respond_to_format?('rss') # explicit only | |
| 103 | + assert !@responder.action_respond_to_format?('json') # exception | |
| 104 | + | |
| 105 | + @controller.action_name = 'edit' | |
| 106 | + assert !@responder.action_respond_to_format?('xml') # inherited | |
| 107 | + assert @responder.action_respond_to_format?('rjs') # implicit only | |
| 108 | + assert @responder.action_respond_to_format?('json') # exception | |
| 109 | + end | |
| 110 | + | |
| 111 | + def test_action_respond_to_format_with_additional_mimes | |
| 112 | + assert @responder.action_respond_to_format?('html', [:xml, :html, :json]) | |
| 113 | + assert !@responder.action_respond_to_format?('html', [:xml, :rss, :json]) | |
| 114 | + | |
| 115 | + @controller.action_name = 'index' | |
| 116 | + assert @responder.action_respond_to_format?('html', []) | |
| 117 | + assert !@responder.action_respond_to_format?('json', []) | |
| 118 | + end | |
| 119 | + | |
| 120 | + def test_clear_respond_to | |
| 121 | + @controller = SuperProjectsController.new | |
| 122 | + @controller.request = ActionController::TestRequest.new | |
| 123 | + | |
| 124 | + @controller.action_name = 'index' | |
| 125 | + @responder = ActionController::MimeResponds::Responder.new(@controller) | |
| 126 | + | |
| 127 | + # Those responses are inherited from ProjectsController | |
| 128 | + assert @responder.action_respond_to_format?('html') # defined | |
| 129 | + assert @responder.action_respond_to_format?('xml') # inherited | |
| 130 | + assert @responder.action_respond_to_format?('rss') # explicit only | |
| 131 | + | |
| 132 | + # Let's clear respond_to definitions | |
| 133 | + SuperProjectsController.send(:clear_respond_to!) | |
| 134 | + | |
| 135 | + assert !@responder.action_respond_to_format?('html') | |
| 136 | + assert !@responder.action_respond_to_format?('xml') | |
| 137 | + assert !@responder.action_respond_to_format?('rss') | |
| 138 | + end | |
| 139 | + | |
| 140 | + def test_respond_except_any_does_not_respond_to_mime_all | |
| 141 | + prepare_responder_to_respond! | |
| 142 | + | |
| 143 | + @responder.respond_except_any | |
| 144 | + assert !@performed | |
| 145 | + | |
| 146 | + @responder.respond | |
| 147 | + assert @performed | |
| 148 | + end | |
| 149 | + | |
| 150 | + def test_respond_any_responds_to_mime_all | |
| 151 | + prepare_responder_to_respond! | |
| 152 | + | |
| 153 | + @responder.respond_any | |
| 154 | + assert @performed | |
| 155 | + end | |
| 156 | + | |
| 157 | + def test_respond_any_responds_only_to_all | |
| 158 | + prepare_responder_to_respond!('text/html') | |
| 159 | + | |
| 160 | + @responder.respond_any | |
| 161 | + assert !@performed | |
| 162 | + end | |
| 163 | + | |
| 164 | + def test_responder_prioritize | |
| 165 | + prepare_responder_to_respond! | |
| 166 | + assert_equal [Mime::HTML, Mime::XML], @responder.order | |
| 167 | + | |
| 168 | + @responder.prioritize(:xml) | |
| 169 | + assert_equal [Mime::XML, Mime::HTML], @responder.order | |
| 170 | + | |
| 171 | + @responder.prioritize(:js) | |
| 172 | + assert_equal [Mime::XML, Mime::HTML], @responder.order | |
| 173 | + end | |
| 174 | + | |
| 175 | + protected | |
| 176 | + def prepare_responder_to_respond!(content_type='*/*') | |
| 177 | + @controller.request = @request = ActionController::TestRequest.new | |
| 178 | + @controller.response = @response = ActionController::TestResponse.new | |
| 179 | + | |
| 180 | + @request.accept = content_type | |
| 181 | + @responder = ActionController::MimeResponds::Responder.new(@controller) | |
| 182 | + @performed = false | |
| 183 | + | |
| 184 | + # Mock template | |
| 185 | + template = mock() | |
| 186 | + @response.stubs(:template).returns(template) | |
| 187 | + template.stubs(:template_format=).returns(true) | |
| 188 | + | |
| 189 | + respond_to_declaration = proc { |format| | |
| 190 | + format.html { @performed = true } | |
| 191 | + format.xml { } | |
| 192 | + } | |
| 193 | + | |
| 194 | + respond_to_declaration.call(@responder) | |
| 195 | + end | |
| 196 | +end | |
| 197 | + | |
| 198 | +class RespondToFunctionalTest < ActionController::TestCase | |
| 199 | + tests ProjectsController | |
| 200 | + | |
| 201 | + def test_respond_with_layout_rendering | |
| 202 | + @request.accept = 'text/html' | |
| 203 | + get :index | |
| 204 | + assert_equal 'Index HTML', @response.body.strip | |
| 205 | + end | |
| 206 | + | |
| 207 | + def test_respond_with_calls_to_format_on_resource | |
| 208 | + @request.accept = 'application/xml' | |
| 209 | + get :index | |
| 210 | + assert_equal 'Generated XML', @response.body.strip | |
| 211 | + end | |
| 212 | + | |
| 213 | + def test_respond_with_inherits_format | |
| 214 | + @request.accept = 'application/xml' | |
| 215 | + get :index | |
| 216 | + assert_equal 'Generated XML', @response.body.strip | |
| 217 | + end | |
| 218 | + | |
| 219 | + def test_respond_with_renders_status_not_acceptable_if_mime_type_is_not_registered | |
| 220 | + @request.accept = 'text/csv' | |
| 221 | + get :index | |
| 222 | + assert_equal '406 Not Acceptable', @response.status | |
| 223 | + end | |
| 224 | + | |
| 225 | + def test_respond_with_renders_not_found_when_mime_type_is_valid_but_could_not_render | |
| 226 | + @request.accept = 'application/rss+xml' | |
| 227 | + get :index | |
| 228 | + assert_equal '404 Not Found', @response.status | |
| 229 | + end | |
| 230 | + | |
| 231 | + def test_respond_to_all | |
| 232 | + @request.accept = '*/*' | |
| 233 | + get :index | |
| 234 | + assert_equal 'Index HTML', @response.body.strip | |
| 235 | + end | |
| 236 | + | |
| 237 | + def test_default_template_is_not_rendered_if_template_format_is_not_accepted | |
| 238 | + @controller.stubs(:default_template_format).returns(:json) | |
| 239 | + @request.accept = '*/*' | |
| 240 | + get :index | |
| 241 | + assert_equal '406 Not Acceptable', @response.status | |
| 242 | + end | |
| 243 | + | |
| 244 | + def test_respond_with_sets_content_type_properly | |
| 245 | + @request.accept = 'text/html' | |
| 246 | + get :index | |
| 247 | + assert_equal 'text/html', @response.content_type | |
| 248 | + assert_equal :html, @response.template.template_format | |
| 249 | + | |
| 250 | + @request.accept = 'application/xml' | |
| 251 | + get :index | |
| 252 | + assert_equal 'application/xml', @response.content_type | |
| 253 | + assert_equal :xml, @response.template.template_format | |
| 254 | + end | |
| 255 | + | |
| 256 | + def test_respond_with_when_to_is_given_as_option | |
| 257 | + @request.accept = 'text/html' | |
| 258 | + get :respond_with_options | |
| 259 | + assert_equal '406 Not Acceptable', @response.status | |
| 260 | + | |
| 261 | + @request.accept = 'application/xml' | |
| 262 | + get :respond_with_options | |
| 263 | + assert_equal 'Generated XML', @response.body.strip | |
| 264 | + end | |
| 265 | + | |
| 266 | + def test_respond_with_forwads_extra_options_to_render | |
| 267 | + @request.accept = 'application/xml' | |
| 268 | + get :respond_with_options | |
| 269 | + assert_equal 'Generated XML', @response.body.strip | |
| 270 | + assert_equal 'http://test.host/', @response.headers['Location'] | |
| 271 | + end | |
| 272 | + | |
| 273 | + def test_respond_with_skips_head_when_skip_not_acceptable_is_given | |
| 274 | + @request.accept = 'application/rss+xml' | |
| 275 | + get :skip_not_acceptable | |
| 276 | + assert_equal 'Will not raise double render error.', @response.body.strip | |
| 277 | + end | |
| 278 | + | |
| 279 | + def test_respond_to_when_a_resource_is_given_as_option | |
| 280 | + @request.accept = 'text/html' | |
| 281 | + get :respond_to_with_resource | |
| 282 | + assert_equal 'RespondTo HTML', @response.body.strip | |
| 283 | + | |
| 284 | + @request.accept = 'application/xml' | |
| 285 | + get :respond_to_with_resource | |
| 286 | + assert_equal 'Generated XML', @response.body.strip | |
| 287 | + | |
| 288 | + @request.accept = 'application/json' | |
| 289 | + get :respond_to_with_resource | |
| 290 | + assert_equal '404 Not Found', @response.status | |
| 291 | + | |
| 292 | + @request.accept = 'application/rss+xml' | |
| 293 | + get :respond_to_with_resource | |
| 294 | + assert_equal '406 Not Acceptable', @response.status | |
| 295 | + end | |
| 296 | + | |
| 297 | + def test_respond_to_overwrite_class_method_definition | |
| 298 | + @request.accept = 'application/rss+xml' | |
| 299 | + get :respond_to_with_resource_and_blocks | |
| 300 | + assert_equal 'Render RSS', @response.body.strip | |
| 301 | + end | |
| 302 | + | |
| 303 | + def test_respond_to_fallback_to_first_block_when_mime_type_is_all | |
| 304 | + @request.accept = '*/*' | |
| 305 | + get :respond_to_with_resource_and_blocks | |
| 306 | + assert_equal 'Render JSON', @response.body.strip | |
| 307 | + end | |
| 308 | + | |
| 309 | + def test_respond_to_skip_default_template_when_it_is_in_block | |
| 310 | + @request.accept = '*/*' | |
| 311 | + get :respond_to_skip_default_template | |
| 312 | + assert_equal 'Render HTML', @response.body.strip | |
| 313 | + end | |
| 314 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,83 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +# This test file is instead to test the how controller flow and actions | |
| 4 | +# using a belongs_to association. This is done using mocks a la rspec. | |
| 5 | +# | |
| 6 | +class Store | |
| 7 | +end | |
| 8 | + | |
| 9 | +class Manager | |
| 10 | + def self.human_name; 'Manager'; end | |
| 11 | +end | |
| 12 | + | |
| 13 | +class ManagersController < InheritedResources::Base | |
| 14 | + belongs_to :store, :singleton => true | |
| 15 | +end | |
| 16 | + | |
| 17 | +class SingletonTest < ActionController::TestCase | |
| 18 | + tests ManagersController | |
| 19 | + | |
| 20 | + def setup | |
| 21 | + @controller.stubs(:resource_url).returns('/') | |
| 22 | + @controller.stubs(:collection_url).returns('/') | |
| 23 | + end | |
| 24 | + | |
| 25 | + def test_expose_the_resquested_manager_on_show | |
| 26 | + Store.expects(:find).with('37').returns(mock_store) | |
| 27 | + mock_store.expects(:manager).returns(mock_manager) | |
| 28 | + get :show, :store_id => '37' | |
| 29 | + assert_equal mock_store, assigns(:store) | |
| 30 | + assert_equal mock_manager, assigns(:manager) | |
| 31 | + end | |
| 32 | + | |
| 33 | + def test_expose_a_new_manager_on_new | |
| 34 | + Store.expects(:find).with('37').returns(mock_store) | |
| 35 | + mock_store.expects(:build_manager).returns(mock_manager) | |
| 36 | + get :new, :store_id => '37' | |
| 37 | + assert_equal mock_store, assigns(:store) | |
| 38 | + assert_equal mock_manager, assigns(:manager) | |
| 39 | + end | |
| 40 | + | |
| 41 | + def test_expose_the_resquested_manager_on_edit | |
| 42 | + Store.expects(:find).with('37').returns(mock_store) | |
| 43 | + mock_store.expects(:manager).returns(mock_manager) | |
| 44 | + get :edit, :store_id => '37' | |
| 45 | + assert_equal mock_store, assigns(:store) | |
| 46 | + assert_equal mock_manager, assigns(:manager) | |
| 47 | + assert_response :success | |
| 48 | + end | |
| 49 | + | |
| 50 | + def test_expose_a_newly_create_manager_on_create | |
| 51 | + Store.expects(:find).with('37').returns(mock_store) | |
| 52 | + mock_store.expects(:build_manager).with({'these' => 'params'}).returns(mock_manager(:save => true)) | |
| 53 | + post :create, :store_id => '37', :manager => {:these => 'params'} | |
| 54 | + assert_equal mock_store, assigns(:store) | |
| 55 | + assert_equal mock_manager, assigns(:manager) | |
| 56 | + end | |
| 57 | + | |
| 58 | + def test_update_the_requested_object_on_update | |
| 59 | + Store.expects(:find).with('37').returns(mock_store(:manager => mock_manager)) | |
| 60 | + mock_manager.expects(:update_attributes).with({'these' => 'params'}).returns(true) | |
| 61 | + put :update, :store_id => '37', :manager => {:these => 'params'} | |
| 62 | + assert_equal mock_store, assigns(:store) | |
| 63 | + assert_equal mock_manager, assigns(:manager) | |
| 64 | + end | |
| 65 | + | |
| 66 | + def test_the_resquested_manager_is_destroyed_on_destroy | |
| 67 | + Store.expects(:find).with('37').returns(mock_store) | |
| 68 | + mock_store.expects(:manager).returns(mock_manager) | |
| 69 | + mock_manager.expects(:destroy) | |
| 70 | + delete :destroy, :store_id => '37' | |
| 71 | + assert_equal mock_store, assigns(:store) | |
| 72 | + assert_equal mock_manager, assigns(:manager) | |
| 73 | + end | |
| 74 | + | |
| 75 | + protected | |
| 76 | + def mock_store(stubs={}) | |
| 77 | + @mock_store ||= mock(stubs) | |
| 78 | + end | |
| 79 | + | |
| 80 | + def mock_manager(stubs={}) | |
| 81 | + @mock_manager ||= mock(stubs) | |
| 82 | + end | |
| 83 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb
0 → 100644
| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | +require 'test/unit' | |
| 2 | +require 'rubygems' | |
| 3 | +require 'ruby-debug' | |
| 4 | +require 'mocha' | |
| 5 | + | |
| 6 | +ENV["RAILS_ENV"] = "test" | |
| 7 | +RAILS_ROOT = "anywhere" | |
| 8 | + | |
| 9 | +require 'active_support' | |
| 10 | +require 'action_controller' | |
| 11 | +require 'action_controller/test_case' | |
| 12 | +require 'action_controller/test_process' | |
| 13 | + | |
| 14 | +I18n.load_path << File.join(File.dirname(__FILE__), 'locales', 'en.yml') | |
| 15 | +I18n.reload! | |
| 16 | + | |
| 17 | +class ApplicationController < ActionController::Base; end | |
| 18 | + | |
| 19 | +# Add IR to load path and load the main file | |
| 20 | +ActiveSupport::Dependencies.load_paths << File.expand_path(File.dirname(__FILE__) + '/../lib') | |
| 21 | +require_dependency 'inherited_resources' | |
| 22 | + | |
| 23 | +ActionController::Base.view_paths = File.join(File.dirname(__FILE__), 'views') | |
| 24 | + | |
| 25 | +ActionController::Routing::Routes.draw do |map| | |
| 26 | + map.connect ':controller/:action/:id' | |
| 27 | +end | ... | ... |
vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,471 @@ |
| 1 | +require File.dirname(__FILE__) + '/test_helper' | |
| 2 | + | |
| 3 | +class Universe; end | |
| 4 | +class UniversesController < InheritedResources::Base | |
| 5 | + defaults :singleton => true, :route_instance_name => 'universum' | |
| 6 | +end | |
| 7 | + | |
| 8 | +class House; end | |
| 9 | +class HousesController < InheritedResources::Base | |
| 10 | +end | |
| 11 | + | |
| 12 | +class Backpack; end | |
| 13 | +module Admin; end | |
| 14 | +class Admin::BackpacksController < InheritedResources::Base | |
| 15 | + defaults :route_collection_name => 'tour_backpacks' | |
| 16 | +end | |
| 17 | + | |
| 18 | +class Table; end | |
| 19 | +class TablesController < InheritedResources::Base | |
| 20 | + belongs_to :house | |
| 21 | +end | |
| 22 | + | |
| 23 | +class RoomsController < InheritedResources::Base | |
| 24 | + belongs_to :house, :route_name => 'big_house' | |
| 25 | +end | |
| 26 | + | |
| 27 | +class ChairsController < InheritedResources::Base | |
| 28 | + belongs_to :house do | |
| 29 | + belongs_to :table | |
| 30 | + end | |
| 31 | +end | |
| 32 | + | |
| 33 | +class OwnersController < InheritedResources::Base | |
| 34 | + singleton_belongs_to :house | |
| 35 | +end | |
| 36 | + | |
| 37 | +class Bed; end | |
| 38 | +class BedsController < InheritedResources::Base | |
| 39 | + optional_belongs_to :house, :building | |
| 40 | +end | |
| 41 | + | |
| 42 | +class Desk; end | |
| 43 | +module Admin | |
| 44 | + class DesksController < InheritedResources::Base | |
| 45 | + optional_belongs_to :house | |
| 46 | + end | |
| 47 | +end | |
| 48 | + | |
| 49 | +class Dish; end | |
| 50 | +class DishesController < InheritedResources::Base | |
| 51 | + belongs_to :house do | |
| 52 | + polymorphic_belongs_to :table, :kitchen | |
| 53 | + end | |
| 54 | +end | |
| 55 | + | |
| 56 | +class Center; end | |
| 57 | +class CentersController < InheritedResources::Base | |
| 58 | + acts_as_singleton! | |
| 59 | + | |
| 60 | + belongs_to :house do | |
| 61 | + belongs_to :table, :kitchen, :polymorphic => true | |
| 62 | + end | |
| 63 | +end | |
| 64 | + | |
| 65 | +# Create a TestHelper module with some helpers | |
| 66 | +class UrlHelpersTest < ActiveSupport::TestCase | |
| 67 | + | |
| 68 | + def test_url_helpers_on_simple_inherited_resource | |
| 69 | + controller = HousesController.new | |
| 70 | + controller.instance_variable_set('@house', :house) | |
| 71 | + | |
| 72 | + [:url, :path].each do |path_or_url| | |
| 73 | + controller.expects("houses_#{path_or_url}").with({}).once | |
| 74 | + controller.send("collection_#{path_or_url}") | |
| 75 | + | |
| 76 | + controller.expects("house_#{path_or_url}").with(:house, {}).once | |
| 77 | + controller.send("resource_#{path_or_url}") | |
| 78 | + | |
| 79 | + controller.expects("new_house_#{path_or_url}").with({}).once | |
| 80 | + controller.send("new_resource_#{path_or_url}") | |
| 81 | + | |
| 82 | + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once | |
| 83 | + controller.send("edit_resource_#{path_or_url}") | |
| 84 | + | |
| 85 | + # With arg | |
| 86 | + controller.expects("house_#{path_or_url}").with(:arg, {}).once | |
| 87 | + controller.send("resource_#{path_or_url}", :arg) | |
| 88 | + | |
| 89 | + controller.expects("house_#{path_or_url}").with(:arg, {}).once | |
| 90 | + controller.send("resource_#{path_or_url}", :arg) | |
| 91 | + | |
| 92 | + # With options | |
| 93 | + controller.expects("house_#{path_or_url}").with(:arg, :page => 1).once | |
| 94 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 95 | + end | |
| 96 | + end | |
| 97 | + | |
| 98 | + def test_url_helpers_on_simple_inherited_namespaced_resource | |
| 99 | + controller = Admin::BackpacksController.new | |
| 100 | + controller.instance_variable_set('@backpack', :backpack) | |
| 101 | + | |
| 102 | + assert_equal 'admin', controller.class.resources_configuration[:self][:route_prefix] | |
| 103 | + | |
| 104 | + [:url, :path].each do |path_or_url| | |
| 105 | + controller.expects("admin_tour_backpacks_#{path_or_url}").with({}).once | |
| 106 | + controller.send("collection_#{path_or_url}") | |
| 107 | + | |
| 108 | + controller.expects("admin_backpack_#{path_or_url}").with(:backpack, {}).once | |
| 109 | + controller.send("resource_#{path_or_url}") | |
| 110 | + | |
| 111 | + controller.expects("new_admin_backpack_#{path_or_url}").with({}).once | |
| 112 | + controller.send("new_resource_#{path_or_url}") | |
| 113 | + | |
| 114 | + controller.expects("edit_admin_backpack_#{path_or_url}").with(:backpack, {}).once | |
| 115 | + controller.send("edit_resource_#{path_or_url}") | |
| 116 | + | |
| 117 | + # With arg | |
| 118 | + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once | |
| 119 | + controller.send("resource_#{path_or_url}", :arg) | |
| 120 | + | |
| 121 | + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once | |
| 122 | + controller.send("resource_#{path_or_url}", :arg) | |
| 123 | + | |
| 124 | + # With options | |
| 125 | + controller.expects("admin_backpack_#{path_or_url}").with(:arg, :page => 1).once | |
| 126 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 127 | + end | |
| 128 | + end | |
| 129 | + | |
| 130 | + def test_url_helpers_on_simple_inherited_singleton_resource | |
| 131 | + controller = UniversesController.new | |
| 132 | + controller.instance_variable_set('@universe', :universe) | |
| 133 | + | |
| 134 | + [:url, :path].each do |path_or_url| | |
| 135 | + controller.expects("root_#{path_or_url}").with({}).once | |
| 136 | + controller.send("collection_#{path_or_url}") | |
| 137 | + | |
| 138 | + controller.expects("universum_#{path_or_url}").with({}).once | |
| 139 | + controller.send("resource_#{path_or_url}") | |
| 140 | + | |
| 141 | + controller.expects("new_universum_#{path_or_url}").with({}).once | |
| 142 | + controller.send("new_resource_#{path_or_url}") | |
| 143 | + | |
| 144 | + controller.expects("edit_universum_#{path_or_url}").with({}).once | |
| 145 | + controller.send("edit_resource_#{path_or_url}") | |
| 146 | + | |
| 147 | + # With options | |
| 148 | + # Also tests that argument sent are not used | |
| 149 | + controller.expects("universum_#{path_or_url}").with(:page => 1).once | |
| 150 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 151 | + end | |
| 152 | + end | |
| 153 | + | |
| 154 | + def test_url_helpers_on_belongs_to | |
| 155 | + controller = TablesController.new | |
| 156 | + controller.instance_variable_set('@house', :house) | |
| 157 | + controller.instance_variable_set('@table', :table) | |
| 158 | + | |
| 159 | + [:url, :path].each do |path_or_url| | |
| 160 | + controller.expects("house_tables_#{path_or_url}").with(:house, {}).once | |
| 161 | + controller.send("collection_#{path_or_url}") | |
| 162 | + | |
| 163 | + controller.expects("house_table_#{path_or_url}").with(:house, :table, {}).once | |
| 164 | + controller.send("resource_#{path_or_url}") | |
| 165 | + | |
| 166 | + controller.expects("new_house_table_#{path_or_url}").with(:house, {}).once | |
| 167 | + controller.send("new_resource_#{path_or_url}") | |
| 168 | + | |
| 169 | + controller.expects("edit_house_table_#{path_or_url}").with(:house, :table, {}).once | |
| 170 | + controller.send("edit_resource_#{path_or_url}") | |
| 171 | + | |
| 172 | + # With arg | |
| 173 | + controller.expects("house_table_#{path_or_url}").with(:house, :arg, {}).once | |
| 174 | + controller.send("resource_#{path_or_url}", :arg) | |
| 175 | + | |
| 176 | + controller.expects("edit_house_table_#{path_or_url}").with(:house, :arg, {}).once | |
| 177 | + controller.send("edit_resource_#{path_or_url}", :arg) | |
| 178 | + | |
| 179 | + # With options | |
| 180 | + controller.expects("house_table_#{path_or_url}").with(:house, :arg, :page => 1).once | |
| 181 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 182 | + end | |
| 183 | + end | |
| 184 | + | |
| 185 | + def test_url_helpers_on_not_default_belongs_to | |
| 186 | + controller = RoomsController.new | |
| 187 | + controller.instance_variable_set('@house', :house) | |
| 188 | + controller.instance_variable_set('@room', :room) | |
| 189 | + | |
| 190 | + [:url, :path].each do |path_or_url| | |
| 191 | + controller.expects("big_house_rooms_#{path_or_url}").with(:house, {}).once | |
| 192 | + controller.send("collection_#{path_or_url}") | |
| 193 | + | |
| 194 | + controller.expects("big_house_room_#{path_or_url}").with(:house, :room, {}).once | |
| 195 | + controller.send("resource_#{path_or_url}") | |
| 196 | + | |
| 197 | + controller.expects("new_big_house_room_#{path_or_url}").with(:house, {}).once | |
| 198 | + controller.send("new_resource_#{path_or_url}") | |
| 199 | + | |
| 200 | + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :room, {}).once | |
| 201 | + controller.send("edit_resource_#{path_or_url}") | |
| 202 | + | |
| 203 | + # With args | |
| 204 | + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, {}).once | |
| 205 | + controller.send("resource_#{path_or_url}", :arg) | |
| 206 | + | |
| 207 | + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :arg, {}).once | |
| 208 | + controller.send("edit_resource_#{path_or_url}", :arg) | |
| 209 | + | |
| 210 | + # With options | |
| 211 | + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, :page => 1).once | |
| 212 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 213 | + end | |
| 214 | + end | |
| 215 | + | |
| 216 | + def test_url_helpers_on_nested_belongs_to | |
| 217 | + controller = ChairsController.new | |
| 218 | + controller.instance_variable_set('@house', :house) | |
| 219 | + controller.instance_variable_set('@table', :table) | |
| 220 | + controller.instance_variable_set('@chair', :chair) | |
| 221 | + | |
| 222 | + [:url, :path].each do |path_or_url| | |
| 223 | + controller.expects("house_table_chairs_#{path_or_url}").with(:house, :table, {}).once | |
| 224 | + controller.send("collection_#{path_or_url}") | |
| 225 | + | |
| 226 | + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once | |
| 227 | + controller.send("resource_#{path_or_url}") | |
| 228 | + | |
| 229 | + controller.expects("new_house_table_chair_#{path_or_url}").with(:house, :table, {}).once | |
| 230 | + controller.send("new_resource_#{path_or_url}") | |
| 231 | + | |
| 232 | + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once | |
| 233 | + controller.send("edit_resource_#{path_or_url}") | |
| 234 | + | |
| 235 | + # With args | |
| 236 | + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once | |
| 237 | + controller.send("edit_resource_#{path_or_url}", :arg) | |
| 238 | + | |
| 239 | + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once | |
| 240 | + controller.send("resource_#{path_or_url}", :arg) | |
| 241 | + | |
| 242 | + # With options | |
| 243 | + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, :page => 1).once | |
| 244 | + controller.send("edit_resource_#{path_or_url}", :arg, :page => 1) | |
| 245 | + end | |
| 246 | + end | |
| 247 | + | |
| 248 | + def test_url_helpers_on_singletons_with_belongs_to | |
| 249 | + controller = OwnersController.new | |
| 250 | + controller.instance_variable_set('@house', :house) | |
| 251 | + controller.instance_variable_set('@owner', :owner) | |
| 252 | + | |
| 253 | + [:url, :path].each do |path_or_url| | |
| 254 | + controller.expects("house_#{path_or_url}").with(:house, {}).once | |
| 255 | + controller.send("collection_#{path_or_url}") | |
| 256 | + | |
| 257 | + controller.expects("house_owner_#{path_or_url}").with(:house, {}).once | |
| 258 | + controller.send("resource_#{path_or_url}") | |
| 259 | + | |
| 260 | + controller.expects("new_house_owner_#{path_or_url}").with(:house, {}).once | |
| 261 | + controller.send("new_resource_#{path_or_url}") | |
| 262 | + | |
| 263 | + controller.expects("edit_house_owner_#{path_or_url}").with(:house, {}).once | |
| 264 | + controller.send("edit_resource_#{path_or_url}") | |
| 265 | + | |
| 266 | + # With options | |
| 267 | + # Also tests that argument sent are not used | |
| 268 | + controller.expects("house_owner_#{path_or_url}").with(:house, :page => 1).once | |
| 269 | + controller.send("resource_#{path_or_url}", :arg, :page => 1) | |
| 270 | + end | |
| 271 | + end | |
| 272 | + | |
| 273 | + def test_url_helpers_on_polymorphic_belongs_to | |
| 274 | + house = House.new | |
| 275 | + bed = Bed.new | |
| 276 | + | |
| 277 | + new_bed = Bed.new | |
| 278 | + Bed.stubs(:new).returns(new_bed) | |
| 279 | + new_bed.stubs(:new_record?).returns(true) | |
| 280 | + | |
| 281 | + controller = BedsController.new | |
| 282 | + controller.instance_variable_set('@parent_type', :house) | |
| 283 | + controller.instance_variable_set('@house', house) | |
| 284 | + controller.instance_variable_set('@bed', bed) | |
| 285 | + | |
| 286 | + [:url, :path].each do |path_or_url| | |
| 287 | + controller.expects("house_beds_#{path_or_url}").with(house).once | |
| 288 | + controller.send("collection_#{path_or_url}") | |
| 289 | + | |
| 290 | + controller.expects("house_bed_#{path_or_url}").with(house, bed).once | |
| 291 | + controller.send("resource_#{path_or_url}") | |
| 292 | + | |
| 293 | + controller.expects("new_house_bed_#{path_or_url}").with(house).once | |
| 294 | + controller.send("new_resource_#{path_or_url}") | |
| 295 | + | |
| 296 | + controller.expects("edit_house_bed_#{path_or_url}").with(house, bed).once | |
| 297 | + controller.send("edit_resource_#{path_or_url}") | |
| 298 | + end | |
| 299 | + | |
| 300 | + # With options | |
| 301 | + controller.expects("house_bed_url").with(house, bed, :page => 1).once | |
| 302 | + controller.send("resource_url", :page => 1) | |
| 303 | + | |
| 304 | + # With args | |
| 305 | + controller.expects("polymorphic_url").with([:arg, new_bed], {}).once | |
| 306 | + controller.send("collection_url", :arg) | |
| 307 | + | |
| 308 | + controller.expects("polymorphic_url").with([house, :arg], {}).once | |
| 309 | + controller.send("resource_url", :arg) | |
| 310 | + | |
| 311 | + controller.expects("edit_polymorphic_url").with([house, :arg], {}).once | |
| 312 | + controller.send("edit_resource_url", :arg) | |
| 313 | + end | |
| 314 | + | |
| 315 | + def test_url_helpers_on_namespaced_polymorphic_belongs_to | |
| 316 | + house = House.new | |
| 317 | + desk = Desk.new | |
| 318 | + | |
| 319 | + new_desk = Desk.new | |
| 320 | + Desk.stubs(:new).returns(new_desk) | |
| 321 | + new_desk.stubs(:new_record?).returns(true) | |
| 322 | + | |
| 323 | + controller = Admin::DesksController.new | |
| 324 | + controller.instance_variable_set('@parent_type', :house) | |
| 325 | + controller.instance_variable_set('@house', house) | |
| 326 | + controller.instance_variable_set('@desk', desk) | |
| 327 | + | |
| 328 | + [:url, :path].each do |path_or_url| | |
| 329 | + controller.expects("admin_house_desks_#{path_or_url}").with(house).once | |
| 330 | + controller.send("collection_#{path_or_url}") | |
| 331 | + | |
| 332 | + controller.expects("admin_house_desk_#{path_or_url}").with(house, desk).once | |
| 333 | + controller.send("resource_#{path_or_url}") | |
| 334 | + | |
| 335 | + controller.expects("new_admin_house_desk_#{path_or_url}").with(house).once | |
| 336 | + controller.send("new_resource_#{path_or_url}") | |
| 337 | + | |
| 338 | + controller.expects("edit_admin_house_desk_#{path_or_url}").with(house, desk).once | |
| 339 | + controller.send("edit_resource_#{path_or_url}") | |
| 340 | + end | |
| 341 | + | |
| 342 | + # With options | |
| 343 | + controller.expects("admin_house_desk_url").with(house, desk, :page => 1).once | |
| 344 | + controller.send("resource_url", :page => 1) | |
| 345 | + | |
| 346 | + # With args | |
| 347 | + controller.expects("polymorphic_url").with(['admin', :arg, new_desk], {}).once | |
| 348 | + controller.send("collection_url", :arg) | |
| 349 | + | |
| 350 | + controller.expects("polymorphic_url").with(['admin', house, :arg], {}).once | |
| 351 | + controller.send("resource_url", :arg) | |
| 352 | + | |
| 353 | + controller.expects("edit_polymorphic_url").with(['admin', house, :arg], {}).once | |
| 354 | + controller.send("edit_resource_url", :arg) | |
| 355 | + end | |
| 356 | + | |
| 357 | + def test_url_helpers_on_nested_polymorphic_belongs_to | |
| 358 | + house = House.new | |
| 359 | + table = Table.new | |
| 360 | + dish = Dish.new | |
| 361 | + | |
| 362 | + new_dish = Dish.new | |
| 363 | + Dish.stubs(:new).returns(new_dish) | |
| 364 | + new_dish.stubs(:new_record?).returns(true) | |
| 365 | + | |
| 366 | + controller = DishesController.new | |
| 367 | + controller.instance_variable_set('@parent_type', :table) | |
| 368 | + controller.instance_variable_set('@house', house) | |
| 369 | + controller.instance_variable_set('@table', table) | |
| 370 | + controller.instance_variable_set('@dish', dish) | |
| 371 | + | |
| 372 | + [:url, :path].each do |path_or_url| | |
| 373 | + controller.expects("house_table_dishes_#{path_or_url}").with(house, table).once | |
| 374 | + controller.send("collection_#{path_or_url}") | |
| 375 | + | |
| 376 | + controller.expects("house_table_dish_#{path_or_url}").with(house, table, dish).once | |
| 377 | + controller.send("resource_#{path_or_url}") | |
| 378 | + | |
| 379 | + controller.expects("new_house_table_dish_#{path_or_url}").with(house, table).once | |
| 380 | + controller.send("new_resource_#{path_or_url}") | |
| 381 | + | |
| 382 | + controller.expects("edit_house_table_dish_#{path_or_url}").with(house, table, dish).once | |
| 383 | + controller.send("edit_resource_#{path_or_url}") | |
| 384 | + end | |
| 385 | + | |
| 386 | + # With options | |
| 387 | + controller.expects("house_table_dish_url").with(house, table, dish, :page => 1).once | |
| 388 | + controller.send("resource_url", :page => 1) | |
| 389 | + | |
| 390 | + # With args | |
| 391 | + controller.expects("polymorphic_url").with([house, table, :arg], {}).once | |
| 392 | + controller.send("resource_url", :arg) | |
| 393 | + | |
| 394 | + controller.expects("edit_polymorphic_url").with([house, table, :arg], {}).once | |
| 395 | + controller.send("edit_resource_url", :arg) | |
| 396 | + end | |
| 397 | + | |
| 398 | + def test_url_helpers_on_singleton_nested_polymorphic_belongs_to | |
| 399 | + # This must not be usefull in singleton controllers... | |
| 400 | + # Center.new | |
| 401 | + house = House.new | |
| 402 | + table = Table.new | |
| 403 | + | |
| 404 | + controller = CentersController.new | |
| 405 | + controller.instance_variable_set('@parent_type', :table) | |
| 406 | + controller.instance_variable_set('@house', house) | |
| 407 | + controller.instance_variable_set('@table', table) | |
| 408 | + | |
| 409 | + # This must not be useful in singleton controllers... | |
| 410 | + # controller.instance_variable_set('@center', :center) | |
| 411 | + | |
| 412 | + [:url, :path].each do |path_or_url| | |
| 413 | + controller.expects("house_table_#{path_or_url}").with(house, table).once | |
| 414 | + controller.send("collection_#{path_or_url}") | |
| 415 | + | |
| 416 | + controller.expects("house_table_center_#{path_or_url}").with(house, table).once | |
| 417 | + controller.send("resource_#{path_or_url}") | |
| 418 | + | |
| 419 | + controller.expects("new_house_table_center_#{path_or_url}").with(house, table).once | |
| 420 | + controller.send("new_resource_#{path_or_url}") | |
| 421 | + | |
| 422 | + controller.expects("edit_house_table_center_#{path_or_url}").with(house, table).once | |
| 423 | + controller.send("edit_resource_#{path_or_url}") | |
| 424 | + end | |
| 425 | + | |
| 426 | + # With options | |
| 427 | + controller.expects("house_table_center_url").with(house, table, :page => 1) | |
| 428 | + controller.send("resource_url", :page => 1) | |
| 429 | + | |
| 430 | + # With args | |
| 431 | + controller.expects("polymorphic_url").with([house, table, :center], {}).once | |
| 432 | + controller.send("resource_url", :arg) | |
| 433 | + end | |
| 434 | + | |
| 435 | + def test_url_helpers_on_optional_polymorphic_belongs_to | |
| 436 | + bed = Bed.new | |
| 437 | + new_bed = Bed.new | |
| 438 | + Bed.stubs(:new).returns(new_bed) | |
| 439 | + new_bed.stubs(:new_record?).returns(true) | |
| 440 | + | |
| 441 | + controller = BedsController.new | |
| 442 | + controller.instance_variable_set('@parent_type', nil) | |
| 443 | + controller.instance_variable_set('@bed', bed) | |
| 444 | + | |
| 445 | + [:url, :path].each do |path_or_url| | |
| 446 | + controller.expects("beds_#{path_or_url}").with().once | |
| 447 | + controller.send("collection_#{path_or_url}") | |
| 448 | + | |
| 449 | + controller.expects("bed_#{path_or_url}").with(bed).once | |
| 450 | + controller.send("resource_#{path_or_url}") | |
| 451 | + | |
| 452 | + controller.expects("new_bed_#{path_or_url}").with().once | |
| 453 | + controller.send("new_resource_#{path_or_url}") | |
| 454 | + | |
| 455 | + controller.expects("edit_bed_#{path_or_url}").with(bed).once | |
| 456 | + controller.send("edit_resource_#{path_or_url}") | |
| 457 | + end | |
| 458 | + | |
| 459 | + # With options | |
| 460 | + controller.expects("bed_url").with(bed, :page => 1).once | |
| 461 | + controller.send("resource_url", :page => 1) | |
| 462 | + | |
| 463 | + # With args | |
| 464 | + controller.expects("polymorphic_url").with([:arg], {}).once | |
| 465 | + controller.send("resource_url", :arg) | |
| 466 | + | |
| 467 | + controller.expects("edit_polymorphic_url").with([:arg], {}).once | |
| 468 | + controller.send("edit_resource_url", :arg) | |
| 469 | + end | |
| 470 | + | |
| 471 | +end | ... | ... |