Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

First commit

  • Loading branch information...
commit f24e1dc4195b2e3ab0303f370056e50af5247ab8 0 parents
@dhh dhh authored
8 .gitignore
@@ -0,0 +1,8 @@
+.bundle/
+log/*.log
+pkg/
+test/dummy/db/*.sqlite3
+test/dummy/log/*.log
+test/dummy/tmp/
+test/dummy/.sass-cache
+tmp/
2  Gemfile
@@ -0,0 +1,2 @@
+source "http://rubygems.org"
+gemspec
64 Gemfile.lock
@@ -0,0 +1,64 @@
+PATH
+ remote: .
+ specs:
+ routing_concerns (0.1.0)
+ actionpack (>= 3.2.0)
+ activemodel (>= 3.2.0)
+ railties (>= 3.2.0)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ actionpack (3.2.6)
+ activemodel (= 3.2.6)
+ activesupport (= 3.2.6)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.1)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.3)
+ activemodel (3.2.6)
+ activesupport (= 3.2.6)
+ builder (~> 3.0.0)
+ activesupport (3.2.6)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ builder (3.0.0)
+ erubis (2.7.0)
+ hike (1.2.1)
+ i18n (0.6.0)
+ journey (1.0.4)
+ json (1.7.3)
+ multi_json (1.3.6)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ railties (3.2.6)
+ actionpack (= 3.2.6)
+ activesupport (= 3.2.6)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ sprockets (2.1.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ thor (0.15.3)
+ tilt (1.3.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ rake
+ routing_concerns!
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright 2012 David Heinemeier Hansson
+
+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.
102 README.rdoc
@@ -0,0 +1,102 @@
+= Routing Concerns
+
+Abstract common routing resource concerns to cut down on duplication.
+
+Code before:
+
+```ruby
+BCX::Application.routes.draw do
+ resources :calendar_events do
+ get :past, on: :collection
+ resources :comments
+ end
+
+ resources :messages { resources :comments }
+ resources :forwards { resources :comments }
+ resources :uploads { resources :comments }
+ resources :documents { resources :comments }
+ resources :todos { resources :comments }
+
+ resources :projects, defaults: { bucket_type: 'project' } do
+ post :trash, :restore, on: :member
+
+ resources :messages, except: [ :new ] do
+ post :trash, :restore, on: :member
+ resources :image_attachments, only: :index
+ end
+
+ resources :forwards do
+ member do
+ get :content
+ post :trash, :restore
+ end
+
+ resources :image_attachments, only: :index
+ end
+
+ resources :uploads do
+ post :trash, :restore, on: :member
+ resources :image_attachments, only: :index
+ end
+
+ resources :todolists do
+ get :more, :completed, on: :collection
+ post :trash, :restore, on: :member
+ end
+
+ get 'todolists/:todolist_id/todos/completed', to: 'todos#completed', as: 'todolist_completed_todos'
+ resources :todos do
+ post :toggle, :trash, :restore, on: :member
+ end
+
+ resources :comments do
+ post :trash, on: :member
+ resources :image_attachments, only: :index
+ end
+ end
+end
+```
+
+Code after:
+
+```ruby
+BCX::Application.routes.draw do
+ concern :commentable do
+ resources :comments
+ end
+
+ concern :trashable do
+ post :trash, :restore, on: :member
+ end
+
+ concern :image_attachable do
+ resources :image_attachments, only: :index
+ end
+
+ resources :calendar_events, concerns: :commentable do
+ get :past, on: :collection
+ end
+
+ resources :messages, :forwards, :uploads, :documents, :todos, concerns: :commentable
+
+ resources :projects, concerns: :trashable, defaults: { bucket_type: 'project' } do
+ resources :messages, :uploads, :comments, concerns: [:trashable, :image_attachable]
+
+ resources :forwards, concerns: [:trashable, :image_attachable] do
+ get :content, on: :member
+ end
+
+ resources :todolists, concerns: :trashable do
+ get :more, :completed, on: :collection
+ end
+
+ resources :todos, concerns: :trashable do
+ post :toggle, on: :member
+ end
+ end
+end
+```
+
+== Compatibility
+
+This plugin was designed as a proof-of-concept for a feature that's destined for Rails 4. It has only been tested on Rails 3.2+, but may work on earlier versions as well.
38 Rakefile
@@ -0,0 +1,38 @@
+#!/usr/bin/env rake
+begin
+ require 'bundler/setup'
+rescue LoadError
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
+end
+begin
+ require 'rdoc/task'
+rescue LoadError
+ require 'rdoc/rdoc'
+ require 'rake/rdoctask'
+ RDoc::Task = Rake::RDocTask
+end
+
+RDoc::Task.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'RoutingConcerns'
+ rdoc.options << '--line-numbers'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+
+
+
+Bundler::GemHelper.install_tasks
+
+require 'rake/testtask'
+
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
+
+
+task :default => :test
56 lib/action_dispatch/routing/concerns.rb
@@ -0,0 +1,56 @@
+require 'action_dispatch'
+
+module ActionDispatch::Routing::Mapper::Concerns
+ def concern(name, &block)
+ @concerns ||= {}
+ @concerns[name] = block
+ end
+
+ def concerns(*names)
+ Array(names).flatten.compact.each do |name|
+ if @concerns && concern = @concerns[name]
+ instance_eval(&concern)
+ else
+ raise "No concern named #{name} was found!"
+ end
+ end
+ end
+end
+
+module ActionDispatch::Routing::Mapper::ResourcesWithConcerns
+ extend ActiveSupport::Concern
+
+ included do
+ alias_method_chain :resource, :concerns
+ alias_method_chain :resources, :concerns
+ end
+
+ def resource_with_concerns(*resources, &block)
+ if (options_with_concerns = resources.last).is_a?(Hash)
+ named_concerns = options_with_concerns[:concerns]
+
+ resource_without_concerns(*resources) do
+ concerns(named_concerns)
+ block.call if block_given?
+ end
+ else
+ resource_without_concerns(*resources, &block)
+ end
+ end
+
+ def resources_with_concerns(*resources, &block)
+ if (options_with_concerns = resources.last).is_a?(Hash)
+ named_concerns = options_with_concerns[:concerns]
+
+ resources_without_concerns(*resources) do
+ concerns(named_concerns)
+ block.call if block_given?
+ end
+ else
+ resources_without_concerns(*resources, &block)
+ end
+ end
+end
+
+ActionDispatch::Routing::Mapper.send :include, ActionDispatch::Routing::Mapper::Concerns
+ActionDispatch::Routing::Mapper.send :include, ActionDispatch::Routing::Mapper::ResourcesWithConcerns
16 lib/active_model/forbidden_attributes_protection.rb
@@ -0,0 +1,16 @@
+module ActiveModel
+ class ForbiddenAttributes < StandardError
+ end
+
+ module ForbiddenAttributesProtection
+ def sanitize_for_mass_assignment(new_attributes, options = {})
+ if !new_attributes.respond_to?(:permitted?) || (new_attributes.respond_to?(:permitted?) && new_attributes.permitted?)
+ super
+ else
+ raise ActiveModel::ForbiddenAttributes
+ end
+ end
+ end
+end
+
+ActiveModel.autoload :ForbiddenAttributesProtection
2  lib/routing_concerns.rb
@@ -0,0 +1,2 @@
+require 'action_dispatch/routing/concerns'
+require 'routing_concerns/railtie'
1  lib/routing_concerns/railtie.rb
@@ -0,0 +1 @@
+require 'rails/railtie'
3  lib/routing_concerns/version.rb
@@ -0,0 +1,3 @@
+module RoutingConcerns
+ VERSION = "0.1.0"
+end
22 routing_concerns.gemspec
@@ -0,0 +1,22 @@
+$:.push File.expand_path("../lib", __FILE__)
+
+# Maintain your gem's version:
+require "routing_concerns/version"
+
+# Describe your gem and declare its dependencies:
+Gem::Specification.new do |s|
+ s.name = "routing_concerns"
+ s.version = RoutingConcerns::VERSION
+ s.authors = ["David Heinemeier Hansson"]
+ s.email = ["david@heinemeierhansson.com"]
+ s.summary = "Routing concerns for Action Pack"
+
+ s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
+ s.test_files = Dir["test/**/*"]
+
+ s.add_dependency "actionpack", ">= 3.2.0"
+ s.add_dependency "activemodel", ">= 3.2.0"
+ s.add_dependency "railties", ">= 3.2.0"
+
+ s.add_development_dependency "rake"
+end
43 test/routing_concerns_test.rb
@@ -0,0 +1,43 @@
+# Configure Rails Environment
+ENV["RAILS_ENV"] = "test"
+
+require 'test/unit'
+
+require 'abstract_controller'
+require 'action_controller'
+require 'action_dispatch'
+
+require 'routing_concerns'
+
+class CommentsController < ActionController::Base
+ def index
+ head :ok
+ end
+end
+
+class RoutingConcernsTest < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ concern :commentable do
+ resources :comments
+ end
+
+ resources :posts, concerns: :commentable
+ resource :post, concerns: :commentable
+ resources :comments
+ end
+ end
+
+ include Routes.url_helpers
+ def app; Routes end
+
+ test "accessing concern from resources" do
+ get "/posts/1/comments"
+ assert_equal "200", @response.code
+ end
+
+ test "accessing concern from resource" do
+ get "/post/comments"
+ assert_equal "200", @response.code
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.