From 48c7a14e1352c12068961b181196222d95aabc2c Mon Sep 17 00:00:00 2001 From: Dan Croak Date: Thu, 13 Aug 2009 22:48:57 -0400 Subject: [PATCH] added josevalim's inherited resources for RESTful controllers --- vendor/gems/josevalim-inherited_resources-0.8.5/.specification | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE | 20 ++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/README | 517 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile | 35 +++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/VERSION | 1 + vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb | 18 ++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb | 39 +++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb | 328 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb | 20 ++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb | 27 +++++++++++++++++++++++++++ vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 35 files changed, 4937 insertions(+), 0 deletions(-) create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/.specification create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/README create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/VERSION create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb create mode 100644 vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/.specification b/vendor/gems/josevalim-inherited_resources-0.8.5/.specification new file mode 100644 index 0000000..8a7fa14 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/.specification @@ -0,0 +1,104 @@ +--- !ruby/object:Gem::Specification +name: josevalim-inherited_resources +version: !ruby/object:Gem::Version + version: 0.8.5 +platform: ruby +authors: +- "Jos\xC3\xA9 Valim" +autorequire: +bindir: bin +cert_chain: [] + +date: 2009-07-24 00:00:00 -04:00 +default_executable: +dependencies: [] + +description: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important. +email: jose.valim@gmail.com +executables: [] + +extensions: [] + +extra_rdoc_files: +- README +files: +- CHANGELOG +- MIT-LICENSE +- README +- Rakefile +- VERSION +- lib/inherited_resources.rb +- lib/inherited_resources/actions.rb +- lib/inherited_resources/base.rb +- lib/inherited_resources/base_helpers.rb +- lib/inherited_resources/belongs_to_helpers.rb +- lib/inherited_resources/class_methods.rb +- lib/inherited_resources/dumb_responder.rb +- lib/inherited_resources/has_scope_helpers.rb +- lib/inherited_resources/polymorphic_helpers.rb +- lib/inherited_resources/respond_to.rb +- lib/inherited_resources/singleton_helpers.rb +- lib/inherited_resources/url_helpers.rb +- test/respond_to_test.rb +- test/customized_belongs_to_test.rb +- test/nested_belongs_to_test.rb +- test/base_test.rb +- test/redirect_to_test.rb +- test/has_scope_test.rb +- test/class_methods_test.rb +- test/aliases_test.rb +- test/flash_test.rb +- test/url_helpers_test.rb +- test/base_helpers_test.rb +- test/belongs_to_test.rb +- test/polymorphic_test.rb +- test/defaults_test.rb +- test/singleton_test.rb +- test/optional_belongs_to_test.rb +- test/test_helper.rb +has_rdoc: true +homepage: http://github.com/josevalim/inherited_resources +licenses: [] + +post_install_message: +rdoc_options: +- --charset=UTF-8 +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] + +rubyforge_project: inherited_resources +rubygems_version: 1.3.4 +signing_key: +specification_version: 3 +summary: Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important. +test_files: +- test/respond_to_test.rb +- test/customized_belongs_to_test.rb +- test/nested_belongs_to_test.rb +- test/base_test.rb +- test/redirect_to_test.rb +- test/has_scope_test.rb +- test/class_methods_test.rb +- test/aliases_test.rb +- test/flash_test.rb +- test/url_helpers_test.rb +- test/base_helpers_test.rb +- test/belongs_to_test.rb +- test/polymorphic_test.rb +- test/defaults_test.rb +- test/singleton_test.rb +- test/optional_belongs_to_test.rb +- test/test_helper.rb diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG b/vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG new file mode 100644 index 0000000..0b9872e --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/CHANGELOG @@ -0,0 +1,95 @@ +# Version 0.8 + +* Fixed a small bug on optional belongs to with namespaced controllers. +* Allow a parameter to be given to collection_url in polymorphic cases to replace + the parent. +* Allow InheritedResources to be called without inheritance. +* Ensure that controllers that inherit from a controller with InheritedResources + works properly. + +# Version 0.7 + +* Allow procs as default value in has scope to be able to use values from session, for example. +* Allow blocks with arity 0 or -1 to be given as the redirect url: + + def destroy + destroy!{ project_url(@project) } + end + +* Allow interpolation_options to be set in the application controller. +* Added has_scope to controller (an interface for named_scopes). +* Added polymorphic_belongs_to, optional_belongs_to and singleton_belongs_to + as quick methods. +* Only load belongs_to, singleton and polymorphic helpers if they are actually + required. base_helpers, class_methods, dumb_responder and url_helpers are loaded + when you inherited from base for the first time. + +# Version 0.6 + +* Ensure that the default template is not rendered if the default_template_format + is not accepted. This is somehow related with the security breach report: + + http://www.rorsecurity.info/journal/2009/4/24/hidden-actions-render-templates.html + + IR forbids based on mime types. For example: respond_to :html, :except => :index + ensures that the index.html.erb view is not rendered, making your IR controllers + safer. + +* Fixed a bug that happens only when format.xml is given to blocks and then it + acts as default, instead of format.html. +* Fixed a strange bug where when you have create.html.erb or update.html.erb, + it makes IE6 and IE7 return unprocessable entity (because they send Mime::ALL). +* Stop rescueing any error when constantizing the resource class and allow + route_prefix to be nil. +* Cleaned up tests and responder structure. Whenever you pass a block to aliases + and this block responds to the request, the other blocks are not parsed improving performance. +* [BACKWARDS INCOMPATIBLE] By default, Inherited Resources respond only :html requests. +* Added a quick way to overwrite the redirect to url in :create, :update and :destroy. + +# Version 0.5 + +* Decoupled routes name from :instance_name and :collection_name. This way we + have more flexibility. Use route_instance_name and route_collection_name to + to change routes. +* Avoid calling human_name on nil when a resource class is not defined. +* Only call I18n if it's defined. + +# Version 0.4 + +* Dealing with namespaced controllers out of the box. +* Added support to namespaced routes through :route_prefix. +* Added fix when resource_url is not defined. +* Added better handling for namespaced controllers. +* Added flash messages scoped by namespaced controllers. +* Deprecated {{resource}} in I18n, use {{resource_name}} instead. +* rspec bug fix is not automatically required anymore. User has to do it + explicitly. +* Added a file which fix a rspec bug when render is called inside a method + which receives a block. +* parent? does not take begin_of_association_chain into account anymore +* Added options to url helpers. +* Added :optional to belongs_to associations. It allows you to deal with + categories/1/products/2 and /products/2 with just one controller. +* Cleaned up tests. + +# Version 0.3 + +* Minor bump after three bug fixes. +* Bug fix when showing warning of constant redefinition. +* Bug fix with ApplicationController not being unloaded properly on development. +* Bug fix when having root singleton resources. Calling collection_url would + raise "NoMethodError _url", not it will call root_url. +* More comments on UrlHelpers. + +# Version 0.2 + +* Bug fix when ApplicationController is already loaded when we load respond_to. +* Added support success/failure blocks. +* Eager loading of files to work properly in multithreaded environments. + +# Version 0.1 + +* Added more helper_methods. +* Added Rails 2.3.0 and changed tests to work with ActionController::TestCase. +* First release. Support to I18n, singleton controllers, polymorphic +controllers, belongs_to, nested_belongs_to and url helpers. diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE b/vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE new file mode 100644 index 0000000..95d4d12 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009 José Valim + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/README b/vendor/gems/josevalim-inherited_resources-0.8.5/README new file mode 100644 index 0000000..3b990c3 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/README @@ -0,0 +1,517 @@ +Inherited Resources +License: MIT +Version: 0.8.5 + +You can also read this README in pretty html at the GitHub project Wiki page: + + http://wiki.github.com/josevalim/inherited_resources + +Description +----------- + +Inherited Resources speeds up development by making your controllers inherit +all restful actions so you just have to focus on what is important. It makes +your controllers more powerful and cleaner at the same time. + +Plus, making your controllers follow a pattern, it helps you to write better +code by following fat models and skinny controllers convention. + +Inherited Resources is tested and compatible with Rails 2.2.x and Rails 2.3.x. + +keywords: resources, controller, singleton, belongs_to, polymorphic, named_scope and I18n + +Installation +------------ + +Install Inherited Resources is very easy. It is stored in GitHub, so just run +the following: + + gem sources -a http://gems.github.com + sudo gem install josevalim-inherited_resources + +If you want it as plugin, just do: + + script/plugin install git://github.com/josevalim/inherited_resources.git + +rspec-rails <= 1.1.12 known bug +------------------------------- + +InheritedResources has a known bug with rspec-rails. Please upgrade your rspec +version or use the fix which ships with InheritedResources: + + require 'inherited_resources/spec' + +Basic Usage +----------- + +To use Inherited Resources you just have to inherit (duh) it: + + class ProjectsController < InheritedResources::Base + end + +And all actions are defined and working, check it! Your projects collection +(in the index action) is still available in the instance variable @projects +and your project resource (all other actions) is available as @ project. + +The next step is to define which mime types this controller provides: + + class ProjectsController < InheritedResources::Base + respond_to :html, :xml, :json + end + +You can also specify them based per action: + + class ProjectsController < InheritedResources::Base + respond_to :html, :xml, :json + respond_to :js, :only => :create + respond_to :iphone, :except => [ :edit, :update ] + end + +For each request, it first checkes if the "controller/action.format" file is +available (for example "projects/create.xml") and if it's not, it checks if +the resource respond to :to_format (in this case, :to_xml). Otherwise returns 404. + +Another option is to specify which actions the controller will inherit from +the InheritedResources::Base: + + class ProjectsController < InheritedResources::Base + actions :index, :show, :new, :create + end + +Or: + + class ProjectsController < InheritedResources::Base + actions :all, :except => [ :edit, :update, :destroy ] + end + +In your views, you will get the following helpers: + + resource #=> @project + collection #=> @projects + resource_class #=> Project + +As you might expect, collection (@projects instance variable) is only available +on index actions. + +If for some reason you cannot inherit from InheritedResources::Base, you can +call inherit_resources or resource_controller in your controller class scope: + + class AccountsController < ApplicationController + inherit_resources # or resource_controller + end + +Overwriting defaults +-------------------- + +Whenever you inherit from InheritedResources, several defaults are assumed. +For example you can have an AccountsController to account management while the +resource is an User: + + class AccountsController < InheritedResources::Base + defaults :resource_class => User, :collection_name, 'users', :instance_name => 'user' + end + +In the case above, in your views you will have @users and @user variables, but +the routes used will still be accounts_url and account_url. If you plan also to +change the routes, you can use :route_collection_name and :route_instance_name. + +Namespaced controllers work out of the box, but if you need to specify a +different route prefix, you can do the following: + + class Administrators::PeopleController < InheritedResources::Base + defaults :route_prefix => 'admin' + end + +Then your named routes will be: 'admin_people_url', 'admin_person_url' instead +of 'administrators_people_url' and 'administrators_person_url'. + +If you want to customize how resources are retrieved you can overwrite +collection and resource methods. The first is called on index action and the +second on all other actions. Let's suppose you want to add pagination to your +projects collection: + + class ProjectsController < InheritedResources::Base + protected + def collection + @projects ||= end_of_association_chain.paginate(params[:page]).all + end + end + +The end_of_association_chain returns your resource after nesting all associations +and scopes (more about this below). + +InheritedResources also introduces another method called begin_of_association_chain. +It's mostly used when you want to create resources based on the @current_user and +you have urls like "account/projects". In such cases, you have to do +@current_user.projects.find or @current_user.projects.build in your actions. + +You can deal with it just doing: + + class ProjectsController < InheritedResources::Base + protected + def begin_of_association_chain + @current_user + end + end + +Overwriting actions +------------------- + +Let's suppose that after destroying a project you want to redirect to your +root url instead of redirecting to projects url. You just have to do: + + class ProjectsController < InheritedResources::Base + def destroy + super do |format| + format.html { redirect_to root_url } + end + end + end + +You are opening your action and giving the parent action a new behavior. No +tricks, no DSL, just Ruby. + +On the other hand, I have to agree that calling super is not very readable. +That's why all methods have aliases. So this is equivalent: + + class ProjectsController < InheritedResources::Base + def destroy + destroy! do |format| + format.html { redirect_to root_url } + end + end + end + +Even more, since most of the times when you change a create, update or destroy +action is because you want to to change to where it redirects, a shortcut is +provided. So you can do: + + class ProjectsController < InheritedResources::Base + def destroy + destroy!{ root_url } + end + end + +Now let's suppose that before create a project you have to do something special +but you don't want to create a before filter for it: + + class ProjectsController < InheritedResources::Base + def create + @project = Project.new(params[:project]) + @project.something_special! + create! + end + end + +Yes, that simple! The nice part is since you already set the instance variable +@project, it will not build a project again. + +Before we finish this topic, we should talk about one more thing: "success/failure +blocks". Let's suppose that when we update our project, in case of failure, we +want to redirect to the project url instead of re-rendering the edit template. + +Our first attempt to do this would be: + + class ProjectsController < InheritedResources::Base + def update + update! do |format| + unless @project.errors.empty? # failure + format.html { redirect_to project_url(@project) } + end + end + end + end + +Looks to verbose, right? We can actually do: + + class ProjectsController < InheritedResources::Base + def update + update! do |success, failure| + failure.html { redirect_to project_url(@project) } + end + end + end + +Much better! So explaining everything: when you give a block which expects one +argument it will be executed in both scenarios: success and failure. But If you +give a block that expects two arguments, the first will be executed only in +success scenarios and the second in failure scenarios. You keep everything +clean and organized inside the same action. + +Flash messages and I18n +----------------------- + +Flash messages are powered by I18n api. It checks for messages in the following +order: + + flash.controller_name.action_name.status + flash.actions.action_name.status + +If none is available, a default message in english set. In a create action +on projects controller, it will search for: + + flash.projects.create.status + flash.actions.create.status + +The status can be :notice (when the object can be created, updated +or destroyed with success) or :error (when the objecy cannot be created +or updated). + +Those messages are interpolated by using the resource class human name, which +is also localized and it means you can set: + + flash: + actions: + create: + notice: "Hooray! {{resource_name}} was successfully created!" + +It will replace {{resource_name}} by the human name of the resource class, +which is "Project" in this case. + +But sometimes, flash messages are not that simple. Sometimes you want to say +the title of the project while updating a project. Well, that's easy also: + + flash: + projects: + update: + notice: "Hooray! The project "{{project_title}}" was updated!" + +Since :project_title is not available for interpolation by default, you have +to overwrite interpolation_options. + + def interpolation_options + { :project_title => @project.title } + end + +Then you will finally have: + + "Hooray! The project "Plataforma" was updated!" + +By default, resource name is capitalized. If you want to make it lower case, you +can add to your application controller: + + def interpolation_options + { :resource_name => resource_class.human_name.downcase } + end + +Finally, if your controller is namespaced, for example Admin::ProjectsController, +the messages will be checked in the following order: + + flash.admin.projects.create.notice + flash.admin.actions.create.notice + flash.projects.create.notice + flash.actions.create.notice + +Has Scope +--------- + +InheritedResources tries to integrate nicely with your model. In order to do so, +it also is named_scope fluent. Let's suppose our Project model with the scopes: + + class ProjectsController < ActiveRecord::Base + named_scope :featured, :conditions => { :featured => true } + named_scope :by_methodology, proc {|methodology| { :conditions => { :methodology => methodology } } } + named_scope :limit, proc{|limit| :limit => limit.to_i } + end + +Your controller: + + class ProjectsController < InheritedResources::Base + has_scope :featured, :boolean => true, :only => :index + has_scope :by_methodology + has_scope :limit, :default => 10 + end + +Then for each request: + + /projects + #=> acts like a normal request, but returning 10 projects + + /projects?featured=true + #=> calls the featured named scope and bring 10 featured projects + + /projects?featured=true&by_methodology=agile&limit=20 + #=> brings 20 featured projects with methodology agile + +You can retrieve the current scopes in use with :current_scopes method. +In the last case, it would return: + + { :featured => "true", :by_methodology => "agile", :limit => "20" } + +Finally, let's suppose you store on the session how many projects the user sees +per page. In such cases, you can give a proc as default value: + + has_scope :limit, :default => proc{|c| c.session[:limit] || 10 } + +Belongs to +---------- + +Finally, our Projects are going to get some Tasks. Then you create a +TasksController and do: + + class TasksController < InheritedResources::Base + belongs_to :project + end + +belongs_to accepts several options to be able to configure the association. +For example, if you want urls like /projects/:project_title/tasks, you can +customize how InheritedResources find your projects: + + class TasksController < InheritedResources::Base + belongs_to :project, :finder => :find_by_title!, :param => :project_title + end + +It also accepts :route_name, :parent_class and :instance_name as options. +Check the lib/inherited_resources/class_methods.rb for more. + +Nested belongs to +----------------- + +Now, our Tasks get some Comments and you need to nest even deeper. Good +practices says that you should never nest more than two resources, but sometimes +you have to for security reasons. So this is an example of how you can do it: + + class CommentsController < InheritedResources::Base + nested_belongs_to :project, :task + end + +If you need to configure any of these belongs to, you can nested them using blocks: + + class CommentsController < InheritedResources::Base + belongs_to :project, :finder => :find_by_title!, :param => :project_title do + belongs_to :task + end + end + +Warning: calling several belongs_to is the same as nesting them: + + class CommentsConroller < InheritedResources::Base + belongs_to :project + belongs_to :task + end + +In other words, the code above is the same as calling nested_belongs_to. + +Polymorphic belongs to +---------------------- + +We can go even further. Let's suppose our Projects can now have Files, Messages +and Tasks, and they are all commentable. In this case, the best solution is to +use polymorphism: + + class CommentsController < InheritedResources::Base + belongs_to :task, :file, :message, :polymorphic => true + # polymorphic_belongs_to :task, :file, :message + end + +You can even use it with nested resources: + + class CommentsController < InheritedResources::Base + belongs_to :project do + belongs_to :task, :file, :message, :polymorphic => true + end + end + +The url in such cases can be: + + /project/1/task/13/comments + /project/1/file/11/comments + /project/1/message/9/comments + +When using polymorphic associations, you get some free helpers: + + parent? #=> true + parent_type #=> :task + parent_class #=> Task + parent #=> @task + +Optional belongs to +------------------- + +Later you decide to create a view to show all comments, independent if they belong +to a task, file or message. You can reuse your polymorphic controller just doing: + + class ProjectsController < InheritedResources::Base + belongs_to :task, :file, :message, :optional => true + # optional_belongs_to :task, :file, :message + end + +This will handle all those urls properly: + + /comment/1 + /tasks/2/comment/5 + /files/10/comment/3 + /messages/13/comment/11 + +This is treated as a special type of polymorphic associations, thus all helpers +are available. As you expect, when no parent is found, the helpers return: + + parent? #=> false + parent_type #=> nil + parent_class #=> nil + parent #=> nil + +Singletons +---------- + +Now we are going to add manager to projects. We say that Manager is a singleton +resource because a Project has just one manager. You should declare it as +has_one (or resource) in your routes. + +To declare an association as singleton, you just have to give the :singleton +option. + + class ManagersController < InheritedResources::Base + belongs_to :project, :singleton => true + # singleton_belongs_to :project + end + +It will deal with everything again and hide the action :index from you. + +URL Helpers +----------- + +When you use InheritedResources it creates some URL helpers. +And they handle everything for you. :) + + # /posts/1/comments + resource_url # => /posts/1/comments/#{@comment.to_param} + resource_url(comment) # => /posts/1/comments/#{comment.to_param} + new_resource_url # => /posts/1/comments/new + edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit + edit_resource_url(comment) #=> /posts/1/comments/#{comment.to_param}/edit + collection_url # => /posts/1/comments + + # /projects/1/tasks + resource_url # => /projects/1/tasks/#{@task.to_param} + resource_url(task) # => /projects/1/tasks/#{task.to_param} + new_resource_url # => /projects/1/tasks/new + edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit + edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit + collection_url # => /projects/1/tasks + + # /users + resource_url # => /users/#{@user.to_param} + resource_url(user) # => /users/#{user.to_param} + new_resource_url # => /users/new + edit_resource_url # => /users/#{@user.to_param}/edit + edit_resource_url(user) # => /users/#{user.to_param}/edit + collection_url # => /users + +Those urls helpers also accepts a hash as options, just as in named routes. + + # /projects/1/tasks + collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10 + +Another nice thing is that those urls are not guessed during runtime. They are +all created when your application is loaded (except for polymorphic +associations, that relies on Rails polymorphic_url). + +Bugs and Feedback +----------------- + +If you discover any bugs, please send an e-mail to jose.valim@gmail.com +If you just want to give some positive feedback or drop a line, that's fine too! + +Copyright (c) 2009 José Valim +http://josevalim.blogspot.com/ diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile b/vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile new file mode 100644 index 0000000..005760e --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/Rakefile @@ -0,0 +1,35 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +begin + require 'jeweler' + Jeweler::Tasks.new do |s| + s.name = "inherited_resources" + s.rubyforge_project = "inherited_resources" + 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." + s.email = "jose.valim@gmail.com" + s.homepage = "http://github.com/josevalim/inherited_resources" + 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." + s.authors = ['José Valim'] + s.files = FileList["[A-Z]*", "{lib}/**/*"] + end +rescue LoadError + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" +end + +desc 'Run tests for InheritedResources.' +Rake::TestTask.new(:test) do |t| + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for InheritedResources.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'InheritedResources' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('MIT-LICENSE') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/VERSION b/vendor/gems/josevalim-inherited_resources-0.8.5/VERSION new file mode 100644 index 0000000..7ada0d3 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/VERSION @@ -0,0 +1 @@ +0.8.5 diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb new file mode 100644 index 0000000..1c11405 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources.rb @@ -0,0 +1,18 @@ +# respond_to is the only file that should be loaded before hand. All others +# are loaded on demand. +# +require File.join(File.dirname(__FILE__), 'inherited_resources', 'respond_to') + +module InheritedResources; end + +class ActionController::Base + # If you cannot inherit from InheritedResources::Base you can call + # inherit_resource in your controller to have all the required modules and + # funcionality included. + # + def self.inherit_resources + InheritedResources::Base.inherit_resources(self) + initialize_resources_class_accessors! + create_resources_url_helpers! + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb new file mode 100644 index 0000000..5e15ebd --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/actions.rb @@ -0,0 +1,96 @@ +module InheritedResources + RESOURCES_ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:RESOURCES_ACTIONS) + + # Holds all default actions for InheritedResouces. + module Actions + + # GET /resources + def index(&block) + respond_to(:with => collection, &block) + end + alias :index! :index + + # GET /resources/1 + def show(&block) + respond_to(:with => resource, &block) + end + alias :show! :show + + # GET /resources/new + def new(&block) + respond_to(:with => build_resource, &block) + end + alias :new! :new + + # GET /resources/1/edit + def edit(&block) + respond_to(:with => resource, &block) + end + alias :edit! :edit + + # POST /resources + def create(&block) + object = build_resource + respond_block, redirect_block = select_block_by_arity(block) + + if object.save + set_flash_message!(:notice, '{{resource_name}} was successfully created.') + options = { :with => object, :status => :created, :location => (resource_url rescue nil) } + + respond_to_with_dual_blocks(true, respond_block, options) do |format| + format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) } + end + else + set_flash_message!(:error) + options = { :with => object.errors, :status => :unprocessable_entity } + + respond_to_with_dual_blocks(false, respond_block, options) do |format| + format.html { render :action => 'new' } + end + end + end + alias :create! :create + + # PUT /resources/1 + def update(&block) + object = resource + respond_block, redirect_block = select_block_by_arity(block) + + if object.update_attributes(params[resource_instance_name]) + set_flash_message!(:notice, '{{resource_name}} was successfully updated.') + + respond_to_with_dual_blocks(true, block) do |format| + format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) } + format.all { head :ok } + end + else + set_flash_message!(:error) + + options = { :with => object.errors, :status => :unprocessable_entity } + + respond_to_with_dual_blocks(false, block, options) do |format| + format.html { render :action => 'edit' } + end + end + end + alias :update! :update + + # DELETE /resources/1 + def destroy(&block) + resource.destroy + respond_block, redirect_block = select_block_by_arity(block) + + set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.') + + respond_to_with_dual_blocks(nil, respond_block) do |format| + format.html { redirect_to(redirect_block ? redirect_block.call : collection_url) } + format.all { head :ok } + end + end + alias :destroy! :destroy + + # Make aliases protected + protected :index!, :show!, :new!, :create!, :edit!, :update!, :destroy! + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb new file mode 100644 index 0000000..3b5ed58 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base.rb @@ -0,0 +1,39 @@ +module InheritedResources + # = Base + # + # This is the base class that holds all actions. If you see the code for each + # action, they are quite similar to Rails default scaffold. + # + # To change your base behavior, you can overwrite your actions and call super, + # call default class method, call <actions class method + # or overwrite some helpers in the base_helpers.rb file. + # + class Base < ::ApplicationController + unloadable + + # Overwrite inherit_resources to add specific InheritedResources behavior. + # + def self.inherit_resources(base) + base.class_eval do + include InheritedResources::Actions + include InheritedResources::BaseHelpers + extend InheritedResources::ClassMethods + extend InheritedResources::UrlHelpers + + helper_method :collection_url, :collection_path, :resource_url, :resource_path, + :new_resource_url, :new_resource_path, :edit_resource_url, :edit_resource_path, + :resource, :collection, :resource_class + + base.with_options :instance_writer => false do |c| + c.class_inheritable_accessor :resource_class + c.class_inheritable_array :parents_symbols + c.class_inheritable_hash :resources_configuration, :scopes_configuration + end + + protected :resource_class, :parents_symbols, :resources_configuration, :scopes_configuration + end + end + + inherit_resources(self) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb new file mode 100644 index 0000000..29de5be --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/base_helpers.rb @@ -0,0 +1,329 @@ +# Whenever base is required load the dumb responder since it's used inside actions. +require File.dirname(__FILE__) + '/dumb_responder.rb' + +module InheritedResources + # Base helpers for InheritedResource work. Some methods here can be overwriten + # and you will need to do that to customize your controllers from time to time. + # + module BaseHelpers + + protected + + # This is how the collection is loaded. + # + # You might want to overwrite this method if you want to add pagination + # for example. When you do that, don't forget to cache the result in an + # instance_variable: + # + # def collection + # @projects ||= end_of_association_chain.paginate(params[:page]).all + # end + # + def collection + get_collection_ivar || set_collection_ivar(end_of_association_chain.find(:all)) + end + + # This is how the resource is loaded. + # + # You might want to overwrite this method when you are using permalink. + # When you do that, don't forget to cache the result in an + # instance_variable: + # + # def resource + # @project ||= end_of_association_chain.find_by_permalink!(params[:id]) + # end + # + # You also might want to add the exclamation mark at the end of the method + # because it will raise a 404 if nothing can be found. Otherwise it will + # probably render a 500 error message. + # + def resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.find(params[:id])) + end + + # This method is responsable for building the object on :new and :create + # methods. If you overwrite it, don't forget to cache the result in an + # instance variable. + # + def build_resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, params[resource_instance_name])) + end + + # This class allows you to set a instance variable to begin your + # association chain. For example, usually your projects belongs to users + # and that means that they belong to the current logged in user. So you + # could do this: + # + # def begin_of_association_chain + # @current_user + # end + # + # So every time we instantiate a project, we will do: + # + # @current_user.projects.build(params[:project]) + # @current_user.projects.find(params[:id]) + # + # The variable set in begin_of_association_chain is not sent when building + # urls, so this is never going to happen when calling resource_url: + # + # project_url(@current_user, @project) + # + # If the user actually scopes the url, you should use belongs_to method + # and declare that projects belong to user. + # + def begin_of_association_chain + nil + end + + # Returns if the controller has a parent. When only base helpers are loaded, + # it's always false and should not be overwriten. + # + def parent? + false + end + + # Overwrite this method to provide other interpolation options when + # the flash message is going to be set. + # + # def interpolation_options + # { } + # end + + private + + # Fast accessor to resource_collection_name + # + def resource_collection_name #:nodoc: + self.resources_configuration[:self][:collection_name] + end + + # Fast accessor to resource_instance_name + # + def resource_instance_name #:nodoc: + self.resources_configuration[:self][:instance_name] + end + + # This methods gets your begin_of_association_chain, join it with your + # parents chain and returns the scoped association. + # + def end_of_association_chain #:nodoc: + chain = symbols_for_association_chain.inject(begin_of_association_chain) do |chain, symbol| + evaluate_parent(symbol, resources_configuration[symbol], chain) + end + + if chain + if method_for_association_chain + apply_scope_to(chain.send(method_for_association_chain)) + else + # This only happens when we specify begin_of_association_chain in + # a singletion controller without parents. In this case, the chain + # is exactly the begin_of_association_chain which is already an + # instance and then not scopable. + chain + end + else + apply_scope_to(resource_class) + end + end + + # Returns the appropriated method to build the resource. + # + def method_for_build #:nodoc: + (begin_of_association_chain || parent?) ? method_for_association_build : :new + end + + # Returns the name of the method used for build the resource in cases + # where we have a parent. This is overwritten in singleton scenarios. + # + def method_for_association_build + :build + end + + # Returns the name of the method to be called, before returning the end + # of the association chain. This is overwriten by singleton cases + # where no method for association chain is called. + # + def method_for_association_chain #:nodoc: + resource_collection_name + end + + # Get resource ivar based on the current resource controller. + # + def get_resource_ivar #:nodoc: + instance_variable_get("@#{resource_instance_name}") + end + + # Set resource ivar based on the current resource controller. + # + def set_resource_ivar(resource) #:nodoc: + instance_variable_set("@#{resource_instance_name}", resource) + end + + # Get collection ivar based on the current resource controller. + # + def get_collection_ivar #:nodoc: + instance_variable_get("@#{resource_collection_name}") + end + + # Set collection ivar based on the current resource controller. + # + def set_collection_ivar(collection) #:nodoc: + instance_variable_set("@#{resource_collection_name}", collection) + end + + # Helper to set flash messages. It's powered by I18n API. + # It checks for messages in the following order: + # + # flash.controller_name.action_name.status + # flash.actions.action_name.status + # + # If none is available, a default message is set. So, if you have + # a CarsController, create action, it will check for: + # + # flash.cars.create.status + # flash.actions.create.status + # + # The statuses can be :notice (when the object can be created, updated + # or destroyed with success) or :error (when the objecy cannot be created + # or updated). + # + # Those messages are interpolated by using the resource class human name. + # This means you can set: + # + # flash: + # actions: + # create: + # notice: "Hooray! {{resource_name}} was successfully created!" + # + # But sometimes, flash messages are not that simple. Going back + # to cars example, you might want to say the brand of the car when it's + # updated. Well, that's easy also: + # + # flash: + # cars: + # update: + # notice: "Hooray! You just tuned your {{car_brand}}!" + # + # Since :car_name is not available for interpolation by default, you have + # to overwrite interpolation_options. + # + # def interpolation_options + # { :car_brand => @car.brand } + # end + # + # Then you will finally have: + # + # 'Hooray! You just tuned your Aston Martin!' + # + # If your controller is namespaced, for example Admin::CarsController, + # the messages will be checked in the following order: + # + # flash.admin.cars.create.status + # flash.admin.actions.create.status + # flash.cars.create.status + # flash.actions.create.status + # + def set_flash_message!(status, default_message=nil) + return flash[status] = default_message unless defined?(::I18n) + + resource_name = if resource_class + if resource_class.respond_to?(:human_name) + resource_class.human_name + else + resource_class.name.humanize + end + else + "Resource" + end + + given_options = if self.respond_to?(:interpolation_options) + interpolation_options + else + {} + end + + options = { + :default => default_message || '', + :resource_name => resource_name + }.merge(given_options) + + defaults = [] + slices = controller_path.split('/') + + while slices.size > 0 + defaults << :"flash.#{slices.fill(controller_name, -1).join('.')}.#{action_name}.#{status}" + defaults << :"flash.#{slices.fill(:actions, -1).join('.')}.#{action_name}.#{status}" + slices.shift + end + + options[:default] = defaults.push(options[:default]) + options[:default].flatten! + + message = ::I18n.t options[:default].shift, options + flash[status] = message unless message.blank? + end + + # Used to allow to specify success and failure within just one block: + # + # def create + # create! do |success, failure| + # failure.html { redirect_to root_url } + # end + # end + # + def respond_to_with_dual_blocks(success, dual_block, options={}, &block) #:nodoc: + responder = ActionController::MimeResponds::Responder.new(self) + + if dual_block + if dual_block.arity == 2 + dumb_responder = InheritedResources::DumbResponder.new + if success + dual_block.call(responder, dumb_responder) + else + dual_block.call(dumb_responder, responder) + end + else + dual_block.call(responder) + end + + # Try to respond with the block given + responder.respond_except_any + end + + respond_to(options.merge!(:responder => responder, :prioritize => :html), &block) unless performed? + end + + # Hook to apply scopes. By default returns only the target_object given. + # It's extend by HasScopeHelpers. + # + def apply_scope_to(target_object) #:nodoc: + target_object + end + + # Symbols chain in base helpers return nothing. This is later overwriten + # by belongs_to and can be complex in polymorphic cases. + # + def symbols_for_association_chain #:nodoc: + [] + end + + # Holds InheritedResources block structure. It returns two blocks: the first + # is used in respond_to blocks and the second is the redirect_to url. + # + def select_block_by_arity(block) #:nodoc + if block + case block.arity + when 2, 1 + [block, nil] + when 0, -1 + [nil, block] + else + raise ScriptError, "InheritedResources does not know how to handle blocks with arity #{block.arity}" + end + else + [nil, nil] + end + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb new file mode 100644 index 0000000..56772ee --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/belongs_to_helpers.rb @@ -0,0 +1,89 @@ +module InheritedResources + + # = belongs_to + # + # Let's suppose that we have some tasks that belongs to projects. To specify + # this assoication in your controllers, just do: + # + # class TasksController < InheritedResources::Base + # belongs_to :project + # end + # + # belongs_to accepts several options to be able to configure the association. + # For example, if you want urls like /projects/:project_title/tasks, you + # can customize how InheritedResources find your projects: + # + # class TasksController < InheritedResources::Base + # belongs_to :project, :finder => :find_by_title!, :param => :project_title + # end + # + # It also accepts :route_name, :parent_class and :instance_name as options. + # Check the lib/inherited_resources/class_methods.rb for more. + # + # = nested_belongs_to + # + # Now, our Tasks get some Comments and you need to nest even deeper. Good + # practices says that you should never nest more than two resources, but sometimes + # you have to for security reasons. So this is an example of how you can do it: + # + # class CommentsController < InheritedResources::Base + # nested_belongs_to :project, :task + # end + # + # If you need to configure any of these belongs to, you can nested them using blocks: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project, :finder => :find_by_title!, :param => :project_title do + # belongs_to :task + # end + # end + # + # Warning: calling several belongs_to is the same as nesting them: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project + # belongs_to :task + # end + # + # In other words, the code above is the same as calling nested_belongs_to. + # + module BelongsToHelpers + + protected + + # Parent is always true when belongs_to is called. + # + def parent? + true + end + + private + + # Evaluate the parent given. This is used to nest parents in the + # association chain. + # + def evaluate_parent(parent_symbol, parent_config, chain = nil) #:nodoc: + instantiated_object = instance_variable_get("@#{parent_config[:instance_name]}") + return instantiated_object if instantiated_object + + parent = if chain + chain.send(parent_config[:collection_name]) + else + parent_config[:parent_class] + end + + parent = parent.send(parent_config[:finder], params[parent_config[:param]]) + + instance_variable_set("@#{parent_config[:instance_name]}", parent) + end + + # Maps parents_symbols to build association chain. In this case, it + # simply return the parent_symbols, however on polymorphic belongs to, + # it has some customization. + # + def symbols_for_association_chain #:nodoc: + parents_symbols + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb new file mode 100644 index 0000000..300581e --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/class_methods.rb @@ -0,0 +1,328 @@ +module InheritedResources + module ClassMethods + + protected + + # Used to overwrite the default assumptions InheritedResources do. Whenever + # this method is called, it should be on the top of your controller, since + # almost other methods depends on the values given to <>defaults. + # + # == Options + # + # * :resource_class - The resource class which by default is guessed + # by the controller name. Defaults to Project in + # ProjectsController. + # + # * :collection_name - The name of the collection instance variable which + # is set on the index action. Defaults to :projects in + # ProjectsController. + # + # * :instance_name - The name of the singular instance variable which + # is set on all actions besides index action. Defaults to + # :project in ProjectsController. + # + # * :route_collection_name - The name of the collection route. Defaults to :collection_name. + # + # * :route_instance_name - The name of the singular route. Defaults to :instance_name. + # + # * :route_prefix - The route prefix which is automically set in namespaced + # controllers. Default to :admin on Admin::ProjectsController. + # + # * :singleton - Tells if this controller is singleton or not. + # + def defaults(options) + raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash + + options.symbolize_keys! + options.assert_valid_keys(:resource_class, :collection_name, :instance_name, + :class_name, :route_prefix, :route_collection_name, + :route_instance_name, :singleton) + + self.resource_class = options.delete(:resource_class) if options.key?(:resource_class) + self.resource_class = options.delete(:class_name).constantize if options.key?(:class_name) + + acts_as_singleton! if options.delete(:singleton) + + config = self.resources_configuration[:self] + config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix) + + options.each do |key, value| + config[key] = value.to_sym + end + + create_resources_url_helpers! + end + + # Defines wich actions to keep from the inherited controller. + # Syntax is borrowed from resource_controller. + # + # actions :index, :show, :edit + # actions :all, :except => :index + # + def actions(*actions_to_keep) + raise ArgumentError, 'Wrong number of arguments. You have to provide which actions you want to keep.' if actions_to_keep.empty? + + options = actions_to_keep.extract_options! + actions_to_keep.map!{ |a| a.to_s } + + actions_to_remove = Array(options[:except]) + actions_to_remove.map!{ |a| a.to_s } + + actions_to_remove += RESOURCES_ACTIONS.map{|a| a.to_s } - actions_to_keep unless actions_to_keep.first == 'all' + actions_to_remove.uniq! + + (instance_methods & actions_to_remove).each do |action| + undef_method action, "#{action}!" + end + end + + # Detects params from url and apply as scopes to your classes. + # + # Your model: + # + # class Graduation < ActiveRecord::Base + # named_scope :featured, :conditions => { :featured => true } + # named_scope :by_degree, proc {|degree| { :conditions => { :degree => degree } } } + # end + # + # Your controller: + # + # class GraduationsController < InheritedResources::Base + # has_scope :featured, :boolean => true, :only => :index + # has_scope :by_degree, :only => :index + # end + # + # Then for each request: + # + # /graduations + # #=> acts like a normal request + # + # /graduations?featured=true + # #=> calls the named scope and bring featured graduations + # + # /graduations?featured=true&by_degree=phd + # #=> brings featured graduations with phd degree + # + # You can retrieve the current scopes in use with current_scopes + # method. In the last case, it would return: { :featured => "true", :by_degree => "phd" } + # + # == Options + # + # * :boolean - When set to true, call the scope only when the params is true or 1, + # and does not send the value as argument. + # + # * :only - In each actions the scope is applied. By default is :all. + # + # * :except - In each actions the scope is not applied. By default is :none. + # + # * :key - The key in the params hash expected to find the scope. + # Defaults to the scope name. + # + # * :default - Default value for the scope. Whenever supplied the scope + # is always called. This is useful to add easy pagination! + # + def has_scope(*scopes) + options = scopes.extract_options! + + options.symbolize_keys! + options.assert_valid_keys(:boolean, :key, :only, :except, :default) + + if self.scopes_configuration.empty? + include HasScopeHelpers + helper_method :current_scopes + end + + scopes.each do |scope| + self.scopes_configuration[scope] ||= {} + self.scopes_configuration[scope][:key] = options[:key] || scope + self.scopes_configuration[scope][:only] = Array(options[:only]) + self.scopes_configuration[scope][:except] = Array(options[:except]) + self.scopes_configuration[scope][:boolean] = options[:boolean] if options.key?(:boolean) + self.scopes_configuration[scope][:default] = options[:default] if options.key?(:default) + end + end + + # Defines that this controller belongs to another resource. + # + # belongs_to :projects + # + # == Options + # + # * :parent_class - Allows you to specify what is the parent class. + # + # belongs_to :project, :parent_class => AdminProject + # + # * :class_name - Also allows you to specify the parent class, but you should + # give a string. Added for ActiveRecord belongs to compatibility. + # + # * :instance_name - The instance variable name. By default is the name of the association. + # + # belongs_to :project, :instance_name => :my_project + # + # * :finder - Specifies which method should be called to instantiate the parent. + # + # belongs_to :project, :finder => :find_by_title! + # + # This will make your projects be instantiated as: + # + # Project.find_by_title!(params[:project_id]) + # + # Instead of: + # + # Project.find(params[:project_id]) + # + # * :param - Allows you to specify params key to retrieve the id. + # Default is :association_id, which in this case is :project_id. + # + # * :route_name - Allows you to specify what is the route name in your url + # helper. By default is association name. + # + # * :collection_name - Tell how to retrieve the next collection. Let's + # suppose you have Tasks which belongs to Projects + # which belongs to companies. This will do somewhere + # down the road: + # + # @company.projects + # + # But if you want to retrieve instead: + # + # @company.admin_projects + # + # You supply the collection name. + # + # * :polymorphic - Tell the association is polymorphic. + # + # * :singleton - Tell it's a singleton association. + # + # * :optional - Tell the association is optional (it's a special + # type of polymorphic association) + # + def belongs_to(*symbols, &block) + options = symbols.extract_options! + + options.symbolize_keys! + options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param, + :finder, :route_name, :collection_name, :singleton, + :polymorphic, :optional) + + optional = options.delete(:optional) + singleton = options.delete(:singleton) + polymorphic = options.delete(:polymorphic) + + include BelongsToHelpers if self.parents_symbols.empty? + + acts_as_singleton! if singleton + acts_as_polymorphic! if polymorphic || optional + + raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty? + raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty? + + symbols.each do |symbol| + symbol = symbol.to_sym + + if polymorphic || optional + self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic) + self.resources_configuration[:polymorphic][:symbols] << symbol + self.resources_configuration[:polymorphic][:optional] ||= optional + else + self.parents_symbols << symbol + end + + config = self.resources_configuration[symbol] = {} + config[:parent_class] = options.delete(:parent_class) + config[:parent_class] ||= (options.delete(:class_name) || symbol).to_s.classify.constantize rescue nil + config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym + config[:instance_name] = options.delete(:instance_name) || symbol + config[:param] = options.delete(:param) || :"#{symbol}_id" + config[:finder] = options.delete(:finder) || :find + config[:route_name] = options.delete(:route_name) || symbol + end + + if block_given? + class_eval(&block) + else + create_resources_url_helpers! + end + end + alias :nested_belongs_to :belongs_to + + # A quick method to declare polymorphic belongs to. + # + def polymorphic_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:polymorphic => true) + belongs_to(*symbols << options, &block) + end + + # A quick method to declare singleton belongs to. + # + def singleton_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:singleton => true) + belongs_to(*symbols << options, &block) + end + + # A quick method to declare optional belongs to. + # + def optional_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:optional => true) + belongs_to(*symbols << options, &block) + end + + private + + def acts_as_singleton! #:nodoc: + unless self.resources_configuration[:self][:singleton] + self.resources_configuration[:self][:singleton] = true + include SingletonHelpers + actions :all, :except => :index + end + end + + def acts_as_polymorphic! #:nodoc: + unless self.parents_symbols.include?(:polymorphic) + include PolymorphicHelpers + helper_method :parent, :parent_type, :parent_class, :parent? + end + end + + # Initialize resources class accessors and set their default values. + # + def initialize_resources_class_accessors! #:nodoc: + # Initialize resource class + self.resource_class = begin + self.controller_name.classify.constantize + rescue NameError + nil + end + + # Initialize resources configuration hash + self.resources_configuration ||= {} + config = self.resources_configuration[:self] = {} + config[:collection_name] = self.controller_name.to_sym + config[:instance_name] = self.controller_name.singularize.to_sym + + config[:route_collection_name] = config[:collection_name] + config[:route_instance_name] = config[:instance_name] + + # Deal with namespaced controllers + namespaces = self.controller_path.split('/')[0..-2] + config[:route_prefix] = namespaces.join('_') unless namespaces.empty? + + # Initialize polymorphic, singleton, scopes and belongs_to parameters + self.parents_symbols ||= [] + self.scopes_configuration ||= {} + self.resources_configuration[:polymorphic] ||= { :symbols => [], :optional => false } + end + + # Hook called on inheritance. + # + def inherited(base) #:nodoc: + super(base) + base.send :initialize_resources_class_accessors! + base.send :create_resources_url_helpers! + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb new file mode 100644 index 0000000..89104bf --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/dumb_responder.rb @@ -0,0 +1,20 @@ +module InheritedResources + # = Dumb Responder + # + # This responder discards all messages sent to him. + # + class DumbResponder + + instance_methods.each do |m| + undef_method m unless m =~ /^__/ + end + + # This is like a good husband, he will just listen everything that his wife + # says (which is a lot) without complaining. :) + # + def method_missing(*args) + nil + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb new file mode 100644 index 0000000..7de4c57 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/has_scope_helpers.rb @@ -0,0 +1,65 @@ +module InheritedResources + + # = has_scopes + # + # This module in included in your controller when has_scope is called for the + # first time. + # + module HasScopeHelpers + TRUE_VALUES = ["true", true, "1", 1] unless self.const_defined?(:TRUE_VALUES) + + protected + + # Overwrites apply to scope to implement default scope logic. + # + def apply_scope_to(target_object) #:nodoc: + @current_scopes ||= {} + + self.scopes_configuration.each do |scope, options| + next unless apply_scope_to_action?(options) + key = options[:key] + + if params.key?(key) + value, call_scope = params[key], true + elsif options.key?(:default) + value, call_scope = options[:default], true + value = value.call(self) if value.is_a?(Proc) + end + + if call_scope + @current_scopes[key] = value + + if options[:boolean] + target_object = target_object.send(scope) if TRUE_VALUES.include?(value) + else + target_object = target_object.send(scope, value) + end + end + end + + target_object + end + + # Given an options with :only and :except arrays, check if the scope + # can be performed in the current action. + # + def apply_scope_to_action?(options) #:nodoc: + if options[:only].empty? + if options[:except].empty? + true + else + !options[:except].include?(action_name.to_sym) + end + else + options[:only].include?(action_name.to_sym) + end + end + + # Returns the scopes used in this action. + # + def current_scopes + @current_scopes || {} + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb new file mode 100644 index 0000000..8a2f09b --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/polymorphic_helpers.rb @@ -0,0 +1,156 @@ +module InheritedResources + + # = polymorphic associations + # + # In some cases you have a resource that belongs to two different resources + # but not at the same time. For example, let's suppose you have File, Message + # and Task as resources and they are all commentable. + # + # Polymorphic associations allows you to create just one controller that will + # deal with each case. + # + # class Comment < InheritedResources::Base + # belongs_to :file, :message, :task, :polymorphic => true + # end + # + # Your routes should be something like: + # + # m.resources :files, :has_many => :comments #=> /files/13/comments + # m.resources :tasks, :has_many => :comments #=> /tasks/17/comments + # m.resources :messages, :has_many => :comments #=> /messages/11/comments + # + # When using polymorphic associations, you get some free helpers: + # + # parent? #=> true + # parent_type #=> :task + # parent_class #=> Task + # parent #=> @task + # + # This polymorphic controllers thing is a great idea by James Golick and he + # built it in resource_controller. Here is just a re-implementation. + # + # = optional polymorphic associations + # + # Let's take another break from ProjectsController. Let's suppose we are + # building a store, which sell products. + # + # On the website, we can show all products, but also products scoped to + # categories, brands, users. In this case case, the association is optional, and + # we deal with it in the following way: + # + # class ProductsController < InheritedResources::Base + # belongs_to :category, :brand, :user, :polymorphic => true, :optional => true + # end + # + # This will handle all those urls properly: + # + # /products/1 + # /categories/2/products/5 + # /brands/10/products/3 + # /user/13/products/11 + # + # = nested polymorphic associations + # + # You can have polymorphic associations with nested resources. Let's suppose + # that our File, Task and Message resources in the previous example belongs to + # a project. + # + # This way we can have: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project { + # belongs_to :file, :message, :task, :polymorphic => true + # } + # end + # + # Or: + # + # class CommentsController < InheritedResources::Base + # nested_belongs_to :project + # nested_belongs_to :file, :message, :task, :polymorphic => true + # end + # + # Choose the syntax that makes more sense to you. :) + # + # Finally your routes should be something like: + # + # map.resources :projects do |m| + # m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments + # m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments + # m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments + # end + # + # The helpers work in the same way as above. + # + module PolymorphicHelpers + + protected + + # Returns the parent type. A Comments class can have :task, :file, :note + # as parent types. + # + def parent_type + @parent_type + end + + def parent_class + parent.class if @parent_type + end + + # Returns the parent object. They are also available with the instance + # variable name: @task, @file, @note... + # + def parent + instance_variable_get("@#{@parent_type}") if @parent_type + end + + # If the polymorphic association is optional, we might not have a parent. + # + def parent? + if resources_configuration[:polymorphic][:optional] + parents_symbols.size > 1 || !@parent_type.nil? + else + true + end + end + + private + + # Maps parents_symbols to build association chain. + # + # If the parents_symbols find :polymorphic, it goes through the + # params keys to see which polymorphic parent matches the given params. + # + # When optional is given, it does not raise errors if the polymorphic + # params are missing. + # + def symbols_for_association_chain #:nodoc: + polymorphic_config = resources_configuration[:polymorphic] + + parents_symbols.map do |symbol| + if symbol == :polymorphic + params_keys = params.keys + + key = polymorphic_config[:symbols].find do |poly| + params_keys.include? resources_configuration[poly][:param].to_s + end + + if key.nil? + raise ScriptError, "Could not find param for polymorphic association. + The request params keys are #{params.keys.inspect} + and the polymorphic associations are + #{polymorphic_symbols.inspect}." unless polymorphic_config[:optional] + + nil + else + @parent_type = key.to_sym + end + else + symbol + end + end.compact + end + + end +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb new file mode 100644 index 0000000..aa380e0 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/respond_to.rb @@ -0,0 +1,339 @@ +module ActionController + # Provides an extension for Rails respond_to by expading MimeResponds::Responder + # and adding respond_to class method and respond_with instance method. + # + class Base + + protected + # Defines respond_to method to store formats that are rendered by default. + # + # Examples: + # + # respond_to :html, :xml, :json + # + # All actions on your controller will respond to :html, :xml and :json. + # But if you want to specify it based on your actions, you can use only and + # except: + # + # respond_to :html + # respond_to :xml, :json, :except => [ :edit ] + # + # The definition above explicits that all actions respond to :html. And all + # actions except :edit respond to :xml and :json. + # + # You can specify also only parameters: + # + # respond_to :rjs, :only => :create + # + # Which would be the same as: + # + # respond_to :rjs => :create + # + def self.respond_to(*formats) + options = formats.extract_options! + formats_hash = {} + + only_actions = Array(options.delete(:only)) + except_actions = Array(options.delete(:except)) + + only_actions.map!{ |a| a.to_sym } + except_actions.map!{ |a| a.to_sym } + + formats.each do |format| + formats_hash[format.to_sym] = {} + formats_hash[format.to_sym][:only] = only_actions unless only_actions.empty? + formats_hash[format.to_sym][:except] = except_actions unless except_actions.empty? + end + + options.each do |format, actions| + formats_hash[format.to_sym] = {} + next if actions == :all || actions == 'all' + + actions = Array(actions) + actions.map!{ |a| a.to_sym } + + formats_hash[format.to_sym][:only] = actions unless actions.empty? + end + + write_inheritable_hash(:formats_for_respond_to, formats_hash) + end + class_inheritable_reader :formats_for_respond_to + + # Method to clear all respond_to declared until the current controller. + # This is like freeing the controller from the inheritance chain. :) + # + def self.clear_respond_to! + formats = formats_for_respond_to + formats.each { |k,v| formats[k] = { :only => [] } } + write_inheritable_hash(:formats_for_respond_to, formats) + end + + # By default, responds only to :html + respond_to :html + + # If ApplicationController is already defined around here, we recriate + # the formats_for_respond_to hash. Since we respond only to :html by + # default, this is as easy as settings the :formats_for_respond_to key + # to {:html=>{}}. + # + if defined?(ApplicationController) + if inheritable = ApplicationController.instance_variable_get("@inheritable_attributes") + inheritable.merge!(:formats_for_respond_to => {:html => {}}) if inheritable + end + end + + # respond_with accepts an object and tries to render a view based in the + # controller and actions that called respond_with. If the view cannot be + # found, it will try to call :to_format in the object. + # + # class ProjectsController < ApplicationController + # respond_to :html, :xml + # + # def show + # @project = Project.find(:id) + # respond_with(@project) + # end + # end + # + # When the client request a xml, we will check first for projects/show.xml + # if it can't be found, we will call :to_xml in the object @project. If the + # object eventually doesn't respond to :to_xml it will render 404. + # + # If you want to overwrite the formats specified in the class, you can + # send your new formats using the options :to. + # + # def show + # @project = Project.find(:id) + # respond_with(@project, :to => :json) + # end + # + # That means that this action will ONLY reply to json requests. + # + # All other options sent will be forwarded to the render method. So you can + # do: + # + # def create + # # ... + # if @project.save + # respond_with(@project, :status => :ok, :location => @project) + # else + # respond_with(@project.errors, :status => :unprocessable_entity) + # end + # end + # + # respond_with does not accept blocks, if you want advanced configurations + # check respond_to method sending :with => @object as option. + # + # Returns true if anything is rendered. Returns false otherwise. + # + def respond_with(object, options = {}) + attempt_to_respond = false + + responder = options.delete(:responder) || Responder.new(self) + skip_not_acceptable = options.delete(:skip_not_acceptable) + skip_default_template = options.delete(:skip_default_template) + + mime_types = Array(options.delete(:to)) + mime_types.map!{ |mime| mime.to_sym } + + for priority in responder.mime_type_priority + if !skip_default_template && priority == Mime::ALL && respond_to_default_template?(responder) + render options.merge(:action => action_name) + return true + + elsif responder.action_respond_to_format?(priority.to_sym, mime_types) + attempt_to_respond = true + response.template.template_format = priority.to_sym + response.content_type = priority.to_s + + if template_exists? + render options.merge(:action => action_name) + return true + elsif object.respond_to?(:"to_#{priority.to_sym}") + render options.merge(:text => object.send(:"to_#{priority.to_sym}")) + return true + end + end + end + + # If we got here we could not render the object. But if attempted to + # render (this means, the format sent by the client was valid) we should + # render a 404. + # + # If we even didn't attempt to respond, we respond :not_acceptable + # unless is told otherwise. + # + if attempt_to_respond + render :text => '404 Not Found', :status => 404 + return true + elsif !skip_not_acceptable + head :not_acceptable + return false + end + + return false + end + + # Extends respond_to behaviour. + # + # You can now pass objects using the options :with. + # + # respond_to(:html, :xml, :rjs, :with => @project) + # + # If you pass an object and send any block, it's exactly the same as: + # + # respond_with(@project, :to => [:html, :xml, :rjs]) + # + # But the main difference of respond_to and respond_with is that the first + # allows further customizations: + # + # respond_to(:html, :with => @project) do |format| + # format.xml { render :xml => @project.errors } + # end + # + # It's the same as: + # + # 1. When responding to html, execute respond_with(@object). + # 2. When accessing a xml, execute the block given. + # + # Formats defined in blocks have precedence to formats sent as arguments. + # In other words, if you pass a format as argument and as block, the block + # will always be executed. + # + # And as in respond_with, all extra options sent will be forwarded to + # the render method: + # + # respond_to(:with => @projects.errors, :status => :unprocessable_entity) do |format| + # format.html { render :template => 'new' } + # end + # + # It also accepts an option called prioritize. It allows you to put a + # format as first, and then when Mime::ALL is sent, it will be the one + # used as response. + # + def respond_to(*types, &block) + options = types.extract_options! + + object = options.delete(:with) + responder = options.delete(:responder) || Responder.new(self) + prioritize = options.delete(:prioritize) + + if object.nil? + block ||= lambda { |responder| types.each { |type| responder.send(type) } } + block.call(responder) + responder.respond + return true + else + # Even if Mime::ALL is sent by the client, we do not respond_to it now. + # This is done using calling :respond_except_any instead of :respond. + # + if block_given? + block.call(responder) + return true if responder.respond_except_any + end + + # If the block includes the default template format, we don't render + # the default template (which uses the default_template_format). + options.merge!(:to => types, :responder => responder, :skip_not_acceptable => true, + :skip_default_template => responder.order.include?(default_template_format)) + + if respond_with(object, options) + return true + elsif block_given? + responder.prioritize(prioritize) if prioritize + return true if responder.respond_any + end + end + + head :not_acceptable + return false + end + + private + + unless ActionController::Base.private_instance_methods.include?('template_exists?') || + ActionController::Base.private_instance_methods.include?(:template_exists?) + + # Define template_exists? for Rails 2.3 + def template_exists? + default_template ? true : false + rescue ActionView::MissingTemplate + false + end + end + + # We respond to the default template if it's a valid format AND the template + # exists. + # + def respond_to_default_template?(responder) #:nodoc: + responder.action_respond_to_format?(default_template_format) && template_exists? + end + + end + + module MimeResponds #:nodoc: + class Responder #:nodoc: + + attr_reader :mime_type_priority, :order + + # Similar as respond but if we can't find a valid mime type, we do not + # send :not_acceptable message as head and it does not respond to + # Mime::ALL in any case. + # + def respond_except_any + for priority in @mime_type_priority + next if priority == Mime::ALL + + if @responses[priority] + @responses[priority].call + return true + end + end + + false + end + + # Respond to the first format given if Mime::ALL is included in the + # mime type priorites. This is the behaviour expected when the client + # sends "*/*" as mime type. + # + def respond_any + any = @responses[@order.include?(Mime::ALL) ? Mime::ALL : @order.first] + + if any && @mime_type_priority.include?(Mime::ALL) + any.call + return true + end + end + + # Receives an format and checks if the current action responds to + # the given format. If additional mimes are sent, only them are checked. + # + def action_respond_to_format?(format, additional_mimes = []) + if !additional_mimes.blank? + additional_mimes.include?(format.to_sym) + elsif formats = @controller.formats_for_respond_to[format.to_sym] + if formats[:only] + formats[:only].include?(@controller.action_name.to_sym) + elsif formats[:except] + !formats[:except].include?(@controller.action_name.to_sym) + else + true + end + else + false + end + end + + # Makes a given format the first in the @order array. + # + def prioritize(format) + if index = @order.index(format) + @order.unshift(@order.delete_at(index)) + end + @order + end + + end + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb new file mode 100644 index 0000000..9395517 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/singleton_helpers.rb @@ -0,0 +1,95 @@ +module InheritedResources + + # = singleton + # + # Singletons are usually used in associations which are related through has_one + # and belongs_to. You declare those associations like this: + # + # class ManagersController < InheritedResources::Base + # belongs_to :project, :singleton => true + # end + # + # But in some cases, like an AccountsController, you have a singleton object + # that is not necessarily associated with another: + # + # class AccountsController < InheritedResources::Base + # defaults :singleton => true + # end + # + # Besides that, you should overwrite the methods :resource and :build_resource + # to make it work properly: + # + # class AccountsController < InheritedResources::Base + # defaults :singleton => true + # + # protected + # def resource + # @current_user.account + # end + # + # def build_resource(attributes = {}) + # Account.new(attributes) + # end + # end + # + # When you have a singleton controller, the action index is removed. + # + module SingletonHelpers + + protected + + # Singleton methods does not deal with collections. + # + def collection + nil + end + + # Overwrites how singleton deals with resource. + # + # If you are going to overwrite it, you should notice that the + # end_of_association_chain here is not the same as in default belongs_to. + # + # class TasksController < InheritedResources::Base + # belongs_to :project + # end + # + # In this case, the association chain would be: + # + # Project.find(params[:project_id]).tasks + # + # So you would just have to call find(:all) at the end of association + # chain. And this is what happened. + # + # In singleton controllers: + # + # class ManagersController < InheritedResources::Base + # belongs_to :project, :singleton => true + # end + # + # The association chain will be: + # + # Project.find(params[:project_id]) + # + # So we have to call manager on it, not find. + # + def resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(resource_instance_name)) + end + + private + + # Returns the appropriated method to build the resource. + # + def method_for_association_build #:nodoc: + :"build_#{resource_instance_name}" + end + + # Sets the method_for_association_chain to nil. See resource + # above for more information. + # + def method_for_association_chain #:nodoc: + nil + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb new file mode 100644 index 0000000..e11e2c5 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/lib/inherited_resources/url_helpers.rb @@ -0,0 +1,173 @@ +module InheritedResources + # = URLHelpers + # + # When you use InheritedResources it creates some UrlHelpers for you. + # And they handle everything for you. + # + # # /posts/1/comments + # resource_url # => /posts/1/comments/#{@comment.to_param} + # resource_url(comment) # => /posts/1/comments/#{comment.to_param} + # new_resource_url # => /posts/1/comments/new + # edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit + # collection_url # => /posts/1/comments + # + # # /projects/1/tasks + # resource_url # => /products/1/tasks/#{@task.to_param} + # resource_url(task) # => /products/1/tasks/#{task.to_param} + # new_resource_url # => /products/1/tasks/new + # edit_resource_url # => /products/1/tasks/#{@task.to_param}/edit + # collection_url # => /products/1/tasks + # + # # /users + # resource_url # => /users/#{@user.to_param} + # resource_url(user) # => /users/#{user.to_param} + # new_resource_url # => /users/new + # edit_resource_url # => /users/#{@user.to_param}/edit + # collection_url # => /users + # + # The nice thing is that those urls are not guessed during runtime. They are + # all created when you inherit. + # + module UrlHelpers + + # This method hard code url helpers in the class. + # + # We are doing this because is cheaper than guessing them when our action + # is being processed (and even more cheaper when we are using nested + # resources). + # + # When we are using polymorphic associations, those helpers rely on + # polymorphic_url Rails helper. + # + def create_resources_url_helpers! + resource_segments, resource_ivars = [], [] + resource_config = self.resources_configuration[:self] + + singleton = self.resources_configuration[:self][:singleton] + polymorphic = self.parents_symbols.include?(:polymorphic) + + # Add route_prefix if any. + unless resource_config[:route_prefix].blank? + if polymorphic + resource_ivars << resource_config[:route_prefix].to_s.inspect + else + resource_segments << resource_config[:route_prefix] + end + end + + # Deal with belongs_to associations and polymorphic associations. + # Remember that we don't have to build the segments in polymorphic cases, + # because the url will be polymorphic_url. + # + self.parents_symbols.each do |symbol| + if symbol == :polymorphic + resource_ivars << :parent + else + config = self.resources_configuration[symbol] + resource_segments << config[:route_name] + resource_ivars << :"@#{config[:instance_name]}" + end + end + + collection_ivars = resource_ivars.dup + collection_segments = resource_segments.dup + + # This is the default route configuration, later we have to deal with + # exception from polymorphic and singleton cases. + # + collection_segments << resource_config[:route_collection_name] + resource_segments << resource_config[:route_instance_name] + resource_ivars << :"@#{resource_config[:instance_name]}" + + # In singleton cases, we do not send the current element instance variable + # because the id is not in the URL. For example, we should call: + # + # project_manager_url(@project) + # + # Instead of: + # + # project_manager_url(@project, @manager) + # + # Another exception in singleton cases is that collection url does not + # exist. In such cases, we create the parent collection url. So in the + # manager case above, the collection url will be: + # + # project_url(@project) + # + # If the singleton does not have a parent, it will default to root_url. + # + # Finally, polymorphic cases we have to give hints to the polymorphic url + # builder. This works by attaching new ivars as symbols or records. + # + if singleton + collection_segments.pop + resource_ivars.pop + + if polymorphic + resource_ivars << resource_config[:instance_name].inspect + new_ivars = resource_ivars + end + elsif polymorphic + collection_ivars << '(@_resource_class_new ||= resource_class.new)' + end + + generate_url_and_path_helpers nil, :collection, collection_segments, collection_ivars + generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars + generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars + generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars + end + + def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc: + ivars = resource_ivars.dup + + singleton = self.resources_configuration[:self][:singleton] + polymorphic = self.parents_symbols.include?(:polymorphic) + + # If it's not a singleton, ivars are not empty, not a collection or + # not a "new" named route, we can pass a resource as argument. + # + unless singleton || ivars.empty? || name == :collection || prefix == :new + ivars.push "(given_args.first || #{ivars.pop})" + end + + # In collection in polymorphic cases, allow an argument to be given as a + # replacemente for the parent. + # + if name == :collection && polymorphic + index = ivars.index(:parent) + ivars.insert index, "(given_args.first || parent)" + ivars.delete(:parent) + end + + # When polymorphic is true, the segments must be replace by :polymorphic + # and ivars should be gathered into an array, which is compacted when + # optional. + # + if polymorphic + segments = :polymorphic + ivars = "[#{ivars.join(', ')}]" + ivars << '.compact' if self.resources_configuration[:polymorphic][:optional] + else + segments = resource_segments.empty? ? 'root' : resource_segments.join('_') + ivars = ivars.join(', ') + end + + prefix = prefix ? "#{prefix}_" : '' + ivars << (ivars.empty? ? 'given_options' : ', given_options') + + class_eval <<-URL_HELPERS, __FILE__, __LINE__ + protected + def #{prefix}#{name}_path(*given_args) + given_options = given_args.extract_options! + #{prefix}#{segments}_path(#{ivars}) + end + + def #{prefix}#{name}_url(*given_args) + given_options = given_args.extract_options! + #{prefix}#{segments}_url(#{ivars}) + end + URL_HELPERS + end + + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb new file mode 100644 index 0000000..6f5b000 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/aliases_test.rb @@ -0,0 +1,134 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Student; + def self.human_name; 'Student'; end +end + +class StudentsController < ApplicationController + inherit_resources + + def edit + edit! do |format| + format.xml { render :text => 'Render XML' } + end + end + + def new + @something = 'magical' + new! + end + + def create + create! do |success, failure| + success.html { render :text => "I won't redirect!" } + failure.xml { render :text => "I shouldn't be rendered" } + end + end + + def update + update! do |success, failure| + success.html { redirect_to(resource_url) } + failure.html { render :text => "I won't render!" } + end + end + + def destroy + destroy! do |format| + format.html { render :text => "Destroyed!" } + end + end + +end + +class AliasesTest < ActionController::TestCase + tests StudentsController + + def test_assignments_before_calling_alias + Student.stubs(:new).returns(mock_student) + get :new + assert_response :success + assert_equal 'magical', assigns(:something) + end + + def test_controller_should_render_new + Student.stubs(:new).returns(mock_student) + get :new + assert_response :success + assert_equal 'New HTML', @response.body.strip + end + + def test_expose_the_resquested_user_on_edit + Student.expects(:find).with('42').returns(mock_student) + get :edit, :id => '42' + assert_equal mock_student, assigns(:student) + assert_response :success + end + + def test_controller_should_render_edit + Student.stubs(:find).returns(mock_student) + get :edit + assert_response :success + assert_equal 'Edit HTML', @response.body.strip + end + + def test_render_xml_when_it_is_given_as_a_block + @request.accept = 'application/xml' + Student.stubs(:find).returns(mock_student) + get :edit + assert_response :success + assert_equal 'Render XML', @response.body + end + + def test_is_not_redirected_on_create_with_success_if_success_block_is_given + Student.stubs(:new).returns(mock_student(:save => true)) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "I won't redirect!", @response.body + end + + def test_dumb_responder_quietly_receives_everything_on_failure + @request.accept = 'text/html' + Student.stubs(:new).returns(mock_student(:save => false, :errors => [])) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end + + def test_html_is_the_default_when_only_xml_is_overwriten + @request.accept = '*/*' + Student.stubs(:new).returns(mock_student(:save => false, :errors => [])) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end + + def test_wont_render_edit_template_on_update_with_failure_if_failure_block_is_given + Student.stubs(:find).returns(mock_student(:update_attributes => false, :errors => [])) + put :update + assert_response :success + assert_equal "I won't render!", @response.body + end + + def test_dumb_responder_quietly_receives_everything_on_success + Student.stubs(:find).returns(mock_student(:update_attributes => true)) + @controller.stubs(:resource_url).returns('http://test.host/') + put :update, :id => '42', :student => {:these => 'params'} + assert_equal mock_student, assigns(:student) + end + + def test_block_is_called_when_student_is_destroyed + Student.stubs(:find).returns(mock_student(:destroy => true)) + delete :destroy + assert_response :success + assert_equal "Destroyed!", @response.body + end + + protected + def mock_student(stubs={}) + @mock_student ||= mock(stubs) + end +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb new file mode 100644 index 0000000..cdc3a76 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_helpers_test.rb @@ -0,0 +1,70 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Pet + def self.human_name; 'Pet'; end +end + +class PetsController < InheritedResources::Base + attr_accessor :current_user + + def edit + @pet = 'new pet' + edit! + end + + protected + def collection + @pets ||= end_of_association_chain.all + end + + def begin_of_association_chain + @current_user + end +end + +class AssociationChainBaseHelpersTest < ActionController::TestCase + tests PetsController + + def setup + @controller.current_user = mock() + end + + def test_begin_of_association_chain_is_called_on_index + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:all).returns(mock_pet) + get :index + assert_response :success + assert 'Index HTML', @response.body.strip + end + + def test_begin_of_association_chain_is_called_on_new + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:build).returns(mock_pet) + get :new + assert_response :success + assert 'New HTML', @response.body.strip + end + + def test_begin_of_association_chain_is_called_on_show + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:find).with('47').returns(mock_pet) + get :show, :id => '47' + assert_response :success + assert 'Show HTML', @response.body.strip + end + + def test_instance_variable_should_not_be_set_if_already_defined + @controller.current_user.expects(:pets).never + Pet.expects(:find).never + get :edit + assert_response :success + assert_equal 'new pet', assigns(:pet) + end + + protected + def mock_pet(stubs={}) + @mock_pet ||= mock(stubs) + end + +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb new file mode 100644 index 0000000..5b4b69c --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/base_test.rb @@ -0,0 +1,219 @@ +require File.dirname(__FILE__) + '/test_helper' + +class User + def self.human_name; 'User'; end +end + +class AccountsController < InheritedResources::Base +end + +class UsersController < AccountsController + respond_to :html, :xml +end + +module UserTestHelper + def setup + @controller = UsersController.new + @controller.request = @request = ActionController::TestRequest.new + @controller.response = @response = ActionController::TestResponse.new + end + + protected + def mock_user(stubs={}) + @mock_user ||= mock(stubs) + end +end + +class IndexActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_all_users_as_instance_variable + User.expects(:find).with(:all).returns([mock_user]) + get :index + assert_equal [mock_user], assigns(:users) + end + + def test_controller_should_render_index + User.stubs(:find).returns([mock_user]) + get :index + assert_response :success + assert_equal 'Index HTML', @response.body.strip + end + + def test_render_all_users_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:find).with(:all).returns(mock_user) + mock_user.expects(:to_xml).returns('Generated XML') + get :index + assert_response :success + assert_equal 'Generated XML', @response.body + end +end + +class ShowActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_the_resquested_user + User.expects(:find).with('42').returns(mock_user) + get :show, :id => '42' + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_show + User.stubs(:find).returns(mock_user) + get :show + assert_response :success + assert_equal 'Show HTML', @response.body.strip + end + + def test_render_exposed_user_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:to_xml).returns("Generated XML") + get :show, :id => '42' + assert_response :success + assert_equal 'Generated XML', @response.body + end +end + +class NewActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_a_new_user + User.expects(:new).returns(mock_user) + get :new + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_new + User.stubs(:new).returns(mock_user) + get :new + assert_response :success + assert_equal 'New HTML', @response.body.strip + end + + def test_render_exposed_a_new_user_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:new).returns(mock_user) + mock_user.expects(:to_xml).returns("Generated XML") + get :new + assert_response :success + assert_equal 'Generated XML', @response.body + end +end + +class EditActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_the_resquested_user + User.expects(:find).with('42').returns(mock_user) + get :edit, :id => '42' + assert_response :success + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_edit + User.stubs(:find).returns(mock_user) + get :edit + assert_response :success + assert_equal 'Edit HTML', @response.body.strip + end +end + +class CreateActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_a_newly_create_user_when_saved_with_success + User.expects(:new).with({'these' => 'params'}).returns(mock_user(:save => true)) + post :create, :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + end + + def test_redirect_to_the_created_user + User.stubs(:new).returns(mock_user(:save => true)) + @controller.expects(:resource_url).returns('http://test.host/').times(2) + post :create + assert_redirected_to 'http://test.host/' + end + + def test_show_flash_message_when_success + User.stubs(:new).returns(mock_user(:save => true)) + post :create + assert_equal flash[:notice], 'User was successfully created.' + end + + def test_render_new_template_when_user_cannot_be_saved + User.stubs(:new).returns(mock_user(:save => false, :errors => [])) + post :create + assert_response :success + assert_template :new + end + + def test_dont_show_flash_message_when_user_cannot_be_saved + User.stubs(:new).returns(mock_user(:save => false, :errors => [])) + post :create + assert flash.empty? + end +end + +class UpdateActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_update_the_requested_object + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + end + + def test_redirect_to_the_created_user + User.stubs(:find).returns(mock_user(:update_attributes => true)) + @controller.expects(:resource_url).returns('http://test.host/') + put :update + assert_redirected_to 'http://test.host/' + end + + def test_show_flash_message_when_success + User.stubs(:find).returns(mock_user(:update_attributes => true)) + put :update + assert_equal flash[:notice], 'User was successfully updated.' + end + + def test_render_edit_template_when_user_cannot_be_saved + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => [])) + put :update + assert_response :success + assert_template :edit + end + + def test_dont_show_flash_message_when_user_cannot_be_saved + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => [])) + put :update + assert flash.empty? + end +end + +class DestroyActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_the_resquested_user_is_destroyed + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:destroy) + delete :destroy, :id => '42' + assert_equal mock_user, assigns(:user) + end + + def test_show_flash_message + User.stubs(:find).returns(mock_user(:destroy => true)) + delete :destroy + assert_equal flash[:notice], 'User was successfully destroyed.' + end + + def test_redirects_to_users_list + User.stubs(:find).returns(mock_user(:destroy => true)) + @controller.expects(:collection_url).returns('http://test.host/') + delete :destroy + assert_redirected_to 'http://test.host/' + end +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb new file mode 100644 index 0000000..8b78cc1 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/belongs_to_test.rb @@ -0,0 +1,87 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Post +end + +class Comment + def self.human_name; 'Comment'; end +end + +class CommentsController < InheritedResources::Base + belongs_to :post +end + +class BelongsToTest < ActionController::TestCase + tests CommentsController + + def setup + Post.expects(:find).with('37').returns(mock_post) + mock_post.expects(:comments).returns(Comment) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_comments_as_instance_variable_on_index + Comment.expects(:find).with(:all).returns([mock_comment]) + get :index, :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal [mock_comment], assigns(:comments) + end + + def test_expose_the_resquested_comment_on_show + Comment.expects(:find).with('42').returns(mock_comment) + get :show, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_expose_a_new_comment_on_new + Comment.expects(:build).returns(mock_comment) + get :new, :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_expose_the_resquested_comment_on_edit + Comment.expects(:find).with('42').returns(mock_comment) + get :edit, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_expose_a_newly_create_comment_on_create + Comment.expects(:build).with({'these' => 'params'}).returns(mock_comment(:save => true)) + post :create, :post_id => '37', :comment => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_update_the_requested_object_on_update + Comment.expects(:find).with('42').returns(mock_comment) + mock_comment.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :post_id => '37', :comment => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_the_resquested_comment_is_destroyed_on_destroy + Comment.expects(:find).with('42').returns(mock_comment) + mock_comment.expects(:destroy) + delete :destroy, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + protected + + def mock_post(stubs={}) + @mock_post ||= mock(stubs) + end + + def mock_comment(stubs={}) + @mock_comment ||= mock(stubs) + end + +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb new file mode 100644 index 0000000..e13b208 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/class_methods_test.rb @@ -0,0 +1,137 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Book; end +class Folder; end + +class BooksController < InheritedResources::Base + actions :index, :show +end + +class ReadersController < InheritedResources::Base + actions :all, :except => [ :edit, :update ] +end + +class FoldersController < InheritedResources::Base +end + +class Dean + def self.human_name; 'Dean'; end +end + +class SchoolsController < InheritedResources::Base + has_scope :by_city + has_scope :featured, :boolean => true, :only => :index, :key => :by_featured +end + +class DeansController < InheritedResources::Base + belongs_to :school +end + + +class ActionsClassMethodTest < ActiveSupport::TestCase + def test_actions_are_undefined + action_methods = BooksController.send(:action_methods) + assert_equal 2, action_methods.size + + ['index', 'show'].each do |action| + assert action_methods.include? action + end + end + + def test_actions_are_undefined_when_except_option_is_given + action_methods = ReadersController.send(:action_methods) + assert_equal 5, action_methods.size + + ['index', 'new', 'show', 'create', 'destroy'].each do |action| + assert action_methods.include? action + end + end +end + + +class DefaultsClassMethodTest < ActiveSupport::TestCase + def test_resource_class_is_set_to_nil_when_resource_model_cannot_be_found + assert_nil ReadersController.send(:resource_class) + end + + def test_defaults_are_set + assert Folder, FoldersController.send(:resource_class) + assert :folder, FoldersController.send(:resources_configuration)[:self][:instance_name] + assert :folders, FoldersController.send(:resources_configuration)[:self][:collection_name] + end + + def test_defaults_can_be_overwriten + BooksController.send(:defaults, :resource_class => String, :instance_name => 'string', :collection_name => 'strings') + + assert String, BooksController.send(:resource_class) + assert :string, BooksController.send(:resources_configuration)[:self][:instance_name] + assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name] + + BooksController.send(:defaults, :class_name => 'Fixnum', :instance_name => :fixnum, :collection_name => :fixnums) + + assert String, BooksController.send(:resource_class) + assert :string, BooksController.send(:resources_configuration)[:self][:instance_name] + assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name] + end + + def test_defaults_raises_invalid_key + assert_raise ArgumentError do + BooksController.send(:defaults, :boom => String) + end + end + + def test_url_helpers_are_recreated_when_defaults_change + BooksController.expects(:create_resources_url_helpers!).returns(true).once + BooksController.send(:defaults, :instance_name => 'string', :collection_name => 'strings') + end +end + +class BelongsToErrorsTest < ActiveSupport::TestCase + def test_belongs_to_raise_errors_with_invalid_arguments + assert_raise ArgumentError do + DeansController.send(:belongs_to) + end + + assert_raise ArgumentError do + DeansController.send(:belongs_to, :nice, :invalid_key => '') + end + end + + def test_belongs_to_raises_an_error_when_multiple_associations_are_given_with_options + assert_raise ArgumentError do + DeansController.send(:belongs_to, :arguments, :with_options, :parent_class => Professor) + end + end + + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_block + DeansController.expects(:create_resources_url_helpers!).returns(true).once + DeansController.send(:belongs_to, :school) do + belongs_to :association + end + ensure + DeansController.send(:parents_symbols=, [:school]) + end + + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_multiple_blocks + DeansController.expects(:create_resources_url_helpers!).returns(true).once + DeansController.send(:belongs_to, :school) do + belongs_to :association do + belongs_to :nested + end + end + ensure + DeansController.send(:parents_symbols=, [:school]) + end +end + +class HasScopeClassMethods < ActiveSupport::TestCase + def test_scope_configuration_is_stored_as_hashes + config = SchoolsController.send(:scopes_configuration) + + assert config.key?(:by_city) + assert config.key?(:featured) + + assert_equal config[:by_city], { :key => :by_city, :only => [], :except => [] } + assert_equal config[:featured], { :key => :by_featured, :only => [ :index ], :except => [], :boolean => true } + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb new file mode 100644 index 0000000..800ce36 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/customized_belongs_to_test.rb @@ -0,0 +1,76 @@ +require File.dirname(__FILE__) + '/test_helper' + +class GreatSchool +end + +class Professor + def self.human_name; 'Professor'; end +end + +class ProfessorsController < InheritedResources::Base + belongs_to :school, :parent_class => GreatSchool, :instance_name => :great_school, + :finder => :find_by_title!, :param => :school_title +end + +class CustomizedBelongsToTest < ActionController::TestCase + tests ProfessorsController + + def setup + GreatSchool.expects(:find_by_title!).with('nice').returns(mock_school(:professors => Professor)) + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_index + Professor.stubs(:find).returns([mock_professor]) + get :index, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_show + Professor.stubs(:find).returns(mock_professor) + get :show, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_new + Professor.stubs(:build).returns(mock_professor) + get :new, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_edit + Professor.stubs(:find).returns(mock_professor) + get :edit, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_create + Professor.stubs(:build).returns(mock_professor(:save => true)) + post :create, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_update + Professor.stubs(:find).returns(mock_professor(:update_attributes => true)) + put :update, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_resquested_school_with_chosen_instance_variable_on_destroy + Professor.stubs(:find).returns(mock_professor(:destroy => true)) + delete :destroy, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + protected + + def mock_school(stubs={}) + @mock_school ||= mock(stubs) + end + + def mock_professor(stubs={}) + @mock_professor ||= mock(stubs) + end +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb new file mode 100644 index 0000000..ce0f9eb --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/defaults_test.rb @@ -0,0 +1,70 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Malarz + def self.human_name; 'Painter'; end +end + +class PaintersController < InheritedResources::Base + defaults :instance_name => 'malarz', :collection_name => 'malarze', + :resource_class => Malarz, :route_prefix => nil +end + +class DefaultsTest < ActionController::TestCase + tests PaintersController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_painters_as_instance_variable + Malarz.expects(:find).with(:all).returns([mock_painter]) + get :index + assert_equal [mock_painter], assigns(:malarze) + end + + def test_expose_the_resquested_painter_on_show + Malarz.expects(:find).with('42').returns(mock_painter) + get :show, :id => '42' + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_a_new_painter + Malarz.expects(:new).returns(mock_painter) + get :new + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_the_resquested_painter_on_edit + Malarz.expects(:find).with('42').returns(mock_painter) + get :edit, :id => '42' + assert_response :success + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_a_newly_create_painter_when_saved_with_success + Malarz.expects(:new).with({'these' => 'params'}).returns(mock_painter(:save => true)) + post :create, :malarz => {:these => 'params'} + assert_equal mock_painter, assigns(:malarz) + end + + def test_update_the_requested_object + Malarz.expects(:find).with('42').returns(mock_painter) + mock_painter.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :malarz => {:these => 'params'} + assert_equal mock_painter, assigns(:malarz) + end + + def test_the_resquested_painter_is_destroyed + Malarz.expects(:find).with('42').returns(mock_painter) + mock_painter.expects(:destroy) + delete :destroy, :id => '42' + assert_equal mock_painter, assigns(:malarz) + end + + protected + def mock_painter(stubs={}) + @mock_painter ||= mock(stubs) + end +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb new file mode 100644 index 0000000..788900f --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/flash_test.rb @@ -0,0 +1,83 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Address + def self.human_name; 'Address'; end +end + +class AddressesController < InheritedResources::Base + protected + def interpolation_options + { :reference => 'Ocean Avenue' } + end +end + +module Admin; end +class Admin::AddressesController < InheritedResources::Base + protected + def interpolation_options + { :reference => 'Ocean Avenue' } + end +end + +class FlashBaseHelpersTest < ActionController::TestCase + tests AddressesController + + def setup + @request.accept = 'application/xml' + end + + def test_success_flash_message_on_create_with_yml + Address.stubs(:new).returns(mock_address(:save => true)) + @controller.stubs(:address_url) + post :create + assert_equal 'You created a new address close to Ocean Avenue.', flash[:notice] + end + + def test_success_flash_message_on_create_with_namespaced_controller + @controller = Admin::AddressesController.new + Address.stubs(:new).returns(mock_address(:save => true)) + @controller.stubs(:address_url) + post :create + assert_equal 'Admin, you created a new address close to Ocean Avenue.', flash[:notice] + end + + def test_failure_flash_message_on_create_with_namespaced_controller_actions + @controller = Admin::AddressesController.new + Address.stubs(:new).returns(mock_address(:save => false)) + @controller.stubs(:address_url) + post :create + assert_equal 'Admin error message.', flash[:error] + end + + def test_inherited_success_flash_message_on_update_on_namespaced_controllers + @controller = Admin::AddressesController.new + Address.stubs(:find).returns(mock_address(:update_attributes => true)) + put :update + assert_response :success + assert_equal 'Nice! Address was updated with success!', flash[:notice] + end + + def test_success_flash_message_on_update + Address.stubs(:find).returns(mock_address(:update_attributes => true)) + put :update + assert_response :success + assert_equal 'Nice! Address was updated with success!', flash[:notice] + end + + def test_failure_flash_message_on_update + Address.stubs(:find).returns(mock_address(:update_attributes => false, :errors => [])) + put :update + assert_equal 'Oh no! We could not update your address!', flash[:error] + end + + def test_success_flash_message_on_destroy + Address.stubs(:find).returns(mock_address(:destroy => true)) + delete :destroy + assert_equal 'Address was successfully destroyed.', flash[:notice] + end + + protected + def mock_address(stubs={}) + @mock_address ||= mock(stubs) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb new file mode 100644 index 0000000..16c48d6 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/has_scope_test.rb @@ -0,0 +1,112 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Tree + def self.human_name; 'Tree'; end +end + +class TreesController < InheritedResources::Base + has_scope :color + has_scope :only_tall, :boolean => true, :only => :index + has_scope :shadown_range, :default => 10, :except => [ :index, :show, :destroy, :new ] + has_scope :root_type, :key => :root + has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new +end + +class HasScopeTest < ActionController::TestCase + tests TreesController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_boolean_scope_is_called_when_boolean_param_is_true + Tree.expects(:only_tall).with().returns(Tree).in_sequence + Tree.expects(:find).with(:all).returns([mock_tree]).in_sequence + get :index, :only_tall => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :only_tall => 'true' }, assigns(:current_scopes)) + end + + def test_boolean_scope_is_called_when_boolean_param_is_false + Tree.expects(:only_tall).never + Tree.expects(:find).with(:all).returns([mock_tree]) + get :index, :only_tall => 'false' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :only_tall => 'false' }, assigns(:current_scopes)) + end + + def test_scope_is_called_only_on_index + Tree.expects(:only_tall).never + Tree.expects(:find).with('42').returns(mock_tree) + get :show, :only_tall => 'true', :id => '42' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ }, assigns(:current_scopes)) + end + + def test_scope_is_called_except_on_index + Tree.expects(:shadown_range).with().never + Tree.expects(:find).with(:all).returns([mock_tree]) + get :index, :shadown_range => 20 + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ }, assigns(:current_scopes)) + end + + def test_scope_is_called_with_arguments + Tree.expects(:color).with('blue').returns(Tree).in_sequence + Tree.expects(:find).with(:all).returns([mock_tree]).in_sequence + get :index, :color => 'blue' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :color => 'blue' }, assigns(:current_scopes)) + end + + def test_multiple_scopes_are_called + Tree.expects(:only_tall).with().returns(Tree) + Tree.expects(:color).with('blue').returns(Tree) + Tree.expects(:find).with(:all).returns([mock_tree]) + get :index, :color => 'blue', :only_tall => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :color => 'blue', :only_tall => 'true' }, assigns(:current_scopes)) + end + + def test_scope_is_called_with_default_value + Tree.expects(:shadown_range).with(10).returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :edit, :id => '42' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :shadown_range => 10 }, assigns(:current_scopes)) + end + + def test_default_scope_value_can_be_overwritten + Tree.expects(:shadown_range).with('20').returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :edit, :id => '42', :shadown_range => '20' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :shadown_range => '20' }, assigns(:current_scopes)) + end + + def test_scope_with_different_key + Tree.expects(:root_type).with('outside').returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :show, :id => '42', :root => 'outside' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :root => 'outside' }, assigns(:current_scopes)) + end + + def test_scope_with_default_value_as_proc + session[:height] = 100 + Tree.expects(:calculate_height).with(100).returns(Tree).in_sequence + Tree.expects(:new).returns(mock_tree).in_sequence + get :new + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :calculate_height => 100 }, assigns(:current_scopes)) + end + + protected + + def mock_tree(stubs={}) + @mock_tree ||= mock(stubs) + end + +end + diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb new file mode 100644 index 0000000..afe2c17 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/nested_belongs_to_test.rb @@ -0,0 +1,108 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Country +end + +class State +end + +class City + def self.human_name; 'City'; end +end + +class CitiesController < InheritedResources::Base + belongs_to :country, :state +end + +class NestedBelongsToTest < ActionController::TestCase + tests CitiesController + + def setup + Country.expects(:find).with('13').returns(mock_country) + mock_country.expects(:states).returns(State) + State.expects(:find).with('37').returns(mock_state) + mock_state.expects(:cities).returns(City) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_assigns_country_and_state_and_city_on_create + City.expects(:find).with(:all).returns([mock_city]) + get :index, :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal [mock_city], assigns(:cities) + end + + def test_assigns_country_and_state_and_city_on_show + City.expects(:find).with('42').returns(mock_city) + get :show, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_new + City.expects(:build).returns(mock_city) + get :new, :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_edit + City.expects(:find).with('42').returns(mock_city) + get :edit, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_create + City.expects(:build).with({'these' => 'params'}).returns(mock_city) + mock_city.expects(:save).returns(true) + post :create, :state_id => '37', :country_id => '13', :city => {:these => 'params'} + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_update + City.expects(:find).with('42').returns(mock_city) + mock_city.expects(:update_attributes).returns(true) + put :update, :id => '42', :state_id => '37', :country_id => '13', :city => {:these => 'params'} + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_destroy + City.expects(:find).with('42').returns(mock_city) + mock_city.expects(:destroy) + delete :destroy, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + protected + def mock_country(stubs={}) + @mock_country ||= mock(stubs) + end + + def mock_state(stubs={}) + @mock_state ||= mock(stubs) + end + + def mock_city(stubs={}) + @mock_city ||= mock(stubs) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb new file mode 100644 index 0000000..b29fe6e --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/optional_belongs_to_test.rb @@ -0,0 +1,164 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Brands; end +class Category; end + +class Product + def self.human_name; 'Product'; end +end + +class ProductsController < InheritedResources::Base + belongs_to :brand, :category, :polymorphic => true, :optional => true +end + +class OptionalTest < ActionController::TestCase + tests ProductsController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_products_as_instance_variable_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with(:all).returns([mock_product]) + get :index, :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal [mock_product], assigns(:products) + end + + def test_expose_all_products_as_instance_variable_without_category + Product.expects(:find).with(:all).returns([mock_product]) + get :index + assert_equal nil, assigns(:category) + assert_equal [mock_product], assigns(:products) + end + + def test_expose_the_resquested_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + get :show, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_resquested_product_without_category + Product.expects(:find).with('42').returns(mock_product) + get :show, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_new_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:build).returns(mock_product) + get :new, :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_new_product_without_category + Product.expects(:new).returns(mock_product) + get :new + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_resquested_product_for_edition_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + get :edit, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_resquested_product_for_edition_without_category + Product.expects(:find).with('42').returns(mock_product) + get :edit, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_newly_create_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:build).with({'these' => 'params'}).returns(mock_product(:save => true)) + post :create, :category_id => '37', :product => {:these => 'params'} + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_newly_create_product_without_category + Product.expects(:new).with({'these' => 'params'}).returns(mock_product(:save => true)) + post :create, :product => {:these => 'params'} + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_update_the_requested_object_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) + + put :update, :id => '42', :category_id => '37', :product => {:these => 'params'} + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_update_the_requested_object_without_category + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) + + put :update, :id => '42', :product => {:these => 'params'} + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_the_resquested_product_is_destroyed_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:destroy) + @controller.expects(:collection_url).returns('/') + + delete :destroy, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_the_resquested_product_is_destroyed_without_category + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:destroy) + @controller.expects(:collection_url).returns('/') + + delete :destroy, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_polymorphic_helpers + Product.expects(:find).with(:all).returns([mock_product]) + get :index + + assert !@controller.send(:parent?) + assert_equal nil, assigns(:parent_type) + assert_equal nil, @controller.send(:parent_type) + assert_equal nil, @controller.send(:parent_class) + assert_equal nil, assigns(:category) + assert_equal nil, @controller.send(:parent) + end + + protected + def mock_category(stubs={}) + @mock_category ||= mock(stubs) + end + + def mock_product(stubs={}) + @mock_product ||= mock(stubs) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb new file mode 100644 index 0000000..446d85b --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/polymorphic_test.rb @@ -0,0 +1,186 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Factory; end +class Company; end + +class Employee + def self.human_name; 'Employee'; end +end + +class EmployeesController < InheritedResources::Base + belongs_to :factory, :company, :polymorphic => true +end + +class PolymorphicFactoriesTest < ActionController::TestCase + tests EmployeesController + + def setup + Factory.expects(:find).with('37').returns(mock_factory) + mock_factory.expects(:employees).returns(Employee) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_employees_as_instance_variable_on_index + Employee.expects(:find).with(:all).returns([mock_employee]) + get :index, :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal [mock_employee], assigns(:employees) + end + + def test_expose_the_resquested_employee_on_show + Employee.expects(:find).with('42').returns(mock_employee) + get :show, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_a_new_employee_on_new + Employee.expects(:build).returns(mock_employee) + get :new, :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_the_resquested_employee_on_edit + Employee.expects(:find).with('42').returns(mock_employee) + get :edit, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + assert_response :success + end + + def test_expose_a_newly_create_employee_on_create + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) + post :create, :factory_id => '37', :employee => {:these => 'params'} + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_update_the_requested_object_on_update + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :factory_id => '37', :employee => {:these => 'params'} + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_the_resquested_employee_is_destroyed_on_destroy + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:destroy) + delete :destroy, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_polymorphic_helpers + mock_factory.stubs(:class).returns(Factory) + + Employee.expects(:find).with(:all).returns([mock_employee]) + get :index, :factory_id => '37' + + assert @controller.send(:parent?) + assert_equal :factory, assigns(:parent_type) + assert_equal :factory, @controller.send(:parent_type) + assert_equal Factory, @controller.send(:parent_class) + assert_equal mock_factory, assigns(:factory) + assert_equal mock_factory, @controller.send(:parent) + end + + protected + def mock_factory(stubs={}) + @mock_factory ||= mock(stubs) + end + + def mock_employee(stubs={}) + @mock_employee ||= mock(stubs) + end +end + +class PolymorphicCompanyTest < ActionController::TestCase + tests EmployeesController + + def setup + Company.expects(:find).with('37').returns(mock_company) + mock_company.expects(:employees).returns(Employee) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_employees_as_instance_variable_on_index + Employee.expects(:find).with(:all).returns([mock_employee]) + get :index, :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal [mock_employee], assigns(:employees) + end + + def test_expose_the_resquested_employee_on_show + Employee.expects(:find).with('42').returns(mock_employee) + get :show, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_a_new_employee_on_new + Employee.expects(:build).returns(mock_employee) + get :new, :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_the_resquested_employee_on_edit + Employee.expects(:find).with('42').returns(mock_employee) + get :edit, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + assert_response :success + end + + def test_expose_a_newly_create_employee_on_create + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) + post :create, :company_id => '37', :employee => {:these => 'params'} + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_update_the_requested_object_on_update + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :company_id => '37', :employee => {:these => 'params'} + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_the_resquested_employee_is_destroyed_on_destroy + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:destroy) + delete :destroy, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_polymorphic_helpers + mock_company.stubs(:class).returns(Company) + + Employee.expects(:find).with(:all).returns([mock_employee]) + get :index, :company_id => '37' + + assert @controller.send(:parent?) + assert_equal :company, assigns(:parent_type) + assert_equal :company, @controller.send(:parent_type) + assert_equal Company, @controller.send(:parent_class) + assert_equal mock_company, assigns(:company) + assert_equal mock_company, @controller.send(:parent) + end + + protected + def mock_company(stubs={}) + @mock_company ||= mock(stubs) + end + + def mock_employee(stubs={}) + @mock_employee ||= mock(stubs) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb new file mode 100644 index 0000000..648e00d --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/redirect_to_test.rb @@ -0,0 +1,77 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Machine; + def self.human_name; 'Machine'; end +end + +class MachinesController < InheritedResources::Base + def create + create!{ complex_url(:create, true, true) } + end + + def update + update!{ complex_url(:update, false, false) } + end + + def destroy + destroy!{ complex_url(:destroy, true, false) } + end + + protected + def complex_url(name, arg2, arg3) + 'http://test.host/' + name.to_s + end +end + +class RedirectToWithBlockTest < ActionController::TestCase + tests MachinesController + + def test_redirect_to_the_given_url_on_create + Machine.stubs(:new).returns(mock_machine(:save => true)) + @controller.expects(:resource_url).times(0) + post :create + assert_redirected_to 'http://test.host/create' + end + + def test_redirect_to_the_given_url_on_update + Machine.stubs(:find).returns(mock_machine(:update_attributes => true)) + @controller.expects(:resource_url).times(0) + put :update + assert_redirected_to 'http://test.host/update' + end + + def test_redirect_to_the_given_url_on_destroy + Machine.stubs(:find).returns(mock_machine(:destroy => true)) + @controller.expects(:collection_url).times(0) + delete :destroy + assert_redirected_to 'http://test.host/destroy' + end + + protected + def mock_machine(stubs={}) + @mock_machine ||= mock(stubs) + end +end + + +# Use this to test blocks with multiple arity in the future. +class SuperMachinesController < InheritedResources::Base + defaults :resource_class => Machine + + def create + create! do |arg1, arg2, arg3| + # nothing + end + end +end + +class RedirectToArityTest < ActionController::TestCase + tests SuperMachinesController + + def test_redirect_to_the_given_url_on_create + Machine.stubs(:new).returns(:anything) + assert_raise ScriptError, /arity/ do + post :create + end + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb new file mode 100644 index 0000000..939a4e7 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/respond_to_test.rb @@ -0,0 +1,314 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Project + def to_html + 'Generated HTML' + end + + def to_xml + 'Generated XML' + end + + [:to_json, :to_rss, :to_rjs].each do |method| + undef_method method if respond_to? method + end +end + +class ProjectsController < ActionController::Base + # Inherited respond_to definition is: + # respond_to :html + respond_to :html + respond_to :xml, :except => :edit + respond_to :rjs => :edit + respond_to :rss, :only => 'index' + respond_to :json, :except => :index + respond_to :csv, :except => :index + + def index + respond_with(Project.new) + end + + def respond_with_options + respond_with(Project.new, :to => [:xml, :json], :location => 'http://test.host/') + end + + def skip_not_acceptable + respond_with(Project.new, :skip_not_acceptable => true) + render :text => 'Will not raise double render error.' + end + + def respond_to_with_resource + respond_to(:with => Project.new) + end + + def respond_to_with_resource_and_blocks + respond_to(:with => Project.new) do |format| + format.json { render :text => 'Render JSON' } + format.rss { render :text => 'Render RSS' } + end + end + + # If the user request Mime::ALL and we have a template called action.html.erb, + # the html template should be rendered *unless* html is specified inside the + # block. This tests exactly this case. + # + def respond_to_skip_default_template + respond_to(:with => Project.new) do |format| + format.html { render :text => 'Render HTML' } + end + end +end + +class SuperProjectsController < ProjectsController +end + +class RespondToUnitTest < ActionController::TestCase + tests ProjectsController + + def setup + @formats = @controller.formats_for_respond_to + @responder = ActionController::MimeResponds::Responder.new(@controller) + end + + def test_respond_to_class_method_without_options + assert_nil @formats[:html][:only] + assert_nil @formats[:html][:except] + end + + def test_respond_to_class_method_inheritance + assert_nil @formats[:xml][:only] + assert_equal [:edit], @formats[:xml][:except] + end + + def test_respond_to_class_method_with_implicit_only + assert_equal [:edit], @formats[:rjs][:only] + assert_nil @formats[:rjs][:except] + end + + def test_respond_to_class_method_with_explicit_only + assert_equal [:index], @formats[:rss][:only] + assert_nil @formats[:rss][:except] + end + + def test_respond_to_class_method_with_explicit_except + assert_nil @formats[:json][:only] + assert_equal [:index], @formats[:json][:except] + end + + def test_action_respond_to_format + @controller.action_name = 'index' + assert @responder.action_respond_to_format?('html') # defined + assert @responder.action_respond_to_format?('xml') # inherited + assert @responder.action_respond_to_format?('rss') # explicit only + assert !@responder.action_respond_to_format?('json') # exception + + @controller.action_name = 'edit' + assert !@responder.action_respond_to_format?('xml') # inherited + assert @responder.action_respond_to_format?('rjs') # implicit only + assert @responder.action_respond_to_format?('json') # exception + end + + def test_action_respond_to_format_with_additional_mimes + assert @responder.action_respond_to_format?('html', [:xml, :html, :json]) + assert !@responder.action_respond_to_format?('html', [:xml, :rss, :json]) + + @controller.action_name = 'index' + assert @responder.action_respond_to_format?('html', []) + assert !@responder.action_respond_to_format?('json', []) + end + + def test_clear_respond_to + @controller = SuperProjectsController.new + @controller.request = ActionController::TestRequest.new + + @controller.action_name = 'index' + @responder = ActionController::MimeResponds::Responder.new(@controller) + + # Those responses are inherited from ProjectsController + assert @responder.action_respond_to_format?('html') # defined + assert @responder.action_respond_to_format?('xml') # inherited + assert @responder.action_respond_to_format?('rss') # explicit only + + # Let's clear respond_to definitions + SuperProjectsController.send(:clear_respond_to!) + + assert !@responder.action_respond_to_format?('html') + assert !@responder.action_respond_to_format?('xml') + assert !@responder.action_respond_to_format?('rss') + end + + def test_respond_except_any_does_not_respond_to_mime_all + prepare_responder_to_respond! + + @responder.respond_except_any + assert !@performed + + @responder.respond + assert @performed + end + + def test_respond_any_responds_to_mime_all + prepare_responder_to_respond! + + @responder.respond_any + assert @performed + end + + def test_respond_any_responds_only_to_all + prepare_responder_to_respond!('text/html') + + @responder.respond_any + assert !@performed + end + + def test_responder_prioritize + prepare_responder_to_respond! + assert_equal [Mime::HTML, Mime::XML], @responder.order + + @responder.prioritize(:xml) + assert_equal [Mime::XML, Mime::HTML], @responder.order + + @responder.prioritize(:js) + assert_equal [Mime::XML, Mime::HTML], @responder.order + end + + protected + def prepare_responder_to_respond!(content_type='*/*') + @controller.request = @request = ActionController::TestRequest.new + @controller.response = @response = ActionController::TestResponse.new + + @request.accept = content_type + @responder = ActionController::MimeResponds::Responder.new(@controller) + @performed = false + + # Mock template + template = mock() + @response.stubs(:template).returns(template) + template.stubs(:template_format=).returns(true) + + respond_to_declaration = proc { |format| + format.html { @performed = true } + format.xml { } + } + + respond_to_declaration.call(@responder) + end +end + +class RespondToFunctionalTest < ActionController::TestCase + tests ProjectsController + + def test_respond_with_layout_rendering + @request.accept = 'text/html' + get :index + assert_equal 'Index HTML', @response.body.strip + end + + def test_respond_with_calls_to_format_on_resource + @request.accept = 'application/xml' + get :index + assert_equal 'Generated XML', @response.body.strip + end + + def test_respond_with_inherits_format + @request.accept = 'application/xml' + get :index + assert_equal 'Generated XML', @response.body.strip + end + + def test_respond_with_renders_status_not_acceptable_if_mime_type_is_not_registered + @request.accept = 'text/csv' + get :index + assert_equal '406 Not Acceptable', @response.status + end + + def test_respond_with_renders_not_found_when_mime_type_is_valid_but_could_not_render + @request.accept = 'application/rss+xml' + get :index + assert_equal '404 Not Found', @response.status + end + + def test_respond_to_all + @request.accept = '*/*' + get :index + assert_equal 'Index HTML', @response.body.strip + end + + def test_default_template_is_not_rendered_if_template_format_is_not_accepted + @controller.stubs(:default_template_format).returns(:json) + @request.accept = '*/*' + get :index + assert_equal '406 Not Acceptable', @response.status + end + + def test_respond_with_sets_content_type_properly + @request.accept = 'text/html' + get :index + assert_equal 'text/html', @response.content_type + assert_equal :html, @response.template.template_format + + @request.accept = 'application/xml' + get :index + assert_equal 'application/xml', @response.content_type + assert_equal :xml, @response.template.template_format + end + + def test_respond_with_when_to_is_given_as_option + @request.accept = 'text/html' + get :respond_with_options + assert_equal '406 Not Acceptable', @response.status + + @request.accept = 'application/xml' + get :respond_with_options + assert_equal 'Generated XML', @response.body.strip + end + + def test_respond_with_forwads_extra_options_to_render + @request.accept = 'application/xml' + get :respond_with_options + assert_equal 'Generated XML', @response.body.strip + assert_equal 'http://test.host/', @response.headers['Location'] + end + + def test_respond_with_skips_head_when_skip_not_acceptable_is_given + @request.accept = 'application/rss+xml' + get :skip_not_acceptable + assert_equal 'Will not raise double render error.', @response.body.strip + end + + def test_respond_to_when_a_resource_is_given_as_option + @request.accept = 'text/html' + get :respond_to_with_resource + assert_equal 'RespondTo HTML', @response.body.strip + + @request.accept = 'application/xml' + get :respond_to_with_resource + assert_equal 'Generated XML', @response.body.strip + + @request.accept = 'application/json' + get :respond_to_with_resource + assert_equal '404 Not Found', @response.status + + @request.accept = 'application/rss+xml' + get :respond_to_with_resource + assert_equal '406 Not Acceptable', @response.status + end + + def test_respond_to_overwrite_class_method_definition + @request.accept = 'application/rss+xml' + get :respond_to_with_resource_and_blocks + assert_equal 'Render RSS', @response.body.strip + end + + def test_respond_to_fallback_to_first_block_when_mime_type_is_all + @request.accept = '*/*' + get :respond_to_with_resource_and_blocks + assert_equal 'Render JSON', @response.body.strip + end + + def test_respond_to_skip_default_template_when_it_is_in_block + @request.accept = '*/*' + get :respond_to_skip_default_template + assert_equal 'Render HTML', @response.body.strip + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb new file mode 100644 index 0000000..239ddf2 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/singleton_test.rb @@ -0,0 +1,83 @@ +require File.dirname(__FILE__) + '/test_helper' + +# This test file is instead to test the how controller flow and actions +# using a belongs_to association. This is done using mocks a la rspec. +# +class Store +end + +class Manager + def self.human_name; 'Manager'; end +end + +class ManagersController < InheritedResources::Base + belongs_to :store, :singleton => true +end + +class SingletonTest < ActionController::TestCase + tests ManagersController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_the_resquested_manager_on_show + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + get :show, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_expose_a_new_manager_on_new + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:build_manager).returns(mock_manager) + get :new, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_expose_the_resquested_manager_on_edit + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + get :edit, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + assert_response :success + end + + def test_expose_a_newly_create_manager_on_create + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:build_manager).with({'these' => 'params'}).returns(mock_manager(:save => true)) + post :create, :store_id => '37', :manager => {:these => 'params'} + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_update_the_requested_object_on_update + Store.expects(:find).with('37').returns(mock_store(:manager => mock_manager)) + mock_manager.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :store_id => '37', :manager => {:these => 'params'} + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_the_resquested_manager_is_destroyed_on_destroy + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + mock_manager.expects(:destroy) + delete :destroy, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + protected + def mock_store(stubs={}) + @mock_store ||= mock(stubs) + end + + def mock_manager(stubs={}) + @mock_manager ||= mock(stubs) + end +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb new file mode 100644 index 0000000..13474db --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/test_helper.rb @@ -0,0 +1,27 @@ +require 'test/unit' +require 'rubygems' +require 'ruby-debug' +require 'mocha' + +ENV["RAILS_ENV"] = "test" +RAILS_ROOT = "anywhere" + +require 'active_support' +require 'action_controller' +require 'action_controller/test_case' +require 'action_controller/test_process' + +I18n.load_path << File.join(File.dirname(__FILE__), 'locales', 'en.yml') +I18n.reload! + +class ApplicationController < ActionController::Base; end + +# Add IR to load path and load the main file +ActiveSupport::Dependencies.load_paths << File.expand_path(File.dirname(__FILE__) + '/../lib') +require_dependency 'inherited_resources' + +ActionController::Base.view_paths = File.join(File.dirname(__FILE__), 'views') + +ActionController::Routing::Routes.draw do |map| + map.connect ':controller/:action/:id' +end diff --git a/vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb b/vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb new file mode 100644 index 0000000..4a67124 --- /dev/null +++ b/vendor/gems/josevalim-inherited_resources-0.8.5/test/url_helpers_test.rb @@ -0,0 +1,471 @@ +require File.dirname(__FILE__) + '/test_helper' + +class Universe; end +class UniversesController < InheritedResources::Base + defaults :singleton => true, :route_instance_name => 'universum' +end + +class House; end +class HousesController < InheritedResources::Base +end + +class Backpack; end +module Admin; end +class Admin::BackpacksController < InheritedResources::Base + defaults :route_collection_name => 'tour_backpacks' +end + +class Table; end +class TablesController < InheritedResources::Base + belongs_to :house +end + +class RoomsController < InheritedResources::Base + belongs_to :house, :route_name => 'big_house' +end + +class ChairsController < InheritedResources::Base + belongs_to :house do + belongs_to :table + end +end + +class OwnersController < InheritedResources::Base + singleton_belongs_to :house +end + +class Bed; end +class BedsController < InheritedResources::Base + optional_belongs_to :house, :building +end + +class Desk; end +module Admin + class DesksController < InheritedResources::Base + optional_belongs_to :house + end +end + +class Dish; end +class DishesController < InheritedResources::Base + belongs_to :house do + polymorphic_belongs_to :table, :kitchen + end +end + +class Center; end +class CentersController < InheritedResources::Base + acts_as_singleton! + + belongs_to :house do + belongs_to :table, :kitchen, :polymorphic => true + end +end + +# Create a TestHelper module with some helpers +class UrlHelpersTest < ActiveSupport::TestCase + + def test_url_helpers_on_simple_inherited_resource + controller = HousesController.new + controller.instance_variable_set('@house', :house) + + [:url, :path].each do |path_or_url| + controller.expects("houses_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("house_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("house_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("house_#{path_or_url}").with(:arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_simple_inherited_namespaced_resource + controller = Admin::BackpacksController.new + controller.instance_variable_set('@backpack', :backpack) + + assert_equal 'admin', controller.class.resources_configuration[:self][:route_prefix] + + [:url, :path].each do |path_or_url| + controller.expects("admin_tour_backpacks_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("admin_backpack_#{path_or_url}").with(:backpack, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_admin_backpack_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_admin_backpack_#{path_or_url}").with(:backpack, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("admin_backpack_#{path_or_url}").with(:arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_simple_inherited_singleton_resource + controller = UniversesController.new + controller.instance_variable_set('@universe', :universe) + + [:url, :path].each do |path_or_url| + controller.expects("root_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("universum_#{path_or_url}").with({}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_universum_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_universum_#{path_or_url}").with({}).once + controller.send("edit_resource_#{path_or_url}") + + # With options + # Also tests that argument sent are not used + controller.expects("universum_#{path_or_url}").with(:page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_belongs_to + controller = TablesController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@table', :table) + + [:url, :path].each do |path_or_url| + controller.expects("house_tables_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("house_table_#{path_or_url}").with(:house, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("edit_house_table_#{path_or_url}").with(:house, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + # With options + controller.expects("house_table_#{path_or_url}").with(:house, :arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_not_default_belongs_to + controller = RoomsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@room', :room) + + [:url, :path].each do |path_or_url| + controller.expects("big_house_rooms_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("big_house_room_#{path_or_url}").with(:house, :room, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_big_house_room_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :room, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With args + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + # With options + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_nested_belongs_to + controller = ChairsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@table', :table) + controller.instance_variable_set('@chair', :chair) + + [:url, :path].each do |path_or_url| + controller.expects("house_table_chairs_#{path_or_url}").with(:house, :table, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_chair_#{path_or_url}").with(:house, :table, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With args + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, :page => 1).once + controller.send("edit_resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_singletons_with_belongs_to + controller = OwnersController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@owner', :owner) + + [:url, :path].each do |path_or_url| + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_owner_#{path_or_url}").with(:house, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_owner_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_owner_#{path_or_url}").with(:house, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With options + # Also tests that argument sent are not used + controller.expects("house_owner_#{path_or_url}").with(:house, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_polymorphic_belongs_to + house = House.new + bed = Bed.new + + new_bed = Bed.new + Bed.stubs(:new).returns(new_bed) + new_bed.stubs(:new_record?).returns(true) + + controller = BedsController.new + controller.instance_variable_set('@parent_type', :house) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@bed', bed) + + [:url, :path].each do |path_or_url| + controller.expects("house_beds_#{path_or_url}").with(house).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_bed_#{path_or_url}").with(house, bed).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_bed_#{path_or_url}").with(house).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_bed_#{path_or_url}").with(house, bed).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + controller.expects("house_bed_url").with(house, bed, :page => 1).once + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([:arg, new_bed], {}).once + controller.send("collection_url", :arg) + + controller.expects("polymorphic_url").with([house, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([house, :arg], {}).once + controller.send("edit_resource_url", :arg) + end + + def test_url_helpers_on_namespaced_polymorphic_belongs_to + house = House.new + desk = Desk.new + + new_desk = Desk.new + Desk.stubs(:new).returns(new_desk) + new_desk.stubs(:new_record?).returns(true) + + controller = Admin::DesksController.new + controller.instance_variable_set('@parent_type', :house) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@desk', desk) + + [:url, :path].each do |path_or_url| + controller.expects("admin_house_desks_#{path_or_url}").with(house).once + controller.send("collection_#{path_or_url}") + + controller.expects("admin_house_desk_#{path_or_url}").with(house, desk).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_admin_house_desk_#{path_or_url}").with(house).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_admin_house_desk_#{path_or_url}").with(house, desk).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + controller.expects("admin_house_desk_url").with(house, desk, :page => 1).once + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with(['admin', :arg, new_desk], {}).once + controller.send("collection_url", :arg) + + controller.expects("polymorphic_url").with(['admin', house, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with(['admin', house, :arg], {}).once + controller.send("edit_resource_url", :arg) + end + + def test_url_helpers_on_nested_polymorphic_belongs_to + house = House.new + table = Table.new + dish = Dish.new + + new_dish = Dish.new + Dish.stubs(:new).returns(new_dish) + new_dish.stubs(:new_record?).returns(true) + + controller = DishesController.new + controller.instance_variable_set('@parent_type', :table) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@table', table) + controller.instance_variable_set('@dish', dish) + + [:url, :path].each do |path_or_url| + controller.expects("house_table_dishes_#{path_or_url}").with(house, table).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_dish_#{path_or_url}").with(house, table, dish).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_dish_#{path_or_url}").with(house, table).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_dish_#{path_or_url}").with(house, table, dish).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + controller.expects("house_table_dish_url").with(house, table, dish, :page => 1).once + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([house, table, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([house, table, :arg], {}).once + controller.send("edit_resource_url", :arg) + end + + def test_url_helpers_on_singleton_nested_polymorphic_belongs_to + # This must not be usefull in singleton controllers... + # Center.new + house = House.new + table = Table.new + + controller = CentersController.new + controller.instance_variable_set('@parent_type', :table) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@table', table) + + # This must not be useful in singleton controllers... + # controller.instance_variable_set('@center', :center) + + [:url, :path].each do |path_or_url| + controller.expects("house_table_#{path_or_url}").with(house, table).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_center_#{path_or_url}").with(house, table).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_center_#{path_or_url}").with(house, table).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_center_#{path_or_url}").with(house, table).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + controller.expects("house_table_center_url").with(house, table, :page => 1) + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([house, table, :center], {}).once + controller.send("resource_url", :arg) + end + + def test_url_helpers_on_optional_polymorphic_belongs_to + bed = Bed.new + new_bed = Bed.new + Bed.stubs(:new).returns(new_bed) + new_bed.stubs(:new_record?).returns(true) + + controller = BedsController.new + controller.instance_variable_set('@parent_type', nil) + controller.instance_variable_set('@bed', bed) + + [:url, :path].each do |path_or_url| + controller.expects("beds_#{path_or_url}").with().once + controller.send("collection_#{path_or_url}") + + controller.expects("bed_#{path_or_url}").with(bed).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_bed_#{path_or_url}").with().once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_bed_#{path_or_url}").with(bed).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + controller.expects("bed_url").with(bed, :page => 1).once + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([:arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([:arg], {}).once + controller.send("edit_resource_url", :arg) + end + +end -- libgit2 0.21.2