14

I made some regular expressions for email, bitmessage etc. and put them as constants to

#config/initializers/regexps.rb
REGEXP_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
REGEXP_BITMESSAGE = /\ABM-[a-zA-Z1-9&&[^OIl]]{32,34}\z/

and use it like

if @user.contact =~ REGEXP_EMAIL
elsif @user.contact =~ REGEXP_BITMESSAGE

Is that's good practice? What's the best way to store them?

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
br.
  • 1,259
  • 1
  • 14
  • 21
  • This is not an answer. The given strings are not regular expression liteals. Remove surrounding `"` if you mean regular expression literals. – falsetru Dec 25 '13 at 10:41
  • yep, i just seen. fixed – br. Dec 25 '13 at 10:44
  • Why wouldn't you use match instead? `if @user.contact.match(REGEXP_EMAIL)` – hwnd Dec 25 '13 at 10:48
  • @hwnd, because its looks clean. Is that method deprecated or not allowed? – br. Dec 25 '13 at 10:55
  • `[123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ]` is horrid. You might be missing `l`, `I`, `O` (or is it deliberate?). Unless the missing characters are by design, it can be shortened to `[1-9a-zA-Z]`. – nhahtdh Dec 25 '13 at 11:26
  • If you dont plan to change them, you can store them into DB, but it is correct to use constants. And to store them for what? – Малъ Скрылевъ Dec 25 '13 at 11:38
  • @nhahtdh, yes, i need to miss lIO0, because [BM address is base58](https://bitmessage.org/wiki/Address) majioa, i don't plan to change them and store in database, it's only for code beautify. – br. Dec 25 '13 at 12:32
  • @br.: For some reason (as it is not specified in any documentation), character set intersection seems to work from Ruby 1.9.2 and above: http://rubular.com/r/Mb0FARCD34. Even if you don't use the set intersection syntax, you can still use range to shorten the regex a bit to help the maintainer. – nhahtdh Dec 25 '13 at 18:24

1 Answers1

25

It makes sense, that's one of the possible approaches. The only downside of this approach, is that the constants will pollute the global namespace.

The approach that I normally prefer is to define them inside the application namespace.

Assuming your application is called Fooapp, then you already have a Fooapp module defined by Rails (see config/application).

I normally create a fooapp.rb file inside lib like the following

module Fooapp
end

and I drop the constants inside. Also make sure to require it at the bottom of you application.rb file

require 'fooapp'

Lazy-loading of the file will not work in this case, because the Fooapp module is already defined.

When the number of constants become large enough, you can more them into a separate file, for example /lib/fooapp/constants.rb. This last step is just a trivial improvement to group all the constants into one simple place (I tend to use constants a lot to replace magic numbers or for optimization, despite Ruby 2.1 Frozen String literal improvements will probably let me remove several constants).

One more thing. In your case, if the regexp is specific to one model, you can store it inside the model itself and create a model method

class User

  REGEXP_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
  REGEXP_BITMESSAGE = /\ABM-[123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ]{32,34}\z/

  def contact_is_email?
    contact =~ REGEXP_EMAIL
  end

end
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • I'm not sure that's the best place to put those constants: REGEXP_EMAIL is not something only related to the User, it is something used to parse emails, and those could be also present in other models. – Alessandro De Simone Nov 25 '16 at 17:17