0

I am building a service where users installs a plugin across all of their pages on their site (such as by adding it to their template) but I only want to run the plugin code on a specific URL or pattern of URLs provided by the site owner.

I would like to allow the site owner to be able to set a simple sort of URL pattern (for example, similar to how Cloudflare does it):

enter image description here

For example, The site owner could set a URL pattern as: https://example.com/pages/*/edit

And save this pattern in the db, like so:

@url = Url.create string: 'https://example.com/pages/*/edit'

Say then a user visits the url https://example.com/pages/my-page/edit I want to pass this back to my app and somehow find the previously created @url with that specific URL.

Url.find_by_url 'https://example.com/pages/my-page/edit'

Should then return the previously created Url record.

How would you go about doing this?

goddamnyouryan
  • 6,854
  • 15
  • 56
  • 105
  • I suppose you could use a LIKE query and gsub the `*` to `%`? Not sure this is best way though – max pleaner May 07 '19 at 00:34
  • @maxpleaner I like that, but I think it would only work in reverse, since `https://example.com/pages/*/edit` will be what's stored in the db, and `https://example.com/pages/my-page/edit` will be what I am searching with. – goddamnyouryan May 07 '19 at 18:25
  • Oh I see, well in that case you can take a similar approach but rather than turning it into a LIKE query you can turn it into a regex. – max pleaner May 07 '19 at 19:27
  • Something like this `"http://foo.com".match Regexp.new(Regexp.quote("http://*.com").gsub("\\*", ".+"))` If this works for you I can make an answer, however feel free to make your own answer upon solving if you like a well. – max pleaner May 07 '19 at 19:30
  • @maxpleaner hmm, I'd rather do it in a query as this will be pretty high volume! I've added an answer with what I've gone with thus far. – goddamnyouryan May 07 '19 at 21:48
  • @maxpleaner hmm, I'd rather do it in a query as this will be pretty high volume! I've added an answer with what I've gone with thus far. – goddamnyouryan May 07 '19 at 21:49

1 Answers1

1

Ended up finding this answer: https://stackoverflow.com/a/3410431/117554 which I adapted to rails like so:

Url.find_by_sql(["
  select * from urls
  where ?
  like replace(value, '*', '%')
", url]).first

Using the replace function from Postgres. Seems to be working thus far!

goddamnyouryan
  • 6,854
  • 15
  • 56
  • 105
  • 2
    awesome! You should probably be using parameterized interpolation instead. See https://stackoverflow.com/a/21886874/2981429 – max pleaner May 07 '19 at 22:46
  • @maxpleaner good call. I edited the question to include my version with parameterized interpolation. It has to be formatted a bit weirdly due to `find_by_sql` but I got it from here: https://devdocs.io/rails~4.2/activerecord/querying#method-i-find_by_sql – goddamnyouryan May 09 '19 at 19:42
  • 1
    There's also a lesser known way to pass parameters to `find_by_sql`. Instead of `?` use `:url` and instead of `url` as the second argument use a hash `{url: url}`. I prefer this approach because you don't have to keep track of the order of the arguments, since they are all _named_ – max pleaner May 09 '19 at 20:05