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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 |