class Rad::Router inject workspace: :workspace attr_reader :routers, :format_processor attr_accessor :default_path, :default_method def initialize ( class_variable = :class, routers = [[:default_router, Rad::Router::SimpleRouter.new]], format_processor = Rad::Router::DefaultFormatProcessor.new ) @class_variable, @format_processor = class_variable, format_processor self.routers = routers end def routers= routers @routers = {} routers.each do |k, v| k.must_be.present v.must_be.present v.must.respond_to(:decode) v.must.respond_to(:encode) self.routers[k] = v end end def url_for *args if args.first.is_a?(Class) args.size.must_be.in 2..3 klass, method, options = args url_for_class(klass, method, (options || {})) else first = args.first.to_s if first =~ /^\// args.size.must_be.in 1..2 path, options = args url_for_path(path, (options || {})) # elsif full_url? first # args.size.must == 1 # return first elsif first =~ /^http:\/\// args.size.must_be.in 1..2 raise "can't use option with full url (#{first})" if args.size == 2 and !args.last.blank? first else args.size.must_be.in 1..2 method, options = args url_for_class(nil, method, (options || {})) end end end def decode path, params path.first.must == '/' # params = params.to_openobject path, format = format_processor.remove_format path if format_processor result = nil routers.each do |name, route| result = route.decode path, params break if result end raise "no route for '#{safe_workspace.path}' request!" unless result klass, method, params = result method ||= default_method params.must_be.defined method.must_be.a Symbol raise "invalid route! No method '#{method}' for #{klass}!" unless klass.instance_methods.include? method raise "invalid route! You try to call protected method '#{method}' for '#{path}'!" unless klass.public_instance_methods.include? method return klass, method, params end def encode klass, method, params = {} klass.must_be.defined method.must_be.a Symbol params = params.clone # method, params = method, params.to_openobject format = params.delete(:format) # raise "Invalid route! No method '#{method}' for #{klass}!" unless klass.method_defined? method # raise "Invalid route! You try to call protected method '#{method}' for '#{klass}'!" unless klass.method_defined? method inject_persistent_params! params result = nil routers.each do |name, route| result = route.encode klass, method, params break if result end raise "no route for '#{klass}.#{method}'!" unless result path, params = result path.must_be.defined params.must_be.defined path = format_processor.add_format path, format if format_processor and format return path, params end def encode_method route_method, has_id # method = method route_method.must_be.present result = nil routers.each do |name, route| result = route.respond_to :encode_method, route_method, has_id break if result end raise "no route for '#{route_method}' route method!" unless result klass, method = result klass.must_be.defined method.must_be.defined method.must =~ /^[_a-zA-Z0-9]+$/ return [klass, method] end cache_method_with_params_in_production :encode_method def persist_params &block if block before = safe_workspace.persist_params? begin safe_workspace[:persist_params] = true block.call ensure safe_workspace.delete :persist_params unless before end else safe_workspace[:persist_params] = true end end def dont_persist_params &block if block before = safe_workspace.persist_params? begin safe_workspace.delete :persist_params block.call ensure safe_workspace[:persist_params] = true if before end else safe_workspace.delete :persist_params end end def persist_params? safe_workspace.persist_params? end def persistent_params; @persistent_params ||= [] end def url_for_path path, params # if full_url? path # params.must_be.blank # return path # end # params = params.to_openobject # url_root = params.include?(:url_root) ? params.delete(:url_root) : config.url_root! # if !url_root or url_root == '/' # url = path.clone # else # url = url_root + path # end # url_root url_root = params.delete(:url_root) url = (url_root && url_root != '/') ? url_root + path : path.clone # host port host, port = params.delete(:host), params.delete(:port) format = params.delete(:format) # json params = {json: params.to_json} if params.delete :as_json #and !params.empty? # format if format params[:format] = format url.marks.format = format.to_s end # Delete 'nil' parameters to_delete = [] params.each{|k, v| to_delete << k if v.nil?} to_delete.each{|k| params.delete k} # build url delimiter = path.include?('?') ? '&' : '?' url << "#{delimiter}#{params.to_query}" unless params.empty? if host.blank? url else %{http://#{host}#{":#{port}" unless port.blank?}#{url}} end end def url_for_class klass, method, params klass ||= current_class # params = params.to_openobject # special params format = params[:format] path, params = encode klass, method, params url = url_for_path path, params url.marks.format = format.to_s if format url end # # public helpers for :router component # delegate :configure, to: Rad::Router::Configurator protected # def full_url? url # url =~ /[a-z0-9]+:\/\// # end # sometimes we need access to routers outside of conveyor :cycle, # for example in spec routing helpers, in that case we just ignore workspace and it's variables def safe_workspace if rad.active? :cycle workspace else Rad::Conveyors::Workspace.new end end def current_class; safe_workspace[@class_variable] end DONOT_PERSIST = [:_, :_method, :_target] def inject_persistent_params! params persist = params.delete(:persist) # global persistent params unless cached_global_persistend_params = safe_workspace.cached_global_persistend_params cached_global_persistend_params, workspace_params = {}, safe_workspace.params if workspace_params persistent_params.collect!{|k| k} workspace_params.each do |k, v| cached_global_persistend_params[k] = v if persistent_params.include?(k) end safe_workspace.cached_global_persistend_params = cached_global_persistend_params end end cached_global_persistend_params.each do |k, v| params[k] = v unless params.include? k end # underscored persistent params if persist_params? unless cached_persistend_params = safe_workspace.cached_persistend_params cached_persistend_params, workspace_params = {}, safe_workspace.params if workspace_params workspace_params.each do |k, v| cached_persistend_params[k] = v if (k =~ /^_/) and !DONOT_PERSIST.include?(k) end safe_workspace.cached_persistend_params = cached_persistend_params end end cached_persistend_params.each do |k, v| params[k] = v unless params.include? k end end end end