1

I'm wracking my brain about how to start setting up the following set of model relationships in my project. I'm not looking for the complete solution (models, tables, migrations, etc), just a little help to get me going in the right direction. I learn more by struggling on my own :)

In short, I want my Users (created with Devise) to have a set of Inclinations that represent preferences they have to certain things (i.e. warmer weather vs colder weather, watching sports vs playing sports, etc) on a sliding scale (coded 5 to -5, zero excluded). Each Inclination (or InclinationData?) will be in a separate table with a name, description, etc, and all Inclinations will get their data pulled from that table (so I don't repeat myself throughout my application). Also, every User will have one Inclination record for each InclinationData(?) by default.

As for the setup, will I need:

  • 5 tables (3 main ones and two join tables)?
  • Just three (main three models)?
  • Four (main three models & a joining table for Inclinations and InclinationData)?
  • Four (main three models & a joining table for Users & Inclinations)?
  • Perhaps something simpler like a single Profile or Preferences model that's bound to a User?

I can never figure out how to decide if joining tables are necessary, and this is the most complex association I've ever tried.

I appreciate any help, and please let me know if you need more information to be able to help me out.

Kyle Carlson
  • 7,967
  • 5
  • 35
  • 43
  • What is the difference between the models Inclination and InclinationData? – eabraham May 31 '13 at 00:29
  • Each user will have `Inclination`, the actual record of their rating, timestamps, etc. Since every user will have the same set of `Inclinations`, I wanted to pull the information (name, description, etc) from a different table & link it to the `Inclination` somehow. That's why I was wondering about how many tables I needed. Does that make sense? – Kyle Carlson May 31 '13 at 03:40

2 Answers2

1

I think I've reasoned through your request:

Users has_many UserInclinations and Inclinations has_one UserInclinations. Roughly, the models should look like this:

class User < ActiveRecord::Base
  has_many :user_inclinations

  #default Devise attr_accessible
end

class UserInclinations < ActiveRecord::Base
  belongs_to :users
  belongs_to :inclinations

  attr_accessible :user_id, :inclination_id, preference_score
end

class Inclination < ActiveRecord::Base
  has_one :user_inclination

  attr_accessible :preference
end
eabraham
  • 4,094
  • 1
  • 23
  • 29
  • Thanks for that, it definitely gets me closer. The part that was confusing was what I mentioned in my comment to you above. Each user will have the same set of `Inclinations`, and I'm trying to find a DRY way to accomplish this. – Kyle Carlson May 31 '13 at 03:42
  • So in my example above, the fixed set of inclinations are stored in the inclination table. The UserInclinations table records the preference score for each user's inclination. – eabraham May 31 '13 at 03:52
  • Ah, that makes sense. I was overcomplicating it bigtime! Let me have a go at it and I'll see what I can do. Thanks! – Kyle Carlson May 31 '13 at 14:28
1

You say, all Users have the same set of Inclinations. You can put the description of the Inclinations in one model/table and the users ratings in the joining table UserInclination , according to eabraham:

class User < ActiveRecord::Base
  has_many :users_inclinations
  has_many :inclinations, through: :users_inclinations

end

class UsersInclination < ActiveRecord::Base
  belongs_to :users
  belongs_to :inclinations

  attr_accessible :user_id, :inclination_id, preference_score
end

class Inclination < ActiveRecord::Base
   has_many :users_inclinations

   attr_accessible :description, :name, :low_label, :high_label
end

So you can pull the description (i.e. to build the rating form) from Inclinations and store the individual ratings with

an_inclination= Inclination.find_by_name('weather')
user.user_inclination.create(inclination: an_inclination, preference_score: the_users_score)
Martin M
  • 8,430
  • 2
  • 35
  • 53
  • THAT is awesome! I like how your solution even includes labels for the high and low ends of the range. Exactly what I needed & didn't even ask for. Marked as the answer :) – Kyle Carlson May 31 '13 at 14:30