Skip to content

Commit

Permalink
Allow symbol_matcher in symbol_matchers plugin to take a block to all…
Browse files Browse the repository at this point in the history
…ow type conversion

This allows symbol matchers to have the same flexibility as class
matchers.

This changes the behavior of the automatically generated
match_symbol_* private request methods to return an array of the
regexp and any conversion block, instead of just the regexp.
  • Loading branch information
jeremyevans committed May 23, 2023
1 parent e29236c commit b3fe9af
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
= master

* Allow symbol_matcher in symbol_matchers plugin to take a block to allow type conversion (jeremyevans)

= 3.68.0 (2023-05-11)

* Make Roda.run in multi_run plugin accept blocks to allow autoloading the apps to dispatch to (jeremyevans)
Expand Down
41 changes: 36 additions & 5 deletions lib/roda/plugins/symbol_matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,35 @@ module RodaPlugins
#
# If using this plugin with the params_capturing plugin, this plugin should
# be loaded first.
#
# You can provide a block when calling +symbol_matcher+, and it will be called
# for all matches to allow for type conversion. The block must return an
# array:
#
# symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
# [Date.new(y.to_i, m.to_i, d.to_i)]
# end
#
# route do |r|
# r.on :date do |date|
# # date is an instance of Date
# end
# end
#
# If you have a segment match the passed regexp, but decide during block
# processing that you do not want to treat it as a match, you can have the
# block return nil or false. This is useful if you want to make sure you
# are using valid data:
#
# symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
# y = y.to_i
# m = m.to_i
# d = d.to_i
# [Date.new(y, m, d)] if Date.valid_date?(y, m, d)
# end
#
# However, if providing a block to the symbol_matchers plugin, the symbol may
# not work with the params_capturing plugin.
module SymbolMatchers
def self.load_dependencies(app)
app.plugin :_symbol_regexp_matchers
Expand All @@ -50,9 +79,10 @@ def self.configure(app)

module ClassMethods
# Set the regexp to use for the given symbol, instead of the default.
def symbol_matcher(s, re)
def symbol_matcher(s, re, &block)
meth = :"match_symbol_#{s}"
self::RodaRequest.send(:define_method, meth){re}
array = [re, block].freeze
self::RodaRequest.send(:define_method, meth){array}
self::RodaRequest.send(:private, meth)
end
end
Expand All @@ -67,8 +97,8 @@ def _match_symbol(s)
meth = :"match_symbol_#{s}"
if respond_to?(meth, true)
# Allow calling private match methods
re = send(meth)
consume(self.class.cached_matcher(re){re})
re, block = send(meth)
consume(self.class.cached_matcher(re){re}, &block)
else
super
end
Expand All @@ -80,7 +110,8 @@ def _match_symbol_regexp(s)
meth = :"match_symbol_#{s}"
if respond_to?(meth, true)
# Allow calling private match methods
send(meth)
re, = send(meth)
re
else
super
end
Expand Down
18 changes: 14 additions & 4 deletions spec/plugin/symbol_matchers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
app(:bare) do
plugin :symbol_matchers
symbol_matcher(:f, /(f+)/)
symbol_matcher(:c, /(c+)/) do |cs|
[cs, cs.length] unless cs.length == 5
end

route do |r|
r.is :d do |d|
Expand All @@ -19,6 +22,10 @@
"f#{f}"
end

r.is :c do |cs, nc|
"#{cs}#{nc}"
end

r.is 'q', :rest do |rest|
"rest#{rest}"
end
Expand All @@ -27,8 +34,8 @@
"w#{w}"
end

r.is :d, :w, :f do |d, w, f|
"dwf#{d}#{w}#{f}"
r.is :d, :w, :f, :c do |d, w, f, cs, nc|
"dwfc#{d}#{w}#{f}#{cs}#{nc}"
end
end
end
Expand All @@ -40,9 +47,12 @@
body("/1az0").must_equal 'w1az0'
body("/f").must_equal 'ff'
body("/ffffffffffffffff").must_equal 'fffffffffffffffff'
body("/c").must_equal 'c1'
body("/cccc").must_equal 'cccc4'
body("/ccccc").must_equal 'wccccc'
status("/-").must_equal 404
body("/1/1a/f").must_equal 'dwf11af'
body("/12/1azy/fffff").must_equal 'dwf121azyfffff'
body("/1/1a/f/cc").must_equal 'dwfc11afcc2'
body("/12/1azy/fffff/ccc").must_equal 'dwfc121azyfffffccc3'
status("/1/f/a").must_equal 404
body("/q/a/b/c/d//f/g").must_equal 'resta/b/c/d//f/g'
body('/q/').must_equal 'rest'
Expand Down

0 comments on commit b3fe9af

Please sign in to comment.