module Roda::RodaPlugins::Path::ClassMethods

def path(name, path=nil, opts=OPTS, &block)

Create a new instance method for the named path. See plugin module documentation for options.
def path(name, path=nil, opts=OPTS, &block)
  if name.is_a?(Class) || (path.is_a?(Hash) && (class_name = path[:class_name]))
    raise RodaError, "can't provide path when calling path with a class" if path && !class_name
    raise RodaError, "can't provide options when calling path with a class" unless opts.empty?
    raise RodaError, "must provide a block when calling path with a class" unless block
    if self.opts[:path_class_by_name]
      if class_name
        name = name.to_s
      else
        name = name.name
      end
    elsif class_name
      name = name.to_s
      raise RodaError, "invalid class name passed when using class_name option" unless VALID_CONSTANT_NAME_REGEXP =~ name
      name = Object.class_eval(name, __FILE__, __LINE__)
    end
    path_classes[name] = block
    self.opts[:path_class_methods][name] = define_roda_method("path_#{name}", :any, &block)
    return
  end
  if path.is_a?(Hash)
    raise RodaError,  "cannot provide two option hashses to Roda.path" unless opts.empty?
    opts = path
    path = nil
  end
  raise RodaError,  "cannot provide both path and block to Roda.path" if path && block
  raise RodaError,  "must provide either path or block to Roda.path" unless path || block
  if path
    path = path.dup.freeze
    block = lambda{path}
  end
  meth = opts[:name] || "#{name}_path"
  url = opts[:url]
  url_only = opts[:url_only]
  relative = opts[:relative]
  add_script_name = opts.fetch(:add_script_name, self.opts[:add_script_name])
  if relative
    if (url || url_only)
      raise RodaError,  "cannot provide :url or :url_only option if using :relative option"
    end
    add_script_name = true
    plugin :relative_path
  end
  if add_script_name || url || url_only || relative
    _meth = "_#{meth}"
    define_method(_meth, &block)
    private _meth
  end
  unless url_only
    if relative
      define_method(meth) do |*a, &blk|
        # Allow calling private _method to get path
        relative_path(request.script_name.to_s + send(_meth, *a, &blk))
      end
      # :nocov:
      ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
      # :nocov:
    elsif add_script_name
      define_method(meth) do |*a, &blk|
        # Allow calling private _method to get path
        request.script_name.to_s + send(_meth, *a, &blk)
      end
      # :nocov:
      ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
      # :nocov:
    else
      define_method(meth, &block)
    end
  end
  if url || url_only
    url_meth = if url.is_a?(String) || url.is_a?(Symbol)
      url
    else
      "#{name}_url"
    end
    url_block = lambda do |*a, &blk|
      # Allow calling private _method to get path
      "#{_base_url}#{request.script_name if add_script_name}#{send(_meth, *a, &blk)}"
    end
    define_method(url_meth, &url_block)
    # :nocov:
    ruby2_keywords(url_meth) if respond_to?(:ruby2_keywords, true)
    # :nocov:
  end
  nil
end