grape-route-helpers-2.1.0/0000755000175000017500000000000013147455765014451 5ustar pravipravigrape-route-helpers-2.1.0/CHANGELOG.md0000644000175000017500000000214113147455765016260 0ustar pravipravi# Changelog ## December 17 2016 * Bump to 2.1.0 * Fix bug that caused POST routes to be ignored if more than one was defined * Many thanks to @njd5475 for the bug report and pull request that helped me write this ## April 28 2016 * Release 2.0.0 * Fix incompatibility between grape-route-helpers and grape 0.16.0 ## April 11 2016 * Release 1.2.2 * Fixed incompatibility between grape-route-helpers and Ruby 2.3 by merging PR #8 from phallguy ## October 11 2015 * Release 1.2.1 * Fixed issue #4 ## September 27 2015 * Release 1.2.0 * You can now assign custom helper names to Grape routes * Fixed a bug where routes would be listed more than once in the rake task if they are mounted to another API * Added the HTTP verb to rake task output ## July 5 2015 * You can now pass query parameters to helper functions in order to generate your own query string (Issue #1) ## June 28 2015 Release 1.0.1 * Rename rake task from `grape:routes` to `grape:route_helpers` * If a Grape::Route has a specific format (json, etc.) in its route_path attribute, the helper will return a path with this extension at the end grape-route-helpers-2.1.0/Gemfile.lock0000644000175000017500000000451113147455765016674 0ustar pravipraviPATH remote: . specs: grape-route-helpers (2.1.0) activesupport grape (>= 0.16.0) rake GEM remote: https://rubygems.org/ specs: activesupport (4.2.6) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) ast (2.0.0) astrolabe (1.3.0) parser (>= 2.2.0.pre.3, < 3.0) axiom-types (0.1.1) descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) builder (3.2.2) coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) diff-lcs (1.2.5) enumerable-lazy (0.0.1) equalizer (0.0.11) grape (0.16.2) activesupport builder hashie (>= 2.1.0) multi_json (>= 1.3.2) multi_xml (>= 0.5.2) mustermann19 (~> 0.4.3) rack (>= 1.3.0) rack-accept virtus (>= 1.0.0) hashie (3.4.3) i18n (0.7.0) ice_nine (0.11.2) json (1.8.3) method_source (0.8.2) minitest (5.8.4) multi_json (1.11.3) multi_xml (0.5.5) mustermann19 (0.4.3) enumerable-lazy parser (2.3.0.pre.2) ast (>= 1.1, < 3.0) powerpack (0.1.1) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) rack (1.6.4) rack-accept (0.4.5) rack (>= 0.4) rainbow (2.0.0) rake (10.4.2) rspec (3.3.0) rspec-core (~> 3.3.0) rspec-expectations (~> 3.3.0) rspec-mocks (~> 3.3.0) rspec-core (3.3.1) rspec-support (~> 3.3.0) rspec-expectations (3.3.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.3.0) rspec-mocks (3.3.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.3.0) rspec-support (3.3.0) rubocop (0.32.1) astrolabe (~> 1.3) parser (>= 2.2.2.5, < 3.0) powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) ruby-progressbar (~> 1.4) ruby-progressbar (1.7.5) slop (3.6.0) thread_safe (0.3.5) tzinfo (1.2.2) thread_safe (~> 0.1) virtus (1.0.5) axiom-types (~> 0.1) coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) equalizer (~> 0.0, >= 0.0.9) PLATFORMS ruby DEPENDENCIES grape-route-helpers! pry rspec rubocop BUNDLED WITH 1.11.2 grape-route-helpers-2.1.0/README.md0000644000175000017500000000714713147455765015741 0ustar pravipravi# grape-route-helpers [![Build Status](https://travis-ci.org/reprah/grape-route-helpers.svg)](https://travis-ci.org/reprah/grape-route-helpers) Provides named route helpers for Grape APIs, similar to [Rails' route helpers](http://edgeguides.rubyonrails.org/routing.html#path-and-url-helpers). ### Installation #### Compatibility with Grape If you're using grape 0.16.0 or higher, you'll need version 2.0.0 or higher of grape-route-helpers. #### Rails 1.) Add the gem to your Gemfile. ```bash $ bundle install grape-route-helpers ``` #### Sinatra/Rack 1.) Add the gem to your Gemfile if you're using Bundler. If you're not using Bundler to install/manage dependencies: ```bash $ gem install grape-route-helpers ``` ```ruby # environment setup file require 'grape' require 'grape/route_helpers' ``` 2.) Write a rake task called `:environment` that loads the application's environment first. This gem's tasks are dependent on it. You could put this in the root of your project directory: ```ruby # Rakefile require 'rake' require 'bundler' Bundler.setup require 'grape-route-helpers' require 'grape-route-helpers/tasks' desc 'load the Sinatra environment.' task :environment do require File.expand_path('your_app_file', File.dirname(__FILE__)) end ``` ### Usage #### List All Helper Names To see which methods correspond to which paths, and which options you can pass them: ```bash # In your API root directory, at the command line $ rake grape:route_helpers ``` #### Use Helpers in IRB/Pry You can use helper methods in your REPL session by including a module: ```ruby [1] pry(main)> include GrapeRouteHelpers::NamedRouteMatcher ``` #### Use Helpers in Your API 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 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.json' # specifying the format api_v1_cats_path(format: '.xml') # => '/api/v1/cats.xml' # adding a query string api_v1_cats_path(params: { sort_by: :age }) # => '/api/v1/cats?sort_by=age' # passing in values required to build a path api_v1_cats_path(id: 1) # => '/api/v1/cats/1.json' # catch-all paths have helpers api_v1_anything_path # => '/api/v1/*anything' ``` #### Custom Helper Names If you want to assign a custom helper name to a route, pass the `:as` option when creating your route in your API: ```ruby class Base < Grape::API get 'ping', as: 'is_the_server_running' 'pong' end end ``` This results in creating a helper called `is_the_server_running_path`. #### Testing You can use route helpers in your API tests by including the `GrapeRouteHelpers::NamedRouteMatcher` module inside your specs. Here's an example: ```ruby require 'spec_helper' describe Api::Base do include GrapeRouteHelpers::NamedRouteMatcher describe 'GET /ping' do it 'returns a 200 OK' do get api_v2_ping_path expect(response.status).to be(200) end end end ``` ### Contributing 1.) Fork it 2.) Create your feature branch `(git checkout -b my-new-feature)` 3.) Write specs for your feature 4.) Commit your changes `(git commit -am 'Add some feature')` 5.) Push to the branch `(git push origin my-new-feature)` 6.) Create a new pull request ### License See LICENSE grape-route-helpers-2.1.0/.rubocop.yml0000644000175000017500000000020413147455765016717 0ustar pravipraviMetrics/ClassLength: Max: 104 Enabled: false Metrics/MethodLength: Max: 21 Enabled: false Style/FileName: Enabled: false grape-route-helpers-2.1.0/grape-route-helpers.gemspec0000644000175000017500000000142613147455765021713 0ustar pravipravirequire 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 = 'harper.henn@legitscript.com' gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) gem.homepage = 'https://github.com/reprah/grape-route-helpers' gem.add_runtime_dependency 'grape', '>= 0.16.0' 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 grape-route-helpers-2.1.0/lib/0000755000175000017500000000000013147455765015217 5ustar pravipravigrape-route-helpers-2.1.0/lib/grape/0000755000175000017500000000000013147455765016315 5ustar pravipravigrape-route-helpers-2.1.0/lib/grape/route_helpers.rb0000644000175000017500000000003613147455765021521 0ustar pravipravirequire 'grape-route-helpers' grape-route-helpers-2.1.0/lib/grape-route-helpers.rb0000644000175000017500000000073113147455765021437 0ustar pravipravirequire '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' # module GrapeRouteHelpers require 'grape-route-helpers/railtie' if defined?(Rails) end Grape::API.extend GrapeRouteHelpers::AllRoutes Grape::Endpoint.send(:include, GrapeRouteHelpers::NamedRouteMatcher) grape-route-helpers-2.1.0/lib/grape-route-helpers/0000755000175000017500000000000013147455765021111 5ustar pravipravigrape-route-helpers-2.1.0/lib/grape-route-helpers/all_routes.rb0000644000175000017500000000101613147455765023605 0ustar pravipravimodule 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 routes = subclasses.flat_map { |s| s.send(:prepare_routes) } routes.uniq { |r| r.options.merge(path: r.path) } end end end grape-route-helpers-2.1.0/lib/grape-route-helpers/tasks.rb0000644000175000017500000000011613147455765022561 0ustar pravipraviDir[File.join(File.dirname(__FILE__), '../tasks/*.rake')].each { |f| load f } grape-route-helpers-2.1.0/lib/grape-route-helpers/named_route_matcher.rb0000644000175000017500000000155513147455765025451 0ustar pravipravimodule 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) super unless method_id.to_s.match(/_path$/) 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 grape-route-helpers-2.1.0/lib/grape-route-helpers/railtie.rb0000644000175000017500000000031213147455765023063 0ustar pravipravimodule GrapeRouteHelpers # class Railtie < Rails::Railtie rake_tasks do files = File.join(File.dirname(__FILE__), '../tasks/*.rake') Dir[files].each { |f| load f } end end end grape-route-helpers-2.1.0/lib/grape-route-helpers/route_displayer.rb0000644000175000017500000000165713147455765024661 0ustar pravipravimodule 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, route_method: route.route_method, helper_names: route.helper_names, helper_arguments: route.helper_arguments } end end def display puts("== GRAPE ROUTE HELPERS ==\n\n") route_attributes.each do |attributes| printf("%s: %s\n", 'Verb', attributes[:route_method]) printf("%s: %s\n", 'Path', attributes[:route_path]) printf("%s: %s\n", 'Helper Method', attributes[:helper_names].join(', ')) printf("%s: %s\n", 'Arguments', attributes[:helper_arguments].join(', ')) puts("\n") end end end end grape-route-helpers-2.1.0/lib/grape-route-helpers/decorated_route.rb0000644000175000017500000000742513147455765024616 0ustar pravipravimodule GrapeRouteHelpers # wrapper around Grape::Route that adds a helper method class DecoratedRoute attr_reader :route, :helper_names, :helper_arguments, :extension, :route_options def self.sanitize_method_name(string) string.gsub(/\W|^[0-9]/, '_') end def initialize(route) @route = route @route_options = route.options @helper_names = [] @helper_arguments = required_helper_segments @extension = default_extension define_path_helpers end def default_extension pattern = /\((\.\:?\w+)\)$/ match = route_path.match(pattern) return '' unless match ext = match.captures.first if ext == '.:format' '' else ext end end def define_path_helpers route_versions.each do |version| route_attributes = { version: version, format: extension } 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) ) query_params = attrs.delete(:params) content_type = attrs.delete(:format) path = '/' + path_segments_with_values(attrs).join('/') path + content_type + query_string(query_params) end RUBY instance_eval method_body end def query_string(params) if params.nil? '' else '?' + params.to_param end end def route_versions version_pattern = /[^\[",\]\s]+/ if route_version route_version.scan(version_pattern) else [nil] end end def path_helper_name(opts = {}) if route_options[:as] name = route_options[:as].to_s else segments = path_segments_with_values(opts) name = if segments.empty? 'root' else segments.join('_') end end sanitized_name = self.class.sanitize_method_name(name) sanitized_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{\(/?\.:?\w+\)|/|\*} 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 special_keys %w(format params) end def uses_segments_in_path_helper?(segments) segments = segments.reject { |x| special_keys.include?(x) } if required_helper_segments.empty? && segments.any? false else required_helper_segments.all? { |x| segments.include?(x) } end end def route_path route.path end def route_version route.version end def route_namespace route.namespace end def route_method route.request_method end end end grape-route-helpers-2.1.0/lib/grape-route-helpers/version.rb0000644000175000017500000000007713147455765023127 0ustar pravipravi# Gem version module GrapeRouteHelpers VERSION = '2.1.0' end grape-route-helpers-2.1.0/lib/tasks/0000755000175000017500000000000013147455765016344 5ustar pravipravigrape-route-helpers-2.1.0/lib/tasks/grape_route_helpers.rake0000644000175000017500000000023313147455765023244 0ustar pravipravinamespace :grape do desc 'Print route helper methods.' task route_helpers: :environment do GrapeRouteHelpers::RouteDisplayer.new.display end end grape-route-helpers-2.1.0/.travis.yml0000644000175000017500000000031313147455765016557 0ustar pravipravilanguage: ruby cache: bundler rvm: - ruby-head - 2.3.0 - 2.2.0 - 2.1.0 - 2.0.0 - 1.9.3 - jruby-19mode - jruby-head matrix: allow_failures: - rvm: ruby-head - rvm: jruby-head grape-route-helpers-2.1.0/LICENSE.txt0000644000175000017500000000206313147455765016275 0ustar pravipraviMIT 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. grape-route-helpers-2.1.0/.gitignore0000644000175000017500000000003213147455765016434 0ustar pravipravi*.swp *.gem .ruby-version grape-route-helpers-2.1.0/Rakefile0000644000175000017500000000051313147455765016115 0ustar pravipravirequire 'rubygems' require 'bundler' Bundler.setup :default, :test, :development Bundler::GemHelper.install_tasks require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |spec| spec.pattern = 'spec/**/*_spec.rb' end task :spec require 'rainbow/ext/string' unless String.respond_to?(:color) task default: [:spec] grape-route-helpers-2.1.0/Gemfile0000644000175000017500000000004713147455765015745 0ustar pravipravisource 'https://rubygems.org' gemspec grape-route-helpers-2.1.0/spec/0000755000175000017500000000000013147455765015403 5ustar pravipravigrape-route-helpers-2.1.0/spec/spec_helper.rb0000644000175000017500000000027313147455765020223 0ustar pravipravi$LOAD_PATH.unshift File.expand_path('lib') require 'pry' require 'grape/route_helpers' support_files = Dir.glob('spec/support/*') support_files.each { |f| require File.expand_path(f) } grape-route-helpers-2.1.0/spec/grape_route_helpers/0000755000175000017500000000000013147455765021441 5ustar pravipravigrape-route-helpers-2.1.0/spec/grape_route_helpers/all_routes_spec.rb0000644000175000017500000000202413147455765025147 0ustar pravipravirequire 'spec_helper' describe GrapeRouteHelpers::AllRoutes do Grape::API.extend described_class describe '#all_routes' do context 'when API is mounted within another API' do let(:mounting_api) { Spec::Support::MountedAPI } it 'does not include the same route twice' do mounting_api # A route is unique if no other route shares the same set of options all_route_options = Grape::API.all_routes.map do |r| r.instance_variable_get(:@options).merge(path: r.path) end duplicates = all_route_options.select do |o| all_route_options.count(o) > 1 end expect(duplicates).to be_empty end end context 'when there are multiple POST routes with the same namespace in the same API' do it 'returns all POST routes' do expected_routes = Spec::Support::MultiplePostsAPI.routes.map(&:path) all_routes = Grape::API.all_routes expect(all_routes.map(&:path)).to include(*expected_routes) end end end end grape-route-helpers-2.1.0/spec/grape_route_helpers/decorated_route_spec.rb0000644000175000017500000001566613147455765026166 0ustar pravipravirequire 'spec_helper' describe GrapeRouteHelpers::DecoratedRoute do let(:api) { Spec::Support::API } let(:routes) do api.routes.map do |route| described_class.new(route) end end let(:index_route) do routes.detect { |route| route.route_namespace == '/cats' } end let(:show_route) do routes.detect { |route| route.route_namespace == '/cats/:id' } end let(:catch_all_route) do routes.detect { |route| route.route_path =~ /\*/ } end let(:custom_route) do routes.detect { |route| route.route_path =~ /custom_name/ } end let(:ping_route) do routes.detect { |route| route.route_path =~ /ping/ } end describe '#sanitize_method_name' do it 'removes characters that are illegal in Ruby method names' do illegal_names = ['beta-1', 'name_with_+', 'name_with_('] sanitized = illegal_names.map do |name| described_class.sanitize_method_name(name) end expect(sanitized).to match_array(%w(beta_1 name_with__ name_with__)) end it 'only replaces integers if they appear at the beginning' do illegal_name = '1' legal_name = 'v1' expect(described_class.sanitize_method_name(illegal_name)).to eq('_') expect(described_class.sanitize_method_name(legal_name)).to eq('v1') end end describe '#helper_names' do context 'when a route is given a custom helper name' do it 'uses the custom name instead of the dynamically generated one' do expect(custom_route.helper_names.first) .to eq('my_custom_route_name_path') end it 'returns the correct path' do expect( custom_route.my_custom_route_name_path ).to eq('/api/v1/custom_name.json') end end context 'when an API has multiple POST routes in a resource' do let(:api) { Spec::Support::MultiplePostsAPI } it 'it creates a helper for each POST route' do expect(routes.size).to eq(2) end end context 'when an API has multiple versions' do let(:api) { Spec::Support::APIWithMultipleVersions } it "returns the route's helper name for each version" do helper_names = ping_route.helper_names expect(helper_names.size).to eq(api.version.size) end end context 'when an API has one version' do it "returns the route's helper name for that version" do helper_name = show_route.helper_names.first expect(helper_name).to eq('api_v1_cats_path') end end end describe '#helper_arguments' do context 'when no user input is needed to generate the correct path' do it 'returns an empty array' do expect(index_route.helper_arguments).to eq([]) end end context 'when user input is needed to generate the correct path' do it 'returns an array of required segments' do expect(show_route.helper_arguments).to eq(['id']) end end end describe '#path_segments_with_values' do context 'when path has dynamic segments' do it 'replaces segments with corresponding values found in @options' do opts = { id: 1 } result = show_route.path_segments_with_values(opts) expect(result).to include(1) end context 'when options contains string keys' do it 'replaces segments with corresponding values found in the options' do opts = { 'id' => 1 } result = show_route.path_segments_with_values(opts) expect(result).to include(1) end end end end describe '#path_helper_name' do it "returns the name of a route's helper method" do expect(index_route.path_helper_name).to eq('api_v1_cats_path') end context 'when the path is the root path' do let(:api_with_root) do Class.new(Grape::API) do get '/' do end end end let(:root_route) do grape_route = api_with_root.routes.first described_class.new(grape_route) end it 'returns "root_path"' do result = root_route.path_helper_name expect(result).to eq('root_path') end end context 'when the path is a catch-all path' do it 'returns a name without the glob star' do result = catch_all_route.path_helper_name expect(result).to eq('api_v1_path_path') end end end describe '#segment_to_value' do context 'when segment is dynamic' do it 'returns the value the segment corresponds to' do result = index_route.segment_to_value(':version') expect(result).to eq('v1') end context 'when segment is found in options' do it 'returns the value found in options' do options = { id: 1 } result = show_route.segment_to_value(':id', options) expect(result).to eq(1) end end end context 'when segment is static' do it 'returns the segment' do result = index_route.segment_to_value('api') expect(result).to eq('api') end end end describe 'path helper method' do context 'when given a "params" key' do context 'when value under "params" key is a hash' do it 'creates a query string' do query = { foo: :bar, baz: :zot } path = index_route.api_v1_cats_path(params: query) expect(path).to eq('/api/v1/cats.json?' + query.to_param) end end context 'when value under "params" is not a hash' do it 'coerces the value into a string' do path = index_route.api_v1_cats_path(params: 1) expect(path).to eq('/api/v1/cats.json?1') end end end # handle different Grape::Route#route_path formats in Grape 0.12.0 context 'when route_path contains a specific format' do it 'returns the correct path with the correct format' do path = index_route.api_v1_cats_path expect(path).to eq('/api/v1/cats.json') end end context 'when helper does not require arguments' do it 'returns the correct path' do path = index_route.api_v1_cats_path expect(path).to eq('/api/v1/cats.json') end end context 'when arguments are needed required to construct the right path' do context 'when not missing arguments' do it 'returns the correct path' do path = show_route.api_v1_cats_path(id: 1) expect(path).to eq('/api/v1/cats/1.json') end end end context "when a route's API has multiple versions" do let(:api) { Spec::Support::APIWithMultipleVersions } it 'returns a path for each version' do expect(ping_route.alpha_ping_path).to eq('/alpha/ping') expect(ping_route.beta_ping_path).to eq('/beta/ping') expect(ping_route.v1_ping_path).to eq('/v1/ping') end end context 'when a format is given' do it 'returns the path with a correct extension' do path = show_route.api_v1_cats_path(id: 1, format: '.xml') expect(path).to eq('/api/v1/cats/1.xml') end end end end grape-route-helpers-2.1.0/spec/grape_route_helpers/named_route_matcher_spec.rb0000644000175000017500000001124013147455765027003 0ustar pravipravirequire 'spec_helper' describe GrapeRouteHelpers::NamedRouteMatcher do include described_class let(:routes) do Grape::API.decorated_routes end let(:ping_route) do routes.detect do |route| route.route_path =~ /ping/ && route.route_version == 'v1' end end let(:index_route) do routes.detect do |route| route.route_namespace =~ /cats$/ end end let(:show_route) do routes.detect do |route| route.route_namespace =~ %r{cats/:id} end end describe '#route_match?' do context 'when route responds to a method name' do let(:route) { ping_route } let(:method_name) { :api_v1_ping_path } let(:segments) { {} } context 'when segments is not a hash' do it 'raises an ArgumentError' do expect do route_match?(route, method_name, 1234) end.to raise_error(ArgumentError) end end it 'returns true' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(true) end context 'when requested segments contains expected options' do let(:segments) { { 'format' => 'xml' } } it 'returns true' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(true) end context 'when no dynamic segments are requested' do context 'when the route requires dynamic segments' do let(:route) { show_route } let(:method_name) { :ap1_v1_cats_path } it 'returns false' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(false) end end context 'when the route does not require dynamic segments' do it 'returns true' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(true) end end end context 'when route requires the requested segments' do let(:route) { show_route } let(:method_name) { :api_v1_cats_path } let(:segments) { { id: 1 } } it 'returns true' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(true) end end context 'when route does not require the requested segments' do let(:segments) { { some_option: 'some value' } } it 'returns false' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(false) end end end context 'when segments contains unexpected options' do let(:segments) { { some_option: 'some value' } } it 'returns false' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(false) end end end context 'when route does not respond to a method name' do let(:method_name) { :some_other_path } let(:route) { ping_route } let(:segments) { {} } it 'returns false' do is_match = route_match?(route, method_name, segments) expect(is_match).to eq(false) end end end describe '#method_missing' do context 'when method name matches a Grape::Route path helper name' do it 'returns the path for that route object' do path = api_v1_ping_path expect(path).to eq('/api/v1/ping.json') end context 'when argument to the helper is not a hash' do it 'raises an ArgumentError' do expect do api_v1_ping_path(1234) end.to raise_error(ArgumentError) end end end context 'when method name does not match a Grape::Route path helper name' do it 'raises a NameError' do expect do some_method_name end.to raise_error(NameError) end end end context 'when Grape::Route objects share the same helper name' do context 'when helpers require different segments to generate their path' do it 'uses arguments to infer which route to use' do show_path = api_v1_cats_path('id' => 1) expect(show_path).to eq('/api/v1/cats/1.json') index_path = api_v1_cats_path expect(index_path).to eq('/api/v1/cats.json') end end context 'when query params are passed in' do it 'uses arguments to infer which route to use' do show_path = api_v1_cats_path('id' => 1, params: { 'foo' => 'bar' }) expect(show_path).to eq('/api/v1/cats/1.json?foo=bar') index_path = api_v1_cats_path(params: { 'foo' => 'bar' }) expect(index_path).to eq('/api/v1/cats.json?foo=bar') end end end end grape-route-helpers-2.1.0/spec/support/0000755000175000017500000000000013147455765017117 5ustar pravipravigrape-route-helpers-2.1.0/spec/support/api.rb0000644000175000017500000000234513147455765020221 0ustar pravipravimodule Spec module Support # Test API class API < Grape::API version 'v1' prefix 'api' format 'json' get 'custom_name', as: :my_custom_route_name do 'hello' end 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, '*path' do 'catch-all route' end end # API with more than one version class APIWithMultipleVersions < Grape::API version %w(beta alpha v1) get 'ping' do 'pong' end end # API with another API mounted inside it class MountedAPI < Grape::API mount Spec::Support::API mount Spec::Support::APIWithMultipleVersions end # API with a version that would be illegal as a method name class APIWithIllegalVersion < Grape::API version 'beta-1' get 'ping' do 'pong' end end # API with multiple POST routes class MultiplePostsAPI < Grape::API resource :hamlet do post 'to_be' do end post 'or_not_to_be' do end end end end end