forked from reprah/grape-route-helpers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8f237b8
Showing
18 changed files
with
730 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.swp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Metrics/ClassLength: | ||
Max: 104 | ||
Enabled: false | ||
|
||
Metrics/MethodLength: | ||
Max: 21 | ||
Enabled: false | ||
|
||
Style/FileName: | ||
Enabled: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
MIT License (MIT) | ||
|
||
Copyright (c) 2015 Harper Henn | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# grape-route-helpers | ||
|
||
Provides named route helpers for Grape APIs, similar to Rails' route helpers. | ||
|
||
### Installation | ||
|
||
1.) Add the gem to your Gemfile if you're using Bundler. | ||
|
||
```bash | ||
$ bundle install grape-route-helpers | ||
``` | ||
|
||
Run `gem install grape-route-helpers` if you're not. | ||
|
||
2.) Require the gem after you `require 'grape'` in your application setup. | ||
|
||
```ruby | ||
require 'grape/route_helpers' | ||
``` | ||
|
||
### Usage examples | ||
|
||
* To see which methods correspond to which paths, and which options you can pass them: | ||
|
||
```bash | ||
$ rake grape:route_helpers | ||
``` | ||
|
||
* Use the methods inside your Grape API actions. Given this example API: | ||
|
||
```ruby | ||
class ExampleAPI < Grape::API | ||
version 'v1' | ||
prefix 'api' | ||
format 'json' | ||
|
||
get 'ping' do | ||
'pong' | ||
end | ||
|
||
resource :cats do | ||
get '/' do | ||
%w(cats cats cats) | ||
end | ||
|
||
route_param :id do | ||
get do | ||
'cat' | ||
end | ||
end | ||
end | ||
|
||
route :any, '*anything' do | ||
redirect_to api_v1_cats_path | ||
end | ||
end | ||
``` | ||
|
||
You'd have the following methods available inside your Grape API actions: | ||
|
||
```ruby | ||
# specifying the version when using Grape's "path" versioning strategy | ||
api_v1_ping_path # => '/api/v1/ping' | ||
|
||
# specifying the format | ||
api_v1_cats_path(format: 'xml') # => '/api/v1/cats.xml' | ||
|
||
# passing in values required to build a path | ||
api_v1_cats_path(id: 1) # => '/api/v1/cats/1' | ||
|
||
# catch-all paths have helpers | ||
api_v1_anything_path # => '/api/v1/*anything' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
$LOAD_PATH.unshift File.expand_path('lib') | ||
|
||
require 'grape/route_helpers' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
require File.join(Dir.pwd, 'lib', 'grape-route-helpers', 'version') | ||
|
||
Gem::Specification.new do |gem| | ||
gem.name = 'grape-route-helpers' | ||
gem.version = GrapeRouteHelpers::VERSION | ||
gem.licenses = ['MIT'] | ||
gem.summary = 'Route helpers for Grape' | ||
gem.description = 'Route helpers for Grape' | ||
gem.authors = ['Harper Henn'] | ||
gem.email = '[email protected]' | ||
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) | ||
gem.homepage = 'https://github.com/reprah/grape-route-helpers' | ||
|
||
gem.add_runtime_dependency 'grape' | ||
gem.add_runtime_dependency 'activesupport' | ||
gem.add_runtime_dependency 'rake' | ||
|
||
gem.add_development_dependency 'pry' | ||
gem.add_development_dependency 'rspec' | ||
gem.add_development_dependency 'rubocop' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
require 'grape' | ||
require 'active_support' | ||
require 'active_support/core_ext/class' | ||
|
||
require 'grape-route-helpers/decorated_route' | ||
require 'grape-route-helpers/named_route_matcher' | ||
require 'grape-route-helpers/all_routes' | ||
require 'grape-route-helpers/route_displayer' | ||
|
||
Grape::API.extend GrapeRouteHelpers::AllRoutes | ||
Grape::Endpoint.include GrapeRouteHelpers::NamedRouteMatcher |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module GrapeRouteHelpers | ||
# methods to extend Grape::API's behavior so it can get a | ||
# list of routes from all APIs and decorate them with | ||
# the DecoratedRoute class | ||
module AllRoutes | ||
def decorated_routes | ||
# memoize so that construction of decorated routes happens once | ||
@decorated_routes ||= all_routes.map { |r| DecoratedRoute.new(r) } | ||
end | ||
|
||
def all_routes | ||
subclasses.flat_map { |s| s.send(:prepare_routes) } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
module GrapeRouteHelpers | ||
# wrapper around Grape::Route that adds a helper method | ||
class DecoratedRoute | ||
attr_reader :route, :helper_names, :helper_arguments | ||
|
||
def initialize(route) | ||
@route = route | ||
@helper_names = [] | ||
@helper_arguments = required_helper_segments | ||
define_path_helpers | ||
end | ||
|
||
def define_path_helpers | ||
route_versions.each do |version| | ||
route_attributes = { version: version } | ||
method_name = path_helper_name(route_attributes) | ||
@helper_names << method_name | ||
define_path_helper(method_name, route_attributes) | ||
end | ||
end | ||
|
||
def define_path_helper(method_name, route_attributes) | ||
method_body = <<-RUBY | ||
def #{method_name}(attributes = {}) | ||
attrs = HashWithIndifferentAccess.new( | ||
#{route_attributes}.merge(attributes) | ||
) | ||
content_type = attrs.delete(:format) | ||
path = '/' + path_segments_with_values(attrs).join('/') | ||
extension = content_type ? '.' + content_type : '' | ||
path + extension | ||
end | ||
RUBY | ||
instance_eval method_body | ||
end | ||
|
||
def route_versions | ||
if route_version | ||
route_version.split('|') | ||
else | ||
[nil] | ||
end | ||
end | ||
|
||
def path_helper_name(opts = {}) | ||
segments = path_segments_with_values(opts) | ||
|
||
name = if segments.empty? | ||
'root' | ||
else | ||
segments.join('_') | ||
end | ||
name + '_path' | ||
end | ||
|
||
def segment_to_value(segment, opts = {}) | ||
options = HashWithIndifferentAccess.new( | ||
route_options.merge(opts) | ||
) | ||
|
||
if dynamic_segment?(segment) | ||
key = segment.slice(1..-1) | ||
options[key] | ||
else | ||
segment | ||
end | ||
end | ||
|
||
def path_segments_with_values(opts) | ||
segments = path_segments.map { |s| segment_to_value(s, opts) } | ||
segments.reject(&:blank?) | ||
end | ||
|
||
def path_segments | ||
pattern = %r{\(/?\.:format\)|/|\*} | ||
route_path.split(pattern).reject(&:blank?) | ||
end | ||
|
||
def dynamic_path_segments | ||
segments = path_segments.select do |segment| | ||
dynamic_segment?(segment) | ||
end | ||
segments.map { |s| s.slice(1..-1) } | ||
end | ||
|
||
def dynamic_segment?(segment) | ||
segment.start_with?(':') | ||
end | ||
|
||
def required_helper_segments | ||
segments_in_options = dynamic_path_segments.select do |segment| | ||
route_options[segment.to_sym] | ||
end | ||
dynamic_path_segments - segments_in_options | ||
end | ||
|
||
def optional_segments | ||
['format'] | ||
end | ||
|
||
def uses_segments_in_path_helper?(segments) | ||
requested = segments - optional_segments | ||
required = required_helper_segments | ||
|
||
if requested.empty? && required.empty? | ||
true | ||
else | ||
requested.all? do |segment| | ||
required.include?(segment) | ||
end | ||
end | ||
end | ||
|
||
# accessing underlying Grape::Route | ||
|
||
def route_path | ||
route.route_path | ||
end | ||
|
||
def route_options | ||
route.instance_variable_get(:@options) | ||
end | ||
|
||
def route_version | ||
route.route_version | ||
end | ||
|
||
def route_namespace | ||
route.route_namespace | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module GrapeRouteHelpers | ||
# methods to extend Grape::Endpoint so that calls | ||
# to unknown methods will look for a route with a matching | ||
# helper function name | ||
module NamedRouteMatcher | ||
def method_missing(method_id, *arguments) | ||
segments = arguments.first || {} | ||
|
||
route = Grape::API.decorated_routes.detect do |r| | ||
route_match?(r, method_id, segments) | ||
end | ||
|
||
if route | ||
route.send(method_id, *arguments) | ||
else | ||
super | ||
end | ||
end | ||
|
||
def route_match?(route, method_name, segments) | ||
return false unless route.respond_to?(method_name) | ||
fail ArgumentError, | ||
'Helper options must be a hash' unless segments.is_a?(Hash) | ||
requested_segments = segments.keys.map(&:to_s) | ||
route.uses_segments_in_path_helper?(requested_segments) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module GrapeRouteHelpers | ||
# class for displaying the path, helper method name, | ||
# and required arguments for every Grape::Route. | ||
class RouteDisplayer | ||
def route_attributes | ||
Grape::API.decorated_routes.map do |route| | ||
{ | ||
route_path: route.route_path, | ||
helper_names: route.helper_names, | ||
helper_arguments: route.helper_arguments | ||
} | ||
end | ||
end | ||
|
||
def display | ||
puts 'Path, Helper, Arguments' | ||
route_attributes.each do |attributes| | ||
print "#{attributes[:route_path]}," | ||
print "#{attributes[:helper_names]}," | ||
print "#{attributes[:helper_arguments]}" | ||
puts("\n") | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Gem version | ||
module GrapeRouteHelpers | ||
VERSION = '1.0.0' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require 'grape-route-helpers' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace :grape do | ||
desc 'Print route helper methods.' | ||
task routes: :environment do | ||
GrapeRouteHelpers::RouteDisplayer.new.display | ||
end | ||
end |
Oops, something went wrong.