title: Model person (user) profile attributes / properties - best practice, static vs dynamic properties
body: <p>I couldn't easily find a relevant topic on SO so here we go - a classic problem: I have a User or Person model and I want to model that person's physical properties/attributes (eye color, hair color, skin color, gender, some lifestyle properties like sleep time per night (&lt;8h, ~8h, >8h), smoking, daily sun exposure etc.</p>
  
  <p>I usually solve that problem by creating a separate rails model (database table) for each property because then it is easy to add more options later, edit them, use as a source for <code>&lt;select&gt;</code>, i.e.</p>
  
  <pre><code>class Person
    belongs_to :eye_color
    belongs_to :skin_color
    belongs_to :hair_color
    belongs_to :sleep_per_night
    belongs_to :sun_exposure
  
    attr_accessible :gender # boolean, m/f
  end
  
  class HairColor
    has_many :people
  
    attr_accessible :value
  end
  
  class EyeColor
    has_many :people
  
    attr_accessible :value
  end
  
  Person.last.eye_color
  ...
  EyeColor.first.people
  </code></pre>
  
  <p>But what if there is a lot of those attributes (i.e. 10-15 different phisycal and lifestyle properties). For me it seems like breaking DRY rule, that is, I'm left with many small tables, like <code>eye_colors</code>, which have 3-5 records. Each of those tables has only one meaningful column - value.</p>
  
  <p>I was thinking how you guys solve those problems, maybe by creating a single model, i.e. PersonProperty that has the following structure</p>
  
  <pre><code>person_properties[type, value]
  </code></pre>
  
  <p>so the previous solution with separate models, i.e. for eye_color and hair_color would look like this (types/classes and values):</p>
  
  <pre><code># PersonProperty/person_properties:
  1. type: 'HairColor', value: 'red'
  2. type: 'HairColor', value: 'blond'
  3. type: 'SkinColor', value: 'white'
  4. type: 'EyeColor', value: 'green'
  5. type: 'HairColor', value: 'black'
  6. type: 'SkinColor', value: 'yellow'
  7. type: 'SleepPerNight', value: 'less than 8h'
  8. type: 'SleepPerNight', value: 'more than 8h'
  9. type: 'DailySunExposure', value: 'more than 1h'
  ...
  19. type: 'EyeColor', value: 'blue'
  ...
  </code></pre>
  
  <p>The above example might be more normalized by splitting the PersonProperty model into two. Or maybe you suggest something else?</p>