WestMichiganRubyTraining / discussion

Create issues on this repository to open discussion threads in the Issue Tracker!
2 stars 0 forks source link

How should I handle devise user profiles and privacy settings #26

Open ThomasBush opened 11 years ago

ThomasBush commented 11 years ago

I have a rails 3 devise app which has users with a profile and privacy settings. I currently have this working, but am concerned about efficiency and would love your advice if you wouldn't mind.

I generated User model with devise and scaffolded out Profile and Privacy models to contain items deemed not required for sign up. I would like the the User to have different settings links.

Account Settings => Devise - just required login type stuff, username, password Profile Settings => Profile model - description, avatar, birthday etc. Privacy Settings => Privacy model - checkboxes that control basic hiding/showing of the user's profile fields.

I have set up my relationships:

user.rb

has_one :profile
has_one :privacy

profile.rb

belongs_to :user

privacy.rb

belongs_to :user

This seems horribly inefficient to me. To display the profile I am relying on loading three tables: users, profiles, and privacies.

I think that all of the tables for Profile and Privacy should be contained in the users table, would this make more sense? How would I separate the different forms?

My one thought was to just add a profile method and a privacy method to the users controller, than I could make profile and privacy templates in my users/views and form partials controlling the different portions of the user record that each form would edit.

Does this make sense? Would this make more sense than separate scaffolds like I currently have?

billgathen commented 11 years ago

As usual, there are opposing forces at work here: efficiency versus maintainability. My best advice is to do whichever minimizes pain for you and your users. "Pain-Driven Programming" is often a useful paradigm when deciding how to refactor/optimize code.

A question to ask is "how many times will a user access their privacy or profile pages?" If you're talking about a couple times a day across the entire user base, the added load of pulling two separate models amounts to milliseconds: neither your server or your users are going to notice. Even if "maximum efficiency" means 20 millis and "horribly inefficient" means 43 (over twice as long!), they'll still both appear instantaneous to the user.

On the flip side is ease of use for the programmer. My rule is that if it isn't hurting the user experience and it isn't requiring extra hardware, make it as easy to maintain as possible.

Splitting the data across 3 models is intended to keep things in neat little boxes so you only deal with the part of the user you're interested in at that moment. But a user page will never access the 2 dependent datasets except through the user model, so they are effectively linked regardless. If you were displaying cross-user data (say a page that displays what percentage of men vs women are on the site, or a pie chart breaking out the various "favorite activities"), then there would be situations when you'd query directly against the profile model and skip the user model entirely. But those queries could be run against a consolidated user model without change.

Your description of the user model sounds more like a "user login" model: it doesn't represent a complete "user" concept. If the total number of fields across the 3 models is manageable (and you'll have to decide that for yourself, but you should be able to handle at least a dozen or so before it starts getting unwieldy), I'd consolidate in order to have everything you're interested in in a single location. If that starts causing you pain, split the painful parts out into their own model. The pain will show you how to do it. Until you feel pain, you're just guessing.

As far as templates go, different views can depend on the same model, so all 3 views would depend on the consolidated user model: there's no requirement that you display ALL the model attributes in every form, just the relevant ones.

A common technique these days is to include multiple related forms on the same page, with javascript that hides all but the one you're currently interested in and tabs that allow the user to navigate between them without switching pages. Very fast and easy to maintain for the programmer, since they can all be sections of a single form underneath. I'd give that a serious try.

coderbydesign commented 11 years ago

I think Bill hit it on the head. The takeaway being: if it's something that's obviously affecting the user experience, it's worth the time spent changing. If the perceived inefficiency is not affecting the user experience or hardware requirements, it can sometimes be easy to over-design, or refactor too much, too soon. With that said, as Bill mentioned, if something becomes too difficult to maintain and there is no real affect on user experience, it can still be advantageous to "clean up your mess" (http://www.youtube.com/watch?v=f5I1iyso29U) to help make the app more maintainable and extendable.

The difficult thing that I've encountered, especially in agile development, is that it can be difficult if not impossible to predict all trouble-points in an application before it's in production. Bill's comment on "feeling the pain" is something that I've tried to embrace. Thinking forward as much as you can, and anticipating issues or changes can make things easier when things do end up needing to be changed, but in some cases you may be making things harder on yourself by solving problems that don't yet (and may never) exist. As long as you've allowed for it, once you feel the pain you can generally let the issue guide you to the correct design solution. There seems to be a balance of design for efficiency/UE and design for maintainability that can change from project to project. That's just my two cents on a broader level from my experience.