Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
99e884b
Create basic accessors for scope properties in AbstractScope
ujjwalt Jun 30, 2014
ce44525
Implemented initialization of Abstract Scope
ujjwalt Jul 1, 2014
56baf07
Remove NilClass refinements as they're not supported on JRuby
ujjwalt Jul 1, 2014
4ffcba0
Refactored match and http helpers and mount for generating routes
ujjwalt Jul 1, 2014
5e28c76
Fixed bug in Scope.module where empty module rendered as '/'
ujjwalt Jul 3, 2014
89d73c1
Instance exec on scoping methods to correctly set self
ujjwalt Jul 3, 2014
069bf57
Added concerns
ujjwalt Jul 4, 2014
de296ae
Implemented controller and concerns method to return the instance var…
ujjwalt Jul 4, 2014
a984aa8
Implemented methods to return constraints and defaults and also act a…
ujjwalt Jul 4, 2014
bb2e8e3
Don't merge permanently with parent hash
ujjwalt Jul 4, 2014
4bb8b4b
Cleaned out match to incorporate MatchRoute
ujjwalt Jul 13, 2014
b577eca
Add match_route class to handle creating routes on match statements
ujjwalt Jul 13, 2014
829c52e
Set @path variable from name if name is in path names
ujjwalt Aug 2, 2014
05c691e
Changed AbstractScope to a module
ujjwalt Aug 13, 2014
02053c4
Fixed prefix_name_for_action
ujjwalt Aug 13, 2014
465e21c
Added redirection module to Scope
ujjwalt Aug 13, 2014
adec389
Set anchor to true by default
ujjwalt Aug 13, 2014
19af8c4
Fixed module method
ujjwalt Aug 13, 2014
af4d7a3
Duplicate dispatch/routing_test.rb for our own tests
ujjwalt Aug 14, 2014
38bcb5e
Implemented a basic singleton resource
ujjwalt Aug 14, 2014
687f777
Fixed route generation for canonical actions
ujjwalt Aug 16, 2014
2779012
Improved prefix naming for singleton resources
ujjwalt Aug 16, 2014
22ed953
Added member scope for resources
ujjwalt Aug 16, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,5 @@ end

# A gem necessary for ActiveRecord tests with IBM DB
gem 'ibm_db' if ENV['IBM_DB']

gem 'byebug'
138 changes: 138 additions & 0 deletions actionpack/lib/action_dispatch/routing/dsl/abstract_scope.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
require 'action_dispatch/routing/dsl/normalization'

module ActionDispatch
module Routing
module DSL
module AbstractScope
# Constants
# =========
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
SCOPE_OPTIONS = [:path, :shallow_path, :as, :shallow_prefix, :module,
:controller, :action, :path_names, :constraints,
:shallow, :blocks, :defaults, :options]

# Accessors
# =========
attr_accessor :set
attr_reader :controller, :action, :concerns, :parent

def initialize(parent, *args)
if parent
@parent, @set, @concerns = parent, parent.set, parent.concerns
else
@parent, @concerns = nil, {}
end

# Extract options out of the variable arguments
options = args.extract_options!.dup

options[:path] = args.flatten.join('/') if args.any?
options[:constraints] ||= {}

if options[:constraints].is_a?(Hash)
defaults = options[:constraints].select do
|k, v| URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Fixnum))
end

(options[:defaults] ||= {}).reverse_merge!(defaults)
else
block, options[:constraints] = options[:constraints], {}
end

SCOPE_OPTIONS.each do |option|
if option == :blocks
value = block
elsif option == :options
value = options
else
value = options.delete(option) { |_option| {} if %w(defaults path_names constraints).include?(_option.to_s) }
end

# Set instance variables
instance_variable_set(:"@#{option}", value || nil)
end
end

def path
parent_path = parent ? parent.path : nil
merge_with_slash(parent_path, @path)
end

def shallow_path
parent_shallow_path = parent ? parent.shallow_path : nil
merge_with_slash(parent_shallow_path, @shallow_path)
end

def as
parent_as = parent ? parent.as : nil
merge_with_underscore(parent_as, @as)
end

def shallow_prefix
parent_shallow_prefix = parent ? parent.shallow_prefix : nil
merge_with_underscore(parent_shallow_prefix, @shallow_prefix)
end

def module
if parent && parent.module
if @module
"#{parent.module}/#{@module}"
else
parent.module
end
else
@module
end
end

def path_names
parent_path_names = parent ? parent.path_names : nil
merge_hashes(parent_path_names, @path_names)
end

def shallow?
@shallow
end

def blocks
parent_blocks = parent ? parent.blocks : nil
merged = parent_blocks ? parent_blocks.dup : []
merged << @blocks if @blocks
merged
end

def options
parent_options = parent ? parent.options : nil
merge_hashes(parent_options, @options)
end

protected
def merge_with_slash(parent, child)
self.class.normalize_path("#{parent}/#{child}")
end

def merge_with_underscore(parent, child)
parent ? "#{parent}_#{child}" : child
end

def merge_hashes(parent, child)
(parent || {}).except(*override_keys(child)).merge(child)
end

def override_keys(child) #:nodoc:
child.key?(:only) || child.key?(:except) ? [:only, :except] : []
end

def defaults
parent_defaults = parent ? parent.defaults : nil
merge_hashes(parent_defaults, @defaults)
end

def constraints
parent_constraints = parent ? parent.constraints : nil
merge_hashes(parent_constraints, @constraints)
end
end
end
end
end
74 changes: 74 additions & 0 deletions actionpack/lib/action_dispatch/routing/dsl/match_route.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# MatchRoute is a special scope in the sense that it has some additonal options
# like :anchor, :to, :via and :format that are specific to routes
require 'action_dispatch/routing/dsl/abstract_scope'

module ActionDispatch
module Routing
module DSL
class MatchRoute
include AbstractScope
ROUTE_OPTIONS = [:anchor, :format, :to, :via]

def initialize(*args)
# options_path = args.extract_options[:path] || nil
super # Let AbstractScope handle all stuff like setting ivar
# Now handle route options

# Set anchor to true by default unless a value is supplied
@anchor = true unless options.key?(:anchor)

# Assign options[:to] to @to and then proceed to set an approriate value if
# it evaluates to false
unless @to = options[:to]
# If we have a controller and action then set 'to' to 'controller#action'
# if it is nil
if controller && action
@to = "#{controller}##{action}"
else
# If @to is still nill then convert the path by assuming the entire
# path to represent the controller and the last segment as action e.g.
# match '/admin/controller/action'
# is tanslated as match controller: 'admin/controller', action: 'action'
#
# But before we do that we need to check if the user specified an optional
# format like (.:format)
# If so then we need to consider the path without the optional parameter
*controllers, action = @path.split('/')
action = action.to_s.sub(/\(\.:format\)$/, '')
@to = "#{controllers.select(&:present?).join('/')}##{action}"
end
end
# Change all '-' to '_' in the to
@to.tr!('-', '_') if @to.is_a? String

# Set @path from path names if available
@path = path_names[@path.to_sym] || @path

# If we still can't set a path then there is something wrong
raise ArgumentError, "path is required" if @path.blank?

add_to_router
end

protected
def add_to_router
build
setup
add_route
end

def build
#
end

def setup
#
end

def add_route
#
end
end
end
end
end
27 changes: 27 additions & 0 deletions actionpack/lib/action_dispatch/routing/dsl/normalization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'action_dispatch/journey'
require 'active_support/concern'

module ActionDispatch
module Routing
module DSL
module AbstractScope
extend ActiveSupport::Concern

included do |base|
# Invokes Journey::Router::Utils.normalize_path and ensure that
# (:locale) becomes (/:locale) instead of /(:locale). Except
# for root cases, where the latter is the correct one.
def base.normalize_path(path)
path = Journey::Router::Utils.normalize_path(path)
path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^)]+\)$}
path
end

def base.normalize_name(name)
normalize_path(name)[1..-1].tr("/", "_")
end
end
end
end
end
end
60 changes: 60 additions & 0 deletions actionpack/lib/action_dispatch/routing/dsl/resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require "action_dispatch/routing/dsl/singleton_resource"

module ActionDispatch
module Routing
module DSL
class Resource < SingletonResource
attr_reader :param

def initialize(parent, resource, options)
super
@param = (options[:param] || :id).to_sym
@path = @path.pluralize
@name = @name.singularize
end

def draw
get '/', action: :index
post '/', action: :create
get '/new', action: :new
get '/edit', action: :edit
get "/:#{@param}", action: :show
patch "/:#{@param}", action: :update
put "/:#{@param}", action: :update
delete "/:#{@param}", action: :destroy
end

def member
param = ":#{name.singularize}_#{@param}"
@path, old_path = "/#{@path}/#{param}", @path
yield
@path = old_path
end

def decomposed_match(path, options) # :nodoc:
if on = options.delete(:on)
send(on) { decomposed_match(path, options) }
else
add_route(path, options)
end
end

def prefixed_name(name_prefix, prefix)
if @parent.class != Scope
[prefix, @parent.name, name]
else
if prefix.blank?
if has_named_route?(name.pluralize)
[name]
else
[name.pluralize]
end
else
[prefix, name]
end
end
end
end
end
end
end
38 changes: 38 additions & 0 deletions actionpack/lib/action_dispatch/routing/dsl/scope.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'action_dispatch/routing/dsl/abstract_scope'
require 'action_dispatch/routing/redirection'

module ActionDispatch
module Routing
module DSL
class Scope
include AbstractScope
include Redirection

def method_missing(method, *args)
@count ||= 0
@count += 1
msg = "#{@count}) Missing :#{method}"
divider = "="*msg.length
puts divider, msg, divider
end

def default_url_options=(options)
@set.default_url_options = options
end
alias_method :default_url_options, :default_url_options=

# Query if the following named route was already defined.
def has_named_route?(name)
@set.named_routes.routes[name.to_sym]
end
end
end
end
end

require 'action_dispatch/routing/dsl/scope/mount'
require 'action_dispatch/routing/dsl/scope/match'
require 'action_dispatch/routing/dsl/scope/http_helpers'
require 'action_dispatch/routing/dsl/scope/scoping'
require 'action_dispatch/routing/dsl/scope/concerns'
require 'action_dispatch/routing/dsl/scope/resources'
Loading