0

I am seeking to populate a select list in a form with options for user gender. I have a learning Rails book that uses a similar approach for credit card options by creating an array in the model and then referencing it in the view. Unfortunayely when I use this approach I receive an error referencing the line in my view stating: "uninitialized constant GENDER_OPTIONS"

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable

  GENDER_OPTIONS = { "Male" => :true, "Female" => :false, "Unspecified" => :nil}

  has_many :discussions
  has_many :comments
end


<div>
  <%= f.label :gender %><br />
  <%= f.select :gender, User::GENDER_OPTIONS​ %>
</div>
Dercni
  • 1,216
  • 3
  • 18
  • 38

2 Answers2

2

"sex" should not be stored as a boolean - it is not a true/false value. Aside from labelling half of the people in your database as "false", when you write SQL queries you (and and future developers) will have to know what the magic values are.

And boolean fields should not have three potential states (true/false/nil) - that's just asking for trouble.

To make your database understandable from the schema side, set the field to be a string, and store the values "male", "female", or "unspecified" (or just blank).

Then ask yourself: why on earth do you actually need to ask people about their sex? Unless it's a dating website, or medical DB; otherwise it's just personal info for personal info's sake - you might as well be asking them their shoe size (or any other bodily part).

Pavling
  • 3,933
  • 1
  • 22
  • 25
  • The following states the standard is to use an integer column called sex and use the standards of 0=Unknown, 1=Male, 2=Female, 3=Not applicable http://en.wikipedia.org/wiki/ISO/IEC_5218 – Dercni Dec 06 '14 at 23:25
  • My apologies. 9 = not applicable (not 3) – Dercni Dec 07 '14 at 08:03
  • 1
    yes, so *not* booleans. That standard avoids the localisation of having English words in the DB, but by using integers that are not foreign keys, you'll still need some documentation somewhere that points new devs to the information that 1==male and 2==female. And it's still probably none of my business which of them my user is. – Pavling Dec 07 '14 at 09:43
  • I have included the following in my Profile model which is self documenting your the reasons you point out: enum sex: { not_known: 0, male: 1, female: 2, not_applicable: 9 }. I am now wondering if I should store Countries in the db is just country codes and use another enum. Thanks for the help. – Dercni Dec 07 '14 at 09:50
1

Try using helper and locale.

# app/helpers/application_helper.rb

def gender_lists 
  I18n.t(:gender_lists).map { |key, value| [ value, key ] } 
end


# config/locale/en.yml

en:
  gender_lists:
      "": Unspecified
      "true": Male
      "false": Female

and on your view, you can do this

<div>
  <%= f.label :gender %><br />
  <%= f.select :gender, gender_lists​ %>
</div>

===

Note :

Just suggestion, user string type data instead of boolean

rails_id
  • 8,120
  • 4
  • 46
  • 84
  • 1
    @user1567212 because it's easier to maintain all UI text when it's not scattered throughout the code and is formatted in almost plain text, editable by anyone. – D-side Dec 06 '14 at 10:58
  • Ok I understand now. So this would conflict with Pavling's suggestion of storing the sex in the database as string values. – Dercni Dec 06 '14 at 22:04
  • 1
    What about storing the gender as integers then using enums? http://stackoverflow.com/questions/22827270/how-to-use-i18n-with-rails-4-enums?lq=1 – Dercni Dec 06 '14 at 22:11
  • @user1567212 totally legit. In fact, it doesn't conflict with @Pavling's answer once you separate the **values** of gender and their **representation** stored in I18n. In that sense, `enum` fits much better, since strings provide much more freedom with values than you can use. `enum` is a generic concept of a type for which you can list all possible values. I'm using a similar scheme myself with a permission model that can permit reading or editing. Should I wish to add more permission types later, I'll have no problem with it. – D-side Dec 06 '14 at 23:44
  • Absolutely - I'd suggest using the strings 'male' and 'female' as values in the DB (or putting a foreign key to a sexes table...) and those strings become the keys to lookup values in any localization. But it makes no difference to functionality if you use integers. The point is - whatever you do, *don't* use booleans for this :-) – Pavling Dec 07 '14 at 13:40