Mark Berry
Mark Berry

Reputation: 19032

Where should I store a list of select options in Rails 3?

Using Rails 3.1.3 and Ruby 1.9.3.

I want to give the user a list of possible date/time formats. The user's selection will be stored in the Users table. Date/time values are then formatted using the I18n.localize function. I actually have 10 formats; here by way of example are the first two:

config/locales/datetime.en.yml

en:
  time:
    format_labels:
      mdyslash12: mm/dd/yyyy - hh:mm am (12-hour)
      mdyslash24: mm/dd/yyyy - hh:mm (24-hour)
    formats:
      mdyslash12: ! '%m/%d/%Y %I:%M%p'
      mdyslash24: ! '%m/%d/%Y %H:%M'

My question is where to store the list of possible date/time formats. I've identified three possibilities.

1. List options as a CONSTANT in model:

app/models/user.rb

DATETIME_FORMATS = %w[mdyslash12 mdyslash24]
validates :datetime_format, :presence => true,
          :inclusion => { :in => DATETIME_FORMATS }

2. Create an application constant and validate against that:

config/initializers/constants.rb

Rails.configuration.datetime_formats = "mdyslash12 mdyslash24"

app/models/user.rb

validates :datetime_format, :presence => true,
          :inclusion => { :in => Rails.application.config.datetime_formats.split(" ") }

3. Validate directly against the locale file:

app/models/user.rb

validates :datetime_format, :presence => true,
          :inclusion => { :in => (I18n.t 'time.format_labels').stringify_keys.keys }

This option uses a feature that is new to me: I18n.t 'time.format_labels' returns a hash of ALL keys and values from that branch of the locale file. The hash keys are symbols, so to get a string array, I call stringify_keys to convert the symbols to strings, then keys to give me only the keys (no values).

Option #3 is the DRYest in that I don't have to list the possible values in two places. But it doesn't feel quite right to depend on the locale file for the discreet list of possible date/time formats.

What would you recommend? One of these options? Something else?

Upvotes: 1

Views: 752

Answers (1)

Alex Dixon
Alex Dixon

Reputation: 613

I'd go with option 1 to start with, since it's simple, clear, and fairly DRY. I might refactor to option 2 if I ended up needing that constant in another model.

Option 3 has the potential to behave differently based on the locale, so I don't like that. If you end up forgetting to specify your format labels in a new locale, your selection list might end up being empty (or if there's a typo in one locale, it might take longer to notice, since the typo would be treated as valid for that locale). Regardless it's probably a good idea to unittest this in all your supported locales.

Upvotes: 3

Related Questions