Rails: Should I have a separate model for a user profile?
Every case is different. But I’d be wary of ever creating a dedicated model for a UserProfile. It sounds like a very general “throw everything here” type of model. Which is something you should avoid. It’s better to be very specific about the type of data being stored.
Modeling Medium’s user profile
For user profiles, generally the information shown on the profile isn’t exclusive to the users profile.
For example: Medium.com’s user profile shows all of the users posts, their followers and what they have highlighted.
I’d imagine their data model works like this. They have a
User model, a
Post model, a
FollowerAssociationModel and a
(yes, I know Medium doesn’t use Rails, but if they did).
For their profile page, they bring in data from several different sources.
Solution: Use the View Object Pattern
The best way I have found to do this in Rails is to use the
View Object Pattern (aka Presenter Object). You can read more about it here: 7 Patterns to Refactor Fat ActiveRecord Models (search view object).
Create a class that encapsulates all the data you want shown on the profile page.
class UserProfile attr_reader :user def initialize(user) @user = user end def tagline # example of some html conversion @tagline ||= ConvertTagsToLinks.run(user.tagline) end def posts @posts ||= user.posts.order_by_featured_date end def followers @follows ||= user.followers.ordered_by_popularity end ## ect... end
(a bit of a contrived example, but hopefully you get the idea)
Then this makes it really easy to have one nice clean object to access in your controllers and views.
# some controller def show @user = User.find(params[:id) @user_profile = UserProfile.new(@user) # render a view... end
Now if you’re wondering things like, “but my user has a resume on their profile and I want it on the profile page.”
In cases like that, it makes sense to dedicate a model to just that object. Then you’d have a
It keeps things very explicit and when other people are working with your code they will know where to look when making changes.