class Rad::Router::RestfulRouter include Rad::Router::AbstractRouter def initialize @resources, @class_names = {}, {} end def add resource, options = {} # parsing options options.validate_options! :class_name, :url_root, :prefix resource = resource.to_s resource.must_not =~ /\// raise "resource should be in plural form!" unless resource.pluralize == resource class_name = options.delete(:class_name) || raise("no class name!") class_name.must_be.a String url_root = parse_url_root options prefix = parse_prefix options # logic meta = Meta.new meta.merge!( class_name: class_name, resource: resource, url_root: url_root, prefix: prefix ) resources.must_not.include(resource.pluralize) class_names.must_not.include(class_name) resources[resource.pluralize] = meta resources[resource.singularize] = meta class_names[class_name] = meta end def encode klass, method, params meta = class_names[klass.name] return nil unless meta path = if id = params.delete(:id) "/#{meta[:resource]}/#{id}/#{method}" else "/#{meta[:resource]}/#{method}" end 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 [path, params] end def decode path, params decode_as_object_resource(path, params) || decode_as_static_resource(path, params) end def encode_method route_method, has_id token = route_method.sub(/_path$/, '') resources.each do |name, meta| if i = token.rindex(name) route_method.size == i + name.size and route_method[(i-1)..(i-1)] == '_' return meta.get_class, route_method[0..(i-2)].to_sym end end return nil end protected attr_accessor :resources, :class_names def decode_as_object_resource path, params parts = path[1..-1].split('/') return nil unless parts.size >= 3 method, id, resource = parts.pop.to_sym, parts.pop, parts.pop meta = resources[resource] return nil unless meta # url_root url_root = meta[:url_root] return nil if url_root and "/#{parts.shift}" != url_root # prefix return nil if parts.size != (meta[:prefix] ? meta[:prefix].size : 0) prefix = meta[:prefix] decode_prefix_params! parts, params, prefix if prefix params[:id] = id return meta.get_class, method, params end def decode_as_static_resource path, params parts = path[1..-1].split('/') return nil unless parts.size >= 2 # method & class method, resource = parts.pop.to_sym, parts.pop meta = resources[resource] return nil unless meta # url_root url_root = meta[:url_root] return nil if url_root and "/#{parts.shift}" != url_root # prefix return nil if parts.size != (meta[:prefix] ? meta[:prefix].size : 0) prefix = meta[:prefix] decode_prefix_params! parts, params, prefix if prefix return meta.get_class, method, params end end Rad::Router::Configurator.class_eval do def resource *args, &block restful_router = @router.routers[:restful_router] raise "There's no RestfulRouter (use config to add it)!" unless restful_router restful_router.add *args, &block end end