class Rad::Router::AliasRouter include Rad::Router::AbstractRouter class TreeHash < Hash attr_accessor :meta end def initialize @route_methods, @paths, @classes = {}, TreeHash.new, {} end def add als, options = {} # parsing options # als, options = als.to_s, options.to_openobject options.validate_options! :class_name, :method, :url_root, :prefix als = als.to_s als.must =~ /^\// class_name = options.delete(:class_name) || raise("no class name!") class_name.must_be.a String method = options.delete(:method) || raise("no method!") method = method.must_be.a Symbol url_root = parse_url_root options prefix = parse_prefix options raise "you can't use '/' alias with :url_root!" if als == '/' and url_root # logic meta = Meta.new meta.merge!( class_name: class_name, method: method, path: als, url_root: url_root, prefix: prefix ) route_methods["#{als[1..-1]}_path"] = meta (classes[class_name] ||= {})[method] = meta parts = als[1..-1].split('/') parts << '' if parts.empty? tree_iterator = paths parts.reverse.each do |part| tree_iterator = (tree_iterator[part] ||= TreeHash.new) raise "alias '#{als}' conflicted with another alias ('#{tree_iterator.meta[:path]}')!" if tree_iterator.meta end tree_iterator.meta = meta end def encode klass, method, params if meta = classes[klass.name].try(:[], method) path = meta[:path] # prefix prefix = meta[:prefix] path = encode_prefix_params! path, params, prefix if prefix url_root = meta[:url_root] params[:url_root] = url_root if url_root return path, params else nil end end def decode path, params parts = path[1..-1].split('/') parts << '' if parts.empty? tree_iterator = paths # checking for first part part = parts.pop tree_iterator = tree_iterator[part] return nil unless tree_iterator # checking for exact match while part = parts.pop tmp = tree_iterator[part] unless tmp parts << part break end tree_iterator = tmp end meta = tree_iterator.meta # url_root url_root = meta[:url_root] return nil if url_root and "/#{parts.shift}" != url_root # prefix prefix = meta[:prefix] decode_prefix_params! parts, params, prefix if prefix return meta.get_class, meta[:method], params end def encode_method route_method, has_id if meta = route_methods[route_method] return meta.get_class, meta[:method] else nil end end protected attr_accessor :paths, :route_methods, :classes end Rad::Router::Configurator.class_eval do def alias *args, &block alias_router = @router.routers[:alias_router] raise "There's no AliasRouter (use config to add it)!" unless alias_router alias_router.add *args, &block end end