Skip to content

Instantly share code, notes, and snippets.

@tekwiz
Created October 2, 2012 17:01
Show Gist options
  • Save tekwiz/3821152 to your computer and use it in GitHub Desktop.
Save tekwiz/3821152 to your computer and use it in GitHub Desktop.
Circuit Formats
module Circuit
FORMAT_EXT_REGEXP = /\.([^\.]+)$/
module Validators
silence_warnings do
SLUG_REGEXP = /\A(?:[-_!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*\Z/
end
class SlugValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add attribute, options[:message] unless value =~ SLUG_REGEXP
end
end
end
module Rack
module Request::ClassMethodsExt
# Parses a URI path String into its segments and iterates over them.
# @param [String] path to parse
# @yield [String, nil] segment or `nil` for the root
def each_path_segment(path)
segments = path_segments(path)
segments.each_with_index do |segment, i|
segment.extend(Module.new do
module_eval %(def last?() #{i == segments.length-1 ? "true" : "false"}; end)
end)
yield(segment)
end
end
end
UnknownFormatError = Class.new(CircuitError)
class Behavioral
def call_with_rescue_unknown_format(env)
call_without_rescue_unknown_format(env)
rescue ::Circuit::Rack::UnknownFormatError => e
[404, {"Content-Type" => "text/plain"}, [e.message]]
end
alias_method_chain :call, :rescue_unknown_format
private
def remap(request)
route = ::Circuit.node_store.get(request.site, request.path)
return nil if route.blank?
if route.last.finite? and request.path =~ FORMAT_EXT_REGEXP
if format = Mime::Type.lookup_by_extension($1)
accepts = [format.to_s, request.env["HTTP_ACCEPT"]].compact
request.env["HTTP_ACCEPT"] = accepts.join(",")
request.env["HTTP_ACCEPT"].gsub!(/,\s*\*\/\*(\;q=\d\.\d)?|\*\/\*\s*(\;q=\d\.\d),/, "")
else
raise UnknownFormatError, "Unknown format extension: #{$1}"
end
end
request.route = route
return request
end
end
end
class Storage::Nodes::BaseStore
protected
# Iterates over the path segments to find the nodes
# @param [Model] root node
# @param [String] path to find
# @return [Array<Model>] array of node Models
# @see Rack::Request::ClassMethods#path_segments
def find_nodes_for_path(root, path)
raise(NotFoundError, "Root path not found") if root.nil?
[root].tap do |result|
::Rack::Request.each_path_segment(path) do |segment|
next if segment.blank?
segment.gsub!(FORMAT_EXT_REGEXP, "") if segment.last?
if node = result.last.find_child_by_segment(segment)
result << node
elsif result.last.finite?
return nil
else
break
end
end
end
end
end
end
Rack::Request.send(:extend, Circuit::Rack::Request::ClassMethodsExt)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment