Sha256: 7c7fc5904b38e0a336e0812676341856a272520783826e035a3f90c8aaa826d2

Contents?: true

Size: 1.92 KB

Versions: 8

Compression:

Stored size: 1.92 KB

Contents

require_relative "handler"
require_relative "errors"

module Coach
  class Router
    ACTION_TRAITS = {
      index:   { method: :get },
      show:    { method: :get, url: ':id' },
      create:  { method: :post },
      update:  { method: :put, url: ':id' },
      destroy: { method: :delete, url: ':id' }
    }.each_value(&:freeze).freeze

    def initialize(app)
      @app = app
    end

    def draw(routes, base: nil, as: nil, constraints: nil, actions: [])
      action_traits(actions).each do |action, traits|
        route = routes.const_get(camel(action))
        match(action_url(base, traits),
              to: Handler.new(route),
              via: traits[:method],
              as: as,
              constraints: constraints)
      end
    end

    def match(url, **args)
      @app.routes.draw do
        match url, args
      end
    end

    private

    # Receives an array of symbols that represent actions for which the default traits
    # should be used, and then lastly an optional trait configuration.
    #
    # Example is...
    #
    #   [ :index, :show, { refund: { url: ':id/refund', method: 'post' } } ]
    #
    # ...which will load the default route for `show` and `index`, while also configuring
    # a refund route.
    def action_traits(list_of_actions)
      if list_of_actions.last.is_a?(Hash)
        *list_of_actions, traits = list_of_actions
      end

      list_of_actions.reduce(traits || {}) do |memo, action|
        trait = ACTION_TRAITS.fetch(action) do
          raise Errors::RouterUnknownDefaultAction, action
        end

        memo.merge(action => trait)
      end
    end

    # Applies trait url to base, removing duplicate /'s
    def action_url(base, traits)
      [base, traits[:url]].compact.join('/').gsub(%r{/+}, '/')
    end

    # Turns a snake_case string/symbol into a CamelCase
    def camel(snake_case)
      snake_case.to_s.capitalize.gsub(/_./) { |match| match[1].upcase }
    end
  end
end

Version data entries

8 entries across 8 versions & 1 rubygems

Version Path
coach-0.3.0 lib/coach/router.rb
coach-0.2.3 lib/coach/router.rb
coach-0.2.2 lib/coach/router.rb
coach-0.2.1 lib/coach/router.rb
coach-0.2.0 lib/coach/router.rb
coach-0.0.2 lib/coach/router.rb
coach-0.0.1 lib/coach/router.rb
coach-0.0.0 lib/coach/router.rb