From 5d4f1e0639c0c9cd3491fef8438a116508ad6e1d Mon Sep 17 00:00:00 2001 From: hukl Date: Thu, 19 Feb 2009 22:42:09 +0100 Subject: added this route filter from sven fuchs to make this simplified route magic possible. hope i don't foot myself in the shot with it. --- config/routes.rb | 4 +- vendor/plugins/routing-filter/.gitignore | 1 + vendor/plugins/routing-filter/MIT-LICENSE | 20 ++ vendor/plugins/routing-filter/README.markdown | 123 +++++++++ vendor/plugins/routing-filter/init.rb | 1 + .../plugins/routing-filter/lib/routing_filter.rb | 69 +++++ .../routing-filter/lib/routing_filter/base.rb | 15 ++ .../routing-filter/lib/routing_filter/locale.rb | 34 +++ .../lib/routing_filter/pagination.rb | 19 ++ .../plugins/routing-filter/spec/generation_spec.rb | 283 +++++++++++++++++++++ .../routing-filter/spec/recognition_spec.rb | 76 ++++++ .../routing-filter/spec/routing_filter_spec.rb | 70 +++++ vendor/plugins/routing-filter/spec/spec.opts | 4 + vendor/plugins/routing-filter/spec/spec_helper.rb | 49 ++++ 14 files changed, 767 insertions(+), 1 deletion(-) create mode 100644 vendor/plugins/routing-filter/.gitignore create mode 100644 vendor/plugins/routing-filter/MIT-LICENSE create mode 100644 vendor/plugins/routing-filter/README.markdown create mode 100644 vendor/plugins/routing-filter/init.rb create mode 100644 vendor/plugins/routing-filter/lib/routing_filter.rb create mode 100644 vendor/plugins/routing-filter/lib/routing_filter/base.rb create mode 100644 vendor/plugins/routing-filter/lib/routing_filter/locale.rb create mode 100644 vendor/plugins/routing-filter/lib/routing_filter/pagination.rb create mode 100644 vendor/plugins/routing-filter/spec/generation_spec.rb create mode 100644 vendor/plugins/routing-filter/spec/recognition_spec.rb create mode 100644 vendor/plugins/routing-filter/spec/routing_filter_spec.rb create mode 100644 vendor/plugins/routing-filter/spec/spec.opts create mode 100644 vendor/plugins/routing-filter/spec/spec_helper.rb diff --git a/config/routes.rb b/config/routes.rb index 2ab68c2..b258fb2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ ActionController::Routing::Routes.draw do |map| + map.filter :locale + map.resources :pages map.resources :nodes @@ -7,7 +9,7 @@ ActionController::Routing::Routes.draw do |map| map.resources :users map.resource :session - map.connect ':language/*page_path', + map.connect '/*page_path', :controller => 'content', :action => 'render_page', :requirements => {:language => /\w{2}/} diff --git a/vendor/plugins/routing-filter/.gitignore b/vendor/plugins/routing-filter/.gitignore new file mode 100644 index 0000000..5657f6e --- /dev/null +++ b/vendor/plugins/routing-filter/.gitignore @@ -0,0 +1 @@ +vendor \ No newline at end of file diff --git a/vendor/plugins/routing-filter/MIT-LICENSE b/vendor/plugins/routing-filter/MIT-LICENSE new file mode 100644 index 0000000..ac93a58 --- /dev/null +++ b/vendor/plugins/routing-filter/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 Sven Fuchs + +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. \ No newline at end of file diff --git a/vendor/plugins/routing-filter/README.markdown b/vendor/plugins/routing-filter/README.markdown new file mode 100644 index 0000000..77ee55d --- /dev/null +++ b/vendor/plugins/routing-filter/README.markdown @@ -0,0 +1,123 @@ +## Routing Filter + +This plugin is a wild hack that wraps around the complex beast that the Rails +routing system is to allow for unseen flexibility and power in Rails URL +recognition and generation. + +As powerful and awesome the Rails' routes are, when you need to design your +URLs in a manner that only slightly leaves the paved cowpaths of Rails +conventions, you're usually unable to use all the goodness of helpers and +convenience that Rails ships with. + +## Usage + +This plugin comes with a locale routing filter that demonstrates the +implementation of a custom filter. + +The following would be a sceleton of an empty filter: + + module RoutingFilter + class Awesomeness < Base + def around_recognize(route, path, env) + # Alter the path here before it gets recognized. + # Make sure to yield (calls the next around filter if present and + # eventually `recognize_path` on the routeset): + returning yield do |params| + # You can additionally modify the params here before they get passed + # to the controller. + end + end + + def around_generate(controller, *args, &block) + # Alter arguments here before they are passed to `url_for`. + # Make sure to yield (calls the next around filter if present and + # eventually `url_for` on the controller): + returning yield do |result| + # You can change the generated url_or_path here. Make sure to use + # one of the "in-place" modifying String methods though (like sub! + # and friends). + end + end + end + end + +You then have to specify the filter explicitely in your routes.rb: + + ActionController::Routing::Routes.draw do |map| + map.filter 'awesomeness' + end + +(I am not sure if it makes sense to provide more technical information than +this because the usage of this plugin definitely requires some advanced +knowledge about Rails internals and especially its routing system. So, I +figure, anyone who could use this should also be able to read the code and +figure out what it's doing much better then from any lengthy documentation. + +If I'm mistaken on this please drop me an email with your suggestions.) + + +## Rationale: Two example usecases + +An early usecase from which this originated was the need to define a locale +at the beginning of an URL in a way so that + +* the locale can be omitted when it is the default locale +* all the url\_helpers that are generated by named routes continue to work in +a concise manner (i.e. without specifying all parameters again and again) +* ideally also plays nicely with default route helpers in tests/specs + +You can read about this struggle and two possible, yet unsatisfying solutions +[here](http://www.artweb-design.de/2007/5/13/concise-localized-rails-url-helpers-solved-twice). +The conclusion so far is that Rails itself does not provide the tools to solve +this problem in a clean and dry way. + +Another usecase that eventually spawned the manifestation of this plugin was +the need to map an arbitrary count of path segments to a certain model +instance. In an application that I've been working on recently I needed to +map URL paths to a nested tree of models like so: + + root + + docs + + api + + wiki + +E.g. the docs section should map to the path `/docs`, the api section to +the path `/docs/api` and so on. Furthermore, after these paths there need to be +more things to be specified. E.g. the wiki needs to define a whole Rails +resource with URLs like `/docs/wiki/pages/1/edit`. + +The only way to solve this problem with Rails' routing toolkit is to map +a big, bold `/*everything` catch-all ("globbing") route and process the whole +path in a custom dispatcher. + +This, of course, is a really unsatisfying solution because one has to +reimplement everything that Rails routes are here to help with: regarding both +URL recognition (like parameter mappings, resources, ...) and generation +(url\_helpers). + +## Solution + +This plugin offers a solution that takes exactly the opposite route. + +Instead of trying to change things *between* the URL recognition and +generation stages to achieve the desired result it *wraps around* the whole +routing system and allows to pre- and post-filter both what goes into it +(URL recognition) and what comes out of it (URL generation). + +This way we can leave *everything* else completely untouched. + +* We can tinker with the URLs that we receive from the server and feed URLs to +Rails that perfectly match the best breed of Rails' conventions. +* Inside of the application we can use all the nice helper goodness and +conveniences that rely on these conventions being followed. +* Finally we can accept URLs that have been generated by the url\_helpers and, +again, mutate them in the way that matches our requirements. + +So, even though the plugin itself is a blatant monkey-patch to one of the +most complex area of Rails internals, this solution seems to be effectively +less intrusive and pricey than others are. + +## Etc + +Authors: [Sven Fuchs](http://www.artweb-design.de) +License: MIT \ No newline at end of file diff --git a/vendor/plugins/routing-filter/init.rb b/vendor/plugins/routing-filter/init.rb new file mode 100644 index 0000000..1189921 --- /dev/null +++ b/vendor/plugins/routing-filter/init.rb @@ -0,0 +1 @@ +require 'routing_filter' \ No newline at end of file diff --git a/vendor/plugins/routing-filter/lib/routing_filter.rb b/vendor/plugins/routing-filter/lib/routing_filter.rb new file mode 100644 index 0000000..d67be14 --- /dev/null +++ b/vendor/plugins/routing-filter/lib/routing_filter.rb @@ -0,0 +1,69 @@ +module RoutingFilter + mattr_accessor :active + @@active = true + + class Chain < Array + def << (filter) + filter.successor = last + super + end + + def run(method, *args, &final) + RoutingFilter.active ? last.run(method, *args, &final) : final.call + end + end +end + +# allows to install a filter to the route set by calling: map.filter 'locale' +ActionController::Routing::RouteSet::Mapper.class_eval do + def filter(name, options = {}) + require "routing_filter/#{name}" + klass = RoutingFilter.const_get name.to_s.camelize + @set.filters << klass.new(options) + end +end + +# same here for the optimized url generation in named routes +ActionController::Routing::RouteSet::NamedRouteCollection.class_eval do + # gosh. monkey engineering optimization code + def generate_optimisation_block_with_filtering(*args) + code = generate_optimisation_block_without_filtering *args + if match = code.match(%r(^return (.*) if (.*))) + # returned string must not contain newlines, or we'll spill out of inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806) + "returning(#{match[1]}) { |result| ActionController::Routing::Routes.filters.run :around_generate, *args, &lambda{ result } } if #{match[2]}" + end + end + alias_method_chain :generate_optimisation_block, :filtering +end + +ActionController::Routing::RouteSet.class_eval do + def filters + @filters ||= RoutingFilter::Chain.new + end + + def recognize_path_with_filtering(path, env) + path = path.dup # string is frozen due to memoize + filters.run :around_recognize, path, env, &lambda{ recognize_path_without_filtering(path, env) } + end + alias_method_chain :recognize_path, :filtering + + def generate_with_filtering(*args) + filters.run :around_generate, args.first, &lambda{ generate_without_filtering(*args) } + end + alias_method_chain :generate, :filtering + + # add some useful information to the request environment + # right, this is from jamis buck's excellent article about routes internals + # http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2 + # TODO move this ... where? + alias_method :extract_request_environment_without_host, :extract_request_environment unless method_defined? :extract_request_environment_without_host + def extract_request_environment(request) + returning extract_request_environment_without_host(request) do |env| + env.merge! :host => request.host, + :port => request.port, + :host_with_port => request.host_with_port, + :domain => request.domain, + :subdomain => request.subdomains.first + end + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/lib/routing_filter/base.rb b/vendor/plugins/routing-filter/lib/routing_filter/base.rb new file mode 100644 index 0000000..bc60ba5 --- /dev/null +++ b/vendor/plugins/routing-filter/lib/routing_filter/base.rb @@ -0,0 +1,15 @@ +module RoutingFilter + class Base + attr_accessor :successor, :options + + def initialize(options) + @options = options + options.each{|name, value| instance_variable_set :"@#{name}", value } + end + + def run(method, *args, &block) + successor = @successor ? lambda { @successor.run(method, *args, &block) } : block + send method, *args, &successor + end + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/lib/routing_filter/locale.rb b/vendor/plugins/routing-filter/lib/routing_filter/locale.rb new file mode 100644 index 0000000..b7fcc31 --- /dev/null +++ b/vendor/plugins/routing-filter/lib/routing_filter/locale.rb @@ -0,0 +1,34 @@ +require 'i18n' +require 'routing_filter/base' + +module RoutingFilter + class Locale < Base + @@default_locale = :en + cattr_reader :default_locale + + class << self + def default_locale=(locale) + @@default_locale = locale.to_sym + end + end + + # remove the locale from the beginning of the path, pass the path + # to the given block and set it to the resulting params hash + def around_recognize(path, env, &block) + locale = nil + path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end + returning yield do |params| + params[:locale] = locale if locale + end + end + + def around_generate(*args, &block) + locale = args.extract_options!.delete(:locale) || I18n.locale + returning yield do |result| + if locale.to_sym != @@default_locale + result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" } + end + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb b/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb new file mode 100644 index 0000000..a5bd7aa --- /dev/null +++ b/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb @@ -0,0 +1,19 @@ +require 'routing_filter/base' + +module RoutingFilter + class Pagination < Base + def around_recognize(path, env, &block) + path.gsub! %r(/pages/([\d]+)/?$), '' + returning yield(path, env) do |params| + params[:page] = $1.to_i if $1 + end + end + + def around_generate(*args, &block) + page = args.extract_options!.delete(:page) + returning yield do |result| + result.replace "#{result}/pages/#{page}" if page && page != 1 + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/spec/generation_spec.rb b/vendor/plugins/routing-filter/spec/generation_spec.rb new file mode 100644 index 0000000..224cd4e --- /dev/null +++ b/vendor/plugins/routing-filter/spec/generation_spec.rb @@ -0,0 +1,283 @@ +require File.dirname(__FILE__) + '/spec_helper.rb' + +describe 'RoutingFilter', 'url generation' do + include RoutingFilterHelpers + + before :each do + RoutingFilter::Locale.default_locale = :en + I18n.default_locale = :en + I18n.locale = :en + + @controller = instantiate_controller :locale => 'de', :id => 1 + @set = draw_routes do |map| + map.section 'sections/:id', :controller => 'sections', :action => "show" + map.section_article 'sections/:section_id/articles/:id', :controller => 'articles', :action => "show" + + map.filter 'locale' + map.filter 'pagination' + end + + @site = Site.new + @section = Section.new + @article = Article.new + + @params = {:controller => 'sections', :action => "show", :id => "1"} + @article_params = {:controller => 'articles', :action => 'show', :section_id => "1", :id => "1"} + @locale_filter = @set.filters.first + + Section.stub!(:types).and_return ['Section'] + Section.stub!(:find).and_return @section + end + + def should_recognize_path(path, params) + @set.recognize_path(path, {}).should == params + end + + def section_path(*args) + @controller.send :section_path, *args + end + + def section_article_path(*args) + @controller.send :section_article_path, *args + end + + def url_for(*args) + @controller.send :url_for, *args + end + + describe "named route url_helpers" do + describe "a not nested resource" do + it 'does not change the section_path when the current locale is the default locale and no page option given' do + section_path(:id => 1).should == '/sections/1' + end + + it 'does not change the section_path when given page option equals 1' do + section_path(:id => 1, :page => 1).should == '/sections/1' + end + + it 'appends the pages segments to section_path when given page option does not equal 1' do + section_path(:id => 1, :page => 2).should == '/sections/1/pages/2' + end + + it 'prepends the current locale to section_path when it is not the default locale' do + I18n.locale = :de + section_path(:id => 1).should == '/de/sections/1' + end + + it 'prepends a given locale param to section_path when it is not the default locale' do + I18n.locale = :de + section_path(:id => 1, :locale => :fi).should == '/fi/sections/1' + end + + it 'works on section_path with both a locale and page option' do + section_path(:id => 1, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2' + end + end + + describe "a nested resource" do + it 'does not change the section_article_path when the current locale is the default locale and no page option given' do + section_article_path(:section_id => 1, :id => 1).should == '/sections/1/articles/1' + end + + it 'does not change the section_article_path when given page option equals 1' do + section_article_path(:section_id => 1, :id => 1, :page => 1).should == '/sections/1/articles/1' + end + + it 'appends the pages segments to section_article_path when given page option does not equal 1' do + section_article_path(:section_id => 1, :id => 1, :page => 2).should == '/sections/1/articles/1/pages/2' + end + + it 'prepends the current locale to section_article_path when it is not the default locale' do + I18n.locale = :de + section_article_path(:section_id => 1, :id => 1).should == '/de/sections/1/articles/1' + end + + it 'prepends a given locale param to section_article_path when it is not the default locale' do + I18n.locale = :de + section_article_path(:section_id => 1, :id => 1, :locale => :fi).should == '/fi/sections/1/articles/1' + end + + it 'works on section_article_path with both a locale and page option' do + section_article_path(:section_id => 1, :id => 1, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2' + end + end + end + + describe 'when used with named route url_helper with "optimized" generation blocks' do + describe "a not nested resource" do + # uses optimization + it 'does not change the section_path when the current locale is the default locale and no page option given' do + section_path(1).should == '/sections/1' + end + + # uses optimization + it 'prepends the current locale to section_path when it is not the default locale' do + I18n.locale = :de + section_path(1).should == '/de/sections/1' + end + + it 'prepends a given locale param to section_path when it is not the default locale' do + I18n.locale = :de + section_path(1, :locale => :fi).should == '/fi/sections/1' + end + + it 'does not change the section_path when given page option equals 1' do + section_path(1, :page => 1).should == '/sections/1' + end + + it 'appends the pages segments to section_path when given page option does not equal 1' do + section_path(1, :page => 2).should == '/sections/1/pages/2' + end + + it 'works for section_path with both a locale and page option' do + section_path(1, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2' + end + end + + describe "a nested resource" do + # uses optimization + it 'does not change the section_article_path when the current locale is the default locale and no page option given' do + section_article_path(1, 1).should == '/sections/1/articles/1' + end + + # uses optimization + it 'prepends the current locale to section_article_path when it is not the default locale' do + I18n.locale = :de + section_article_path(1, 1).should == '/de/sections/1/articles/1' + end + + it 'prepends a given locale param when it is not the default locale' do + I18n.locale = :de + section_article_path(1, 1, :locale => :fi).should == '/fi/sections/1/articles/1' + end + + it 'does not change the section_article_path when given page option equals 1' do + section_article_path(1, 1, :page => 1).should == '/sections/1/articles/1' + end + + it 'appends the pages segments to section_article_path when given page option does not equal 1' do + section_article_path(1, 1, :page => 2).should == '/sections/1/articles/1/pages/2' + end + + it 'works for section_article_path with both a locale and page option' do + section_article_path(1, 1, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2' + end + end + end + + describe 'when used with a polymorphic_path' do + describe "a not nested resource" do + # uses optimization + it 'does not change the section_path when the current locale is the default locale and no page option given' do + section_path(@section).should == '/sections/1' + end + + # uses optimization + it 'prepends the current locale to section_path when it is not the default locale' do + I18n.locale = :de + section_path(@section).should == '/de/sections/1' + end + + it 'prepends a given locale param to section_path when it is not the default locale' do + I18n.locale = :de + section_path(@section, :locale => :fi).should == '/fi/sections/1' + end + + it 'does not change the section_path when given page option equals 1' do + section_path(@section, :page => 1).should == '/sections/1' + end + + it 'appends the pages segments to section_path when given page option does not equal 1' do + section_path(@section, :page => 2).should == '/sections/1/pages/2' + end + + it 'works for section_path with both a locale and page option' do + section_path(@section, :locale => :fi, :page => 2).should == '/fi/sections/1/pages/2' + end + end + + describe "a nested resource" do + # uses optimization + it 'does not change the section_article_path when the current locale is the default locale and no page option given' do + section_article_path(@section, @article).should == '/sections/1/articles/1' + end + + # uses optimization + it 'prepends the current locale to section_article_path when it is not the default locale' do + I18n.locale = :de + section_article_path(@section, @article).should == '/de/sections/1/articles/1' + end + + it 'prepends a given locale param to section_article_path when it is not the default locale' do + I18n.locale = :de + section_article_path(@section, @article, :locale => :fi).should == '/fi/sections/1/articles/1' + end + + it 'does not change the section_article_path when given page option equals 1' do + section_article_path(@section, @article, :page => 1).should == '/sections/1/articles/1' + end + + it 'appends the pages segments to section_article_path when given page option does not equal 1' do + section_article_path(@section, @article, :page => 2).should == '/sections/1/articles/1/pages/2' + end + + it 'works for section_article_path with both a locale and page option' do + section_article_path(@section, @article, :locale => :fi, :page => 2).should == '/fi/sections/1/articles/1/pages/2' + end + end + end + + describe 'when used with url_for and an ActivRecord instance' do + describe "a not nested resource" do + it 'prepends the current locale to section_path when it is not the default locale' do + I18n.locale = :de + url_for(@section).should == 'http://test.host/de/sections/1' + end + + it 'does not change the section_path when no page option given' do + url_for(@section).should == 'http://test.host/sections/1' + end + + it 'does not change the section_path when given page option equals 1' do + params = @params.update :id => @section, :page => 1 + url_for(params).should == 'http://test.host/sections/1' + end + + it 'appends the pages segments to section_path when given page option does not equal 1' do + params = @params.update :id => @section, :page => 2 + url_for(params).should == 'http://test.host/sections/1/pages/2' + end + + it 'works for section_path with both a locale and page option' do + params = @params.update :id => @section, :locale => :fi, :page => 2 + url_for(params).should == 'http://test.host/fi/sections/1/pages/2' + end + end + + describe "a nested resource" do + it 'prepends the current locale to section_article_path when it is not the default locale' do + I18n.locale = :de + url_for([@section, @article]).should == 'http://test.host/de/sections/1/articles/1' + end + + it 'does not change the section_article_path when no page option given' do + url_for([@section, @article]).should == 'http://test.host/sections/1/articles/1' + end + + it 'does not change the section_article_path when given page option equals 1' do + params = @article_params.update :section_id => @section, :id => @article, :page => 1 + url_for(params).should == 'http://test.host/sections/1/articles/1' + end + + it 'appends the pages segments to section_article_path when given page option does not equal 1' do + params = @article_params.update :section_id => @section, :id => @article, :page => 2 + url_for(params).should == 'http://test.host/sections/1/articles/1/pages/2' + end + + it 'works for section_article_path with both a locale and page option' do + params = @article_params.update :section_id => @section, :id => @article, :locale => :fi, :page => 2 + url_for(params).should == 'http://test.host/fi/sections/1/articles/1/pages/2' + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/spec/recognition_spec.rb b/vendor/plugins/routing-filter/spec/recognition_spec.rb new file mode 100644 index 0000000..11f0892 --- /dev/null +++ b/vendor/plugins/routing-filter/spec/recognition_spec.rb @@ -0,0 +1,76 @@ +require File.dirname(__FILE__) + '/spec_helper.rb' + +describe 'RoutingFilter', 'url recognition' do + include RoutingFilterHelpers + + before :each do + RoutingFilter::Locale.default_locale = :en + I18n.default_locale = :en + I18n.locale = :en + + @controller = instantiate_controller :locale => 'de', :id => 1 + @set = draw_routes do |map| + map.filter 'locale' + map.filter 'pagination' + + map.section 'sections/:id', :controller => 'sections', :action => "show" + map.article 'sections/:section_id/articles/:id', :controller => 'articles', :action => "show" + end + + @section_params = {:controller => 'sections', :action => "show", :id => "1"} + @article_params = {:controller => 'articles', :action => "show", :section_id => "1", :id => "1"} + @locale_filter = @set.filters.first + end + + def should_recognize_path(path, params) + @set.recognize_path(path, {}).should == params + end + + def section_path(*args) + @controller.send :section_path, *args + end + + def url_for(*args) + @controller.send :url_for, *args + end + + it 'recognizes the path /de/sections/1 and sets the :locale param' do + should_recognize_path '/de/sections/1', @section_params.update(:locale => 'de') + end + + it 'recognizes the path /sections/1/pages/1 and sets the :page param' do + should_recognize_path '/sections/1/pages/1', @section_params.update(:page => 1) + end + + it 'recognizes the path /de/sections/1/pages/1 and sets the :locale param' do + should_recognize_path '/de/sections/1/pages/1', @section_params.update(:locale => 'de', :page => 1) + end + + it 'recognizes the path /sections/1/articles/1 and sets the :locale param' do + should_recognize_path '/sections/1/articles/1', @article_params + end + + it 'recognizes the path /de/sections/1/articles/1 and sets the :locale param' do + should_recognize_path '/de/sections/1/articles/1', @article_params.update(:locale => 'de') + end + + it 'recognizes the path /de/sections/1/articles/1/pages/1 and sets the :locale param' do + should_recognize_path '/de/sections/1/articles/1/pages/1', @article_params.update(:locale => 'de', :page => 1) + end + + it 'recognizes the path /sections/1 and does not set a :locale param' do + should_recognize_path '/sections/1', @section_params + end + + it 'recognizes the path /sections/1 and does not set a :page param' do + should_recognize_path '/sections/1', @section_params + end + + it 'recognizes the path /sections/1/articles/1 and does not set a :locale param' do + should_recognize_path '/sections/1/articles/1', @article_params + end + + it 'recognizes the path /sections/1/articles/1 and does not set a :page param' do + should_recognize_path '/sections/1/articles/1', @article_params + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/spec/routing_filter_spec.rb b/vendor/plugins/routing-filter/spec/routing_filter_spec.rb new file mode 100644 index 0000000..f919c29 --- /dev/null +++ b/vendor/plugins/routing-filter/spec/routing_filter_spec.rb @@ -0,0 +1,70 @@ +require File.dirname(__FILE__) + '/spec_helper.rb' + +describe 'RoutingFilter' do + include RoutingFilterHelpers + + before :each do + @controller = instantiate_controller :locale => 'de', :section_id => 1 + @set = draw_routes do |map| + map.section 'sections/:section_id', :controller => 'sections', :action => "show" + map.filter 'locale' + map.filter 'pagination' + end + @locale_filter = @set.filters.first + @pagination_filter = @set.filters.last + end + + def recognize_path(path = '/de/sections/1', options = {}) + @set.recognize_path path, options + end + + def url_for(options) + @controller.send :url_for, options + end + + def section_path(*args) + @controller.send :section_path, *args + end + + it 'installs filters to the route set' do + @locale_filter.should be_instance_of(RoutingFilter::Locale) + @pagination_filter.should be_instance_of(RoutingFilter::Pagination) + end + + it 'calls the first filter for route recognition' do + @locale_filter.should_receive(:around_recognize).and_return :foo => :bar + recognize_path.should == {:foo => :bar} + end + + it 'calls the second filter for route recognition' do + @pagination_filter.should_receive(:around_recognize).and_return :foo => :bar + recognize_path.should == {:foo => :bar} + end + + it 'calls the first filter for url generation' do + @locale_filter.should_receive(:around_generate).and_return '/sections/1' + url_for :controller => 'sections', :action => 'show', :section_id => 1 + end + + it 'calls the second filter for url generation' do + @pagination_filter.should_receive(:around_generate).and_return '/sections/1' + url_for :controller => 'sections', :action => 'show', :section_id => 1 + end + + it 'calls the first filter for named route url_helper' do + @locale_filter.should_receive(:around_generate).and_return '/sections/1' + section_path :section_id => 1 + end + + it 'calls the filter for named route url_helper with "optimized" generation blocks' do + # at_least(1) since the inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper also call us (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806) + @locale_filter.should_receive(:around_generate).at_least(1).and_return '/sections/1' + section_path 1 + end + + it 'calls the filter for named route polymorphic_path' do + # at_least(1) since the inline code comments in ActionController::Routing::RouteSet::NamedRouteCollection#define_url_helper also call us (as of http://github.com/rails/rails/commit/a2270ef2594b97891994848138614657363f2806) + @locale_filter.should_receive(:around_generate).at_least(1).and_return '/sections/1' + section_path Section.new + end +end \ No newline at end of file diff --git a/vendor/plugins/routing-filter/spec/spec.opts b/vendor/plugins/routing-filter/spec/spec.opts new file mode 100644 index 0000000..391705b --- /dev/null +++ b/vendor/plugins/routing-filter/spec/spec.opts @@ -0,0 +1,4 @@ +--colour +--format progress +--loadby mtime +--reverse diff --git a/vendor/plugins/routing-filter/spec/spec_helper.rb b/vendor/plugins/routing-filter/spec/spec_helper.rb new file mode 100644 index 0000000..a92a3d9 --- /dev/null +++ b/vendor/plugins/routing-filter/spec/spec_helper.rb @@ -0,0 +1,49 @@ +$: << File.dirname(__FILE__) +$: << File.dirname(__FILE__) + '/../lib/' +$: << File.dirname(__FILE__) + '/../vendor/rails/actionpack/lib' +$: << File.dirname(__FILE__) + '/../vendor/rails/activesupport/lib' + +require 'action_controller' +require 'action_controller/test_process' +require 'active_support/vendor' + +require 'routing_filter' +require 'routing_filter/locale' +require 'routing_filter/pagination' + +class Site +end + +class Section + def id; 1 end + alias :to_param :id + + def type; 'Section' end + + def path; 'section' end +end + +class Article + def to_param; 1 end +end + +module RoutingFilterHelpers + def draw_routes(&block) + set = returning ActionController::Routing::RouteSet.new do |set| + class << set; def clear!; end; end + set.draw &block + silence_warnings{ ActionController::Routing.const_set 'Routes', set } + end + set + end + + def instantiate_controller(params) + returning ActionController::Base.new do |controller| + request = ActionController::TestRequest.new + url = ActionController::UrlRewriter.new(request, params) + controller.stub!(:request).and_return request + controller.instance_variable_set :@url, url + controller + end + end +end \ No newline at end of file -- cgit v1.3