class Radical::Router

Constants

ACTIONS
RESOURCE_ACTIONS

Attributes

routes[RW]

Public Class Methods

new() click to toggle source
# File lib/radical/router.rb, line 62
def initialize
  @routes = Hash.new { |hash, key| hash[key] = [] }
end

Public Instance Methods

add_resource(klass) click to toggle source
# File lib/radical/router.rb, line 78
def add_resource(klass)
  add_routes(klass, actions: RESOURCE_ACTIONS)
  add_resource_paths(klass)
end
add_resources(klass, parents: nil) click to toggle source
# File lib/radical/router.rb, line 84
def add_resources(klass, parents: nil)
  if parents
    parents.each do |scope|
      add_routes(klass, actions: ACTIONS, scope: scope)
      add_resources_paths(klass, scope: scope)
    end
  else
    add_routes(klass, actions: ACTIONS)
    add_resources_paths(klass)
  end
end
add_root(klass) click to toggle source
# File lib/radical/router.rb, line 72
def add_root(klass)
  add_routes(klass, name: '', actions: ACTIONS)
  add_root_paths(klass)
end
route(request, options: {}) click to toggle source
# File lib/radical/router.rb, line 97
def route(request, options: {})
  params = T.let({}, T.nilable(Hash))

  route = @routes[request.request_method].find do |r|
    params = request.path_info.match(r.first)&.named_captures
  end

  return Rack::Response.new('404 Not Found', 404) unless route

  klass, method = route.last

  params.each do |k, v|
    request.update_param(k, v)
  end

  instance = klass.new(request, options: options)

  response = instance.public_send(method)

  return response if response.is_a?(Rack::Response)

  body = instance.view(method.to_s)

  return Rack::Response.new(nil, 404) if body.nil?

  Rack::Response.new(body, 200, { 'Content-Type' => 'text/html' })
end
route_prefix(classes) click to toggle source
# File lib/radical/router.rb, line 67
def route_prefix(classes)
  classes.map(&:route_name).map { |n| "#{n}/:#{n}_id" }.join('/')
end

Private Instance Methods

add_resource_paths(klass) click to toggle source
# File lib/radical/router.rb, line 178
def add_resource_paths(klass)
  name = klass.route_name

  if %i[create show update destroy].any? { |method| klass.method_defined?(method) }
    Controller.define_method :"#{name}_path" do
      "/#{name}"
    end
  end

  if klass.method_defined?(:new)
    Controller.define_method :"new_#{name}_path" do
      "/#{name}/new"
    end
  end

  return unless klass.method_defined?(:edit)

  Controller.define_method :"edit_#{name}_path" do
    "/#{name}/edit"
  end
end
add_resources_paths(klass, scope: nil) click to toggle source
# File lib/radical/router.rb, line 201
def add_resources_paths(klass, scope: nil)
  path_name = klass.route_name
  scope_path_name = [scope&.route_name, klass.route_name].compact.join('_')
  name = klass.route_name

  if %i[index create show update destroy].any? { |method| klass.method_defined?(method) }
    if scope
      Controller.define_method :"#{scope_path_name}_path" do |parent|
        "/#{scope.route_name}/#{parent.id}/#{name}"
      end

      Controller.define_method :"#{path_name}_path" do |obj|
        "/#{name}/#{obj.id}"
      end
    else
      Controller.define_method :"#{path_name}_path" do |obj = nil|
        if obj
          "/#{name}/#{obj.id}"
        else
          "/#{name}"
        end
      end
    end
  end

  if klass.method_defined?(:new)
    if scope
      Controller.define_method :"new_#{scope_path_name}_path" do |parent|
        "/#{scope.route_name}/#{parent.id}/#{name}/new"
      end
    else
      Controller.define_method :"new_#{path_name}_path" do
        "/#{name}/new"
      end
    end
  end

  return unless klass.method_defined?(:edit)

  Controller.define_method :"edit_#{path_name}_path" do |obj|
    "/#{name}/#{obj.id}/edit"
  end
end
add_root_paths(klass) click to toggle source
# File lib/radical/router.rb, line 151
def add_root_paths(klass)
  route_name = klass.route_name

  if %i[index create show update destroy].any? { |method| klass.method_defined?(method) }
    Controller.define_method :"#{route_name}_path" do |obj = nil|
      if obj
        "/#{obj.id}"
      else
        '/'
      end
    end
  end

  if klass.method_defined?(:new)
    Controller.define_method :"new_#{route_name}_path" do
      '/new'
    end
  end

  return unless klass.method_defined?(:edit)

  Controller.define_method :"edit_#{route_name}_path" do |obj|
    "/#{obj.id}/edit"
  end
end
add_routes(klass, actions:, name: nil, scope: nil) click to toggle source
# File lib/radical/router.rb, line 128
def add_routes(klass, actions:, name: nil, scope: nil)
  name ||= klass.route_name

  actions.each do |method, http_method, suffix|
    next unless klass.method_defined?(method)

    path = if scope
             if %i[index new create].include?(method)
               "/#{scope.route_name}/:#{scope.route_name}_id/#{name}#{suffix}"
             else
               "/#{name}#{suffix}"
             end
           else
             "/#{name}#{suffix}"
           end

    path = Regexp.new("^#{path.gsub(/:(\w+)/, '(?<\1>[a-zA-Z0-9_]+)')}$").freeze

    @routes[http_method] << [path, [klass, method]]
  end
end