diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 03eadfa..cbfb87c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - ruby-version: ['2.5', '2.6', '2.7'] + ruby-version: ['2.6', '2.7', '3.0'] steps: - uses: actions/checkout@v3 @@ -19,5 +19,4 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true - name: Run tests - run: bundle exec rake - \ No newline at end of file + run: bundle exec rspec \ No newline at end of file diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..b3eb8b4 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..47c36d1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +### 1.1.0 (Next) + +#### Features + +* Your contribution here. + +#### Fixes + +* [#21](https://github.com/ruby-grape/mustermann-grape/pull/21): Introducing the `params` option to `Mustermann::Grape` to enhance matching by offering detailed information regarding the parameter types. - [@jcagarcia](https://github.com/jcagarcia). +* Your contribution here. \ No newline at end of file diff --git a/README.md b/README.md index c8ea566..c860815 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,17 @@ This gem implements the `grape` pattern type for Mustermann. ## Overview **Supported options:** -`capture`, `except`, `greedy`, `space_matches_plus`, `uri_decode`, `converters` and `ignore_unknown_options` +`capture`, `converters`, `except`, `greedy`, `ignore_unknown_options`, `params`, `space_matches_plus` and `uri_decode` ``` ruby require 'mustermann/grape' Mustermann.new('/:id', type: :grape).params('/foo') # => { id: 'foo' } + +# Providing params option +Mustermann.new('/:id', type: :grape, params: {"id"=>{:type=>"Integer"}}).params('/1') # => { id: '1'} +Mustermann.new('/:id', type: :grape, params: {"id"=>{:type=>"Integer"}}).params('/foo') # => nil +Mustermann.new('/:id', type: :grape, params: {"id"=>{:type=>"String"}}).params('/foo') # => { id: 'foo'} ``` ## Syntax diff --git a/lib/mustermann/grape.rb b/lib/mustermann/grape.rb index 036aa53..edd005d 100644 --- a/lib/mustermann/grape.rb +++ b/lib/mustermann/grape.rb @@ -13,11 +13,28 @@ module Mustermann # @see file:README.md#grape Syntax description in the README class Grape < AST::Pattern register :grape + supported_options :params on(nil, '?', ')') { |c| unexpected(c) } on('*') { |_c| scan(/\w+/) ? node(:named_splat, buffer.matched) : node(:splat) } - on(':') { |_c| node(:capture, constraint: "[^/\\?#\.]") { scan(/\w+/) } } + on(':') do |_c| + param_name = scan(/\w+/) + return node(:capture, param_name, constraint: "[^/\\?#\.]") { scan(/\w+/) } unless pattern + + params_opt = pattern.options[:params] + if params_opt && params_opt[param_name] && params_opt[param_name][:type] + param_type = params_opt[param_name][:type] + case(param_type) + when "Integer" + node(:capture, param_name, constraint: /\d/) { scan(/\w+/) } + else + node(:capture, param_name, constraint: "[^/\\?#\.]") { scan(/\w+/) } + end + else + node(:capture, param_name, constraint: "[^/\\?#\.]") { scan(/\w+/) } + end + end on('\\') { |_c| node(:char, expect(/./)) } on('(') { |_c| node(:optional, node(:group) { read unless scan(')') }) } on('|') { |_c| node(:or) } diff --git a/lib/mustermann/grape/version.rb b/lib/mustermann/grape/version.rb index 5deb4c9..a932d05 100644 --- a/lib/mustermann/grape/version.rb +++ b/lib/mustermann/grape/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module MustermannGrape - VERSION = '1.0.3' + VERSION = '1.1.0' end diff --git a/spec/grape_spec.rb b/spec/grape_spec.rb index 7336bf0..c47109d 100644 --- a/spec/grape_spec.rb +++ b/spec/grape_spec.rb @@ -751,4 +751,33 @@ example { pattern.peek_params('/foo bar') .should be_nil } end end + + context 'when params option is provided' do + context 'and they contain parameters information' do + pattern '/foo/:id', params: {"id"=>{:type=>"Integer"}} do + it { should match('/foo/1') } + it { should_not match('/foo/bar') } + end + + context 'and inherit routes are present' do + pattern '/foo/:id/bar/:reference', params: {"id"=>{:type=>"Integer"}, "reference"=>{:type=>"String"}} do + it { should match('/foo/1/bar/wadus') } + it { should_not match('/foo/bar/bar/wadus') } + end + + pattern '/foo/:id/bar/:reference', params: {"id"=>{:type=>"Integer"}, "reference"=>{:type=>"Integer"}} do + it { should match('/foo/1/bar/1') } + it { should_not match('/foo/1/bar/wadus') } + it { should_not match('/foo/bar/bar/1') } + end + end + end + + context 'and they do NOT contain parameters information' do + pattern '/foo/:id' do + it { should match('/foo/1') } + it { should match('/foo/bar') } + end + end + end end