>> path
=> "/:foo/bar/:baz"
>> params
=> {:foo=>"FOO", :baz=>"BAZ"}
>> path.split("/").map { |v| (params[v[1,v.length].to_sym] if !v.empty? && v[0] == ':'[0]) || v }.join('/')
=> "/FOO/bar/BAZ"
>>
def interpreted_route_path(path, params)
path.split('/').map { |v| (params[v[1,v.length].to_sym] if !v.empty? && v[0] == ':'[0]) || v }.join('/')
end
# To check map.root:
# use as: check_routing_for(:route_name => 'root', :route_path => '/', :controller => 'foo', :action => 'bar')
def check_routing_for(options)
route_name = options.delete(:route_name)
route_path = options.delete(:route_path)
controller, action = options.delete(:controller), options.delete(:action)
class_eval do
describe "map.#{route_name}" do
before do
@route_hash = { :controller => controller, :action => action }.merge(options)
end
it "Routes to #{route_path}" do
route_for(@route_hash).should == interpreted_route_path(route_path, options)
end
it "Recognizes #{@route_hash.inspect}" do
params_from(:get, interpreted_route_path(route_path, options)).should == @route_hash
end
end
end
end
Refactorings
No refactoring yet !
hellekin
October 27, 2008, October 27, 2008 22:16, permalink
Ok, here's one solution, but... ahem... I don't understand it :)
def interpreted_route_path(path, params)
path.gsub(/:([^\/]+)/) { |b| params[b[1..-1].to_sym] }
end
>> path ="/:foo/bar/:baz"
=> "/:foo/bar/:baz"
>> params = { :foo => "FOO", :baz => "BAZ" }
=> {:foo=>"FOO", :baz=>"BAZ"}
>> path.gsub(/:([^\/]+)/) { |b| params[b[1..-1].to_sym] }
=> "/FOO/bar/BAZ"
>> path.gsub(/:([^\/]+)/) { |b| b }
=> "/:foo/bar/:baz"
>> path.gsub(/:([^\/]+)/) { |b| b.upcase }
=> "/:FOO/bar/:BAZ"
>> path.gsub(/:([^\/]+)/) { |b| "--#{b}--" }
=> "/--:foo--/bar/--:baz--"
>> path.gsub(/:[^\/]+/) { |b| "--#{b}--" }
=> "/--:foo--/bar/--:baz--"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b]}--" }
=> "/----/bar/----"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b.to_sym]}--" }
=> "/----/bar/----"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b[1..-1].to_sym]}--" }
=> "/--FOO--/bar/--BAZ--"
hellekin
October 27, 2008, October 27, 2008 22:17, permalink
Ok, here's one solution, but... ahem... I don't understand it :)
def interpreted_route_path(path, params)
path.gsub(/:([^\/]+)/) { |b| params[b[1..-1].to_sym] }
end
>> path ="/:foo/bar/:baz"
=> "/:foo/bar/:baz"
>> params = { :foo => "FOO", :baz => "BAZ" }
=> {:foo=>"FOO", :baz=>"BAZ"}
>> path.gsub(/:([^\/]+)/) { |b| params[b[1..-1].to_sym] }
=> "/FOO/bar/BAZ"
>> path.gsub(/:([^\/]+)/) { |b| b }
=> "/:foo/bar/:baz"
>> path.gsub(/:([^\/]+)/) { |b| b.upcase }
=> "/:FOO/bar/:BAZ"
>> path.gsub(/:([^\/]+)/) { |b| "--#{b}--" }
=> "/--:foo--/bar/--:baz--"
>> path.gsub(/:[^\/]+/) { |b| "--#{b}--" }
=> "/--:foo--/bar/--:baz--"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b]}--" }
=> "/----/bar/----"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b.to_sym]}--" }
=> "/----/bar/----"
>> path.gsub(/:[^\/]+/) { |b| "--#{params[b[1..-1].to_sym]}--" }
=> "/--FOO--/bar/--BAZ--"
hellekin
October 27, 2008, October 27, 2008 22:31, permalink
So, here's the final version, thanks to Kyle and underflow
def interpreted_route_path(path, params)
path.gsub(/:([^\/]+)/) { |b| params[$1.to_sym] }
end
def check_routing_for(options)
route_name = options.delete(:route_name)
route_path = options.delete(:route_path)
controller, action = options.delete(:controller), options.delete(:action)
class_eval do
describe "map.#{route_name}" do
before do
@route_hash = { :controller => controller, :action => action.gsub(/(:\w+)/, "#{options[" + '\1' + "]}") }.merge(options)
end
it "Routes to #{route_path}" do
route_for(@route_hash).should == interpreted_route_path(route_path, options)
end
it "Recognizes #{@route_hash.inspect}" do
params_from(:get, interpreted_route_path(route_path, options)).should == @route_hash
end
end
end
end
hellekin
October 27, 2008, October 27, 2008 22:37, permalink
Hmmm line 13 is wrong!
@route_hash = { :controller => controller, :action => action }.merge(options)
hellekin
October 27, 2008, October 27, 2008 23:00, permalink
Here is the final final version ;o)
def interpreted_route_path(path, params)
path.gsub(/:([^\/]+)/) { |b| params[$1.to_sym] }
end
def check_routing_for(options)
route_name = options.delete(:route_name)
route_path = options.delete(:route_path)
controller, action = options.delete(:controller), options.delete(:action)
class_eval do
describe "map.#{route_name}" do
before do
@route_hash = { :controller => controller, :action => action }.merge(options)
end
it "Routes to #{route_path}" do
route_for(@route_hash).should == interpreted_route_path(route_path, options)
end
it "Recognizes #{@route_hash.inspect}" do
params_from(:get, interpreted_route_path(route_path, options)).should == @route_hash
end
end
end
end
hellekin
October 28, 2008, October 28, 2008 14:52, permalink
This version is more solid
# Add this to spec/spec_helper.rb
# Use as:
# check_route_for(:route_name => 'foo', :route_path => '/foo/:bar/baz/:quuq', :controller => 'foo', :action => 'foos', :bar => 'BAR', :quux => 'Moo')
Spec::Runner.configure do |config|
# [snip]
def interpreted_route_path(path, params)
params ||= {}
path.gsub(/:([^\/]+)/) { |b| params[$1.to_sym] }
end
def check_routing_for(options)
route_name = options.delete(:route_name) # map.#{route_name}
route_path = options.delete(:route_path) # /some/action/:param
controller = options.delete(:controller) # some_controller
action = options.delete(:action) # some_action
%w(route_name route_path controller action).each do |required_key|
next unless instance_eval(required_key).nil?
raise ArgumentError, "check_routing_for: missing required key #{required_key} (:route_name, :route_path, :controller, :action)"
end
class_eval do
describe "map.#{route_name}" do
before do
@route_hash = (options || {}).merge({ :controller => controller, :action => action })
end
it "routes to #{route_path}" do
route_for(@route_hash).should == interpreted_route_path(route_path, options)
end
it "recognizes #{(options || {}).merge({ :controller => controller, :action => action }).inspect}" do
params_from(:get, interpreted_route_path(route_path, options)).should == @route_hash
end
end
end
end
end # Spec::Runner.configure block
I'm trying to extract a pattern from rails routes rspec'ing into a helper.
The helper works great and makes it nice to read/write routing specs (only for :get right now) such as shown below.
But the "interpreted_route_path" part really sucks. Any better ways?