44

I currently have a piece of code that looks like:

if match = request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)
  match[:slug]
end

Is there a way to use the safe navigation operator (introduced in 2.3.0) to avoid this if conditional?

Kyle Decot
  • 20,715
  • 39
  • 142
  • 263

4 Answers4

67

Just use the ordinary (non-sugar) form.

request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.[](:slug)
sawa
  • 165,429
  • 45
  • 277
  • 381
23

For better readability I would pick #dig instead of the #[].

Like,

request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.dig(:slug)

instead of

request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.[](:slug)
Vedant Agarwala
  • 18,146
  • 4
  • 66
  • 89
  • 3
    Interesting idea, but I get "undefined method 'dig' for MatchData", even with ruby 2.4.2 and rails 5.1.4. – Anson Sep 18 '17 at 13:46
  • 5
    The dig method is for hashes. While it also works on arrays, it looks like MatchData doesn't fully implement the array interface. Since the safe navigation operator works like #try! instead of #try, only the second version works. https://stackoverflow.com/a/45825498 – Kingdon May 31 '18 at 19:06
8

For readability, I prefer using the match's named_captures method which is available from ruby 1.9.1, with the safe operator which is available from ruby 2.3.0.

request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.named_captures&.dig('slug')
Mike State
  • 509
  • 7
  • 3
4

You can send any method, so using safe-browsing operator this will be:

request.path.match(/\A\/(?<slug>(?!admin|assets)\w+)/)&.send(:[], :slug)
Vasfed
  • 18,013
  • 10
  • 47
  • 53
  • 1
    This definitely works but I went w/ the approach of using `&.[](:slug)`. Thanks for looking into it though! – Kyle Decot Jan 14 '16 at 17:00