Skip to content

Commit

Permalink
Merge cbc4c3e into a905744
Browse files Browse the repository at this point in the history
  • Loading branch information
gregschmit committed Mar 29, 2021
2 parents a905744 + cbc4c3e commit aca82fa
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 42 deletions.
67 changes: 25 additions & 42 deletions lib/rest_framework/routers.rb
Expand Up @@ -6,7 +6,7 @@ class Mapper
# Internal helper to take extra_actions hash and convert to a consistent format.
protected def _parse_extra_actions(extra_actions)
return (extra_actions || {}).map do |k,v|
kwargs = {}
kwargs = {action: k}
path = k

# Convert structure to path/methods/kwargs.
Expand All @@ -25,11 +25,6 @@ class Mapper
path = v.delete(:path)
end

# Set the action to be the action key unless it's already defined.
if !kwargs[:action]
kwargs[:action] = k
end

# Pass any further kwargs to the underlying Rails interface.
kwargs = kwargs.merge(v)
elsif v.is_a?(Symbol) || v.is_a?(String)
Expand Down Expand Up @@ -77,6 +72,16 @@ class Mapper
return controller
end

# Interal interface for routing extra actions.
protected def _route_extra_actions(actions, &block)
actions.each do |action_config|
action_config[:methods].each do |m|
public_send(m, action_config[:path], **action_config[:kwargs])
end
yield if block_given?
end
end

# Internal core implementation of the `rest_resource(s)` router, both singular and plural.
# @param default_singular [Boolean] the default plurality of the resource if the plurality is
# not otherwise defined by the controller
Expand Down Expand Up @@ -105,28 +110,20 @@ class Mapper
end
resource_method = singular ? :resource : :resources

# call either `resource` or `resources`, passing appropriate modifiers
# Call either `resource` or `resources`, passing appropriate modifiers.
skip_undefined = kwargs.delete(:skip_undefined) || true
skip = controller_class.get_skip_actions(skip_undefined: skip_undefined)
public_send(resource_method, name, except: skip, **kwargs) do
if controller_class.respond_to?(:extra_member_actions)
member do
actions = self._parse_extra_actions(controller_class.extra_member_actions)
actions.each do |action_config|
action_config[:methods].each do |m|
public_send(m, action_config[:path], **action_config[:kwargs])
end
end
_route_extra_actions(actions)
end
end

collection do
actions = self._parse_extra_actions(controller_class.extra_actions)
actions.each do |action_config|
action_config[:methods].each do |m|
public_send(m, action_config[:path], **action_config[:kwargs])
end
end
_route_extra_actions(actions)
end

yield if block_given?
Expand All @@ -150,6 +147,7 @@ def rest_resources(*names, **kwargs, &block)
# Route a controller without the default resourceful paths.
def rest_route(name=nil, **kwargs, &block)
controller = kwargs.delete(:controller) || name
route_root_to = kwargs.delete(:route_root_to)
if controller.is_a?(Class)
controller_class = controller
else
Expand All @@ -162,42 +160,27 @@ def rest_route(name=nil, **kwargs, &block)
# Route actions using the resourceful router, but skip all builtin actions.
actions = self._parse_extra_actions(controller_class.extra_actions)
public_send(:resource, name, only: [], **kwargs) do
actions.each do |action_config|
action_config[:methods].each do |m|
public_send(m, action_config[:path], **action_config[:kwargs])
end
yield if block_given?
# Route a root for this resource.
if route_root_to
get '', action: route_root_to
end

_route_extra_actions(actions, &block)
end
end

# Route a controller's `#root` to '/' in the current scope/namespace, along with other actions.
# @param name [Symbol] the snake_case name of the controller
def rest_root(name=nil, **kwargs, &block)
# By default, use RootController#root.
root_action = kwargs.delete(:action) || :root
controller = kwargs.delete(:controller) || name || :root

# Route the root.
get name.to_s, controller: controller, action: root_action

# Route any additional actions.
controller_class = self._get_controller_class(controller, pluralize: false)
actions = self._parse_extra_actions(controller_class.extra_actions)
actions.each do |action_config|
# Add :action unless kwargs defines it.
unless action_config[:kwargs].key?(:action)
action_config[:kwargs][:action] = action_config[:path]
end
# Remove path if name is nil (routing to the root of current namespace).
unless name
kwargs[:path] = ''
end

action_config[:methods].each do |m|
public_send(
m,
File.join(name.to_s, action_config[:path].to_s),
controller: controller,
**action_config[:kwargs],
)
end
return rest_route(controller, route_root_to: root_action, **kwargs) do
yield if block_given?
end
end
Expand Down
6 changes: 6 additions & 0 deletions test/app/controllers/api1_controller.rb
Expand Up @@ -2,9 +2,15 @@
class Api1Controller < ApplicationController
include RESTFramework::BaseControllerMixin

self.extra_actions = {test: :get}

def root
api_response({message: "Welcome to your custom API1 root!"})
end

def test
api_response({message: "Test successful!"})
end
end

module Api1
Expand Down
7 changes: 7 additions & 0 deletions test/test/integration/api1_routing_test.rb
Expand Up @@ -10,6 +10,13 @@ def test_can_get_root
assert_response :success
end

def can_get_root_test
get '/api1/test'
assert_response :success
get '/api1/test.json'
assert_response :success
end

def test_can_get_things
get '/api1/things'
assert_response :success
Expand Down

0 comments on commit aca82fa

Please sign in to comment.