import sinatra-decompile

This commit is contained in:
Konstantin Haase 2011-03-24 08:45:29 +01:00
parent 07a649ab6d
commit f5e015894d
3 changed files with 114 additions and 0 deletions

View File

@ -0,0 +1,61 @@
require 'sinatra/base'
require 'backports'
module Sinatra
##
# Can be used as extension or stand-alone:
#
# Sinatra::Decompile.decompile(...)
module Decompile
extend self
##
# Regenerates a string pattern for a given route
#
# Example:
#
# class Sinatra::Application
# routes.each do |verb, list|
# puts "#{verb}:"
# list.each do |data|
# puts "\t" << decompile(data)
# end
# end
# end
#
# Will return the internal Regexp if unable to reconstruct the pattern,
# which likely indicates that a Regexp was used in the first place.
#
# You can also use this to check whether you could actually use a string
# pattern instead of your regexp:
#
# decompile /^/foo$/ # => '/foo'
def decompile(pattern, keys = nil, *)
# Everything in here is basically just the reverse of
# Sinatra::Base#compile
pattern, keys = pattern if pattern.respond_to? :to_ary
keys, str = keys.try(:dup), pattern.inspect
return pattern unless str.start_with? '/' and str.end_with? '/'
str.gsub! /^\/\^?|\$?\/$/, ''
return pattern if str =~ /^[\.\+]/
str.gsub! /\([^\(]*\)/ do |part|
case part
when '(.*?)'
return pattern if keys.shift != 'splat'
'*'
when '([^\/?#]+)'
return pattern if keys.empty?
":" << keys.shift
else
return pattern
end
end
str.gsub /(.)([\.\+\(\)\/])/ do
return pattern if $1 != "\\"
$2
end
end
end
register Decompile
end

View File

@ -0,0 +1,42 @@
require 'backports'
require_relative 'spec_helper'
RSpec::Matchers.define :decompile do |path|
match do |app|
@compiled, @keys = app.send :compile, path
@decompiled = app.decompile(@compiled, @keys)
@decompiled.should == path
end
failure_message_for_should do |app|
values = [app, @compiled, @keys, path, @decompiled].map(&:inspect)
"expected %s to decompile %s with %s to %s, but was %s" % values
end
end
describe Sinatra::Decompile do
subject { Sinatra::Application }
it { should decompile("") }
it { should decompile("/") }
it { should decompile("/?") }
it { should decompile("/foo") }
it { should decompile("/:name") }
it { should decompile("/:name?") }
it { should decompile("/:foo/:bar") }
it { should decompile("/page/:id/edit") }
it { should decompile("/hello/*") }
it { should decompile("/*/foo/*") }
it { should decompile("*") }
it { should decompile(":name.:format") }
it { should decompile(/./) }
it { should decompile(/f(oo)/) }
it { should decompile(/ba+r/) }
it 'just returns strings' do
subject.decompile('/foo').should == '/foo'
end
it 'just decompile simple regexps without keys' do
subject.decompile(%r{/foo}).should == '/foo'
end
end

View File

@ -0,0 +1,11 @@
require 'forwardable'
module TestHelpers
end
require 'sinatra/contrib'
RSpec.configure do |config|
config.expect_with :rspec, :stdlib
config.include Sinatra::TestHelpers
end