5

Question

I have a User model with authorisation and authentication logic built.

Now I realise I have three different types of users. I want to store different information about each of them.

What is the best way to handle this in Rails?

Thoughts based on current reading

I've looked at STI but from what I've read feel it is inappropriate because I'll end up with a lot of NULL fields in my database.

Ideally I'd like to not duplicate the authentication / authorisation logic for each of the three user types.

Each user will also have different functionality within the application.

cmd
  • 81
  • 8
  • you should add a user_type attribute in your model/db, and then setup a model to map the user_types with what activites/functionality they're allowed to use. – rnirnber Feb 07 '13 at 23:57
  • But this still means I'd have one User table, right? So if I wanted to store name and email for one user (type A) and name, email, address,dob,phone for another (type B) I'd still have a lot of null fields for every type A user I create. – cmd Feb 08 '13 at 00:02
  • you should set up a generic field. in rails, this is where the serialize/deserialize functions in Active record would come in handy. There are better data structure to use, like an array, etc...but for sake of easiness let's just go with this. In models/user.rb set up a text field and store the custom/variable options in the single field. Call it maybe user_profile. One record for that column might look like "dob: 031388\nphone:8312229999\nemail:user@hotmail.com".....and then you just split/join the fields by a the "\n" character – rnirnber Feb 08 '13 at 00:09
  • and then you could use the active record callbacks and the controller (although I'm sure doing it in the controller would violate Rails best practices) to tweak the data from the form fields before it gets uploaded....and then for displaying the data, its just as easy you split it up and write it out in separate divs – rnirnber Feb 08 '13 at 00:10
  • http://apidock.com/rails/ActiveRecord/Base/serialize/class – rnirnber Feb 08 '13 at 00:11

2 Answers2

1

You can try using polymorphic associations and creating table users with data that all types of users have and putting other data in seperate tables. Railscast epizode covering this topic.

Konrad Gadzina
  • 3,407
  • 1
  • 18
  • 29
  • I tried to use polymorphic association as outlined in the answer here (to create different profiles associated to user) but I couldn't get it to work. http://stackoverflow.com/questions/7719600/designing-a-rails-application-single-table-inheritance -- I hadn't thought of using polymorphic association the way you've suggested, it could be what I'm looking for :) – cmd Feb 08 '13 at 00:20
0

There are lots of ways to do this. Here's one approach:

Instead of thinking of different types of users, you could think of roles that a user has.

For example, if a user could be a butcher, baker, or candlestick maker, you could have four tables: users, butchers, bakers, candlestick_makers. The latter three role tables each have a user_id column; they "belong to" the user.

If you need to enforce that a particular user has only one role, you will have to do that in the application (since this database schema would allow multiple roles for a single user).

This method is good if there is a lot of stuff that would belong in those role tables. If not, leaving some NULL columns on the users table probably won't kill you.

benzado
  • 82,288
  • 22
  • 110
  • 138
  • If i have 3 separate tables will the butchers, bakers and candlestick_makers all be able to login using the logic I have in for my User model? – cmd Feb 08 '13 at 00:16
  • The idea is that authentication only looks at your User model; once logged in you can redirect based on whether `user.butcher_role != nil` and so on. – benzado Feb 08 '13 at 01:42