views:

41

answers:

4

When building a rails app that allows a User to login and create data, is it best to setup a belongs_to :user association on every single model? For example, let's say a user can create Favorites, Colors and Tags.

And let's say Favorites has_many :tags and Colors also has_many :tags. Is it still important for Tags to belong_to :user assuming the User is the only person who has authority to edit those tags?

And a similar question along the same lines: When updating data in FavoritesController, I've come to the conclusion that you perform CRUD operations by always doing something like current_user.favorites.find(param[:id].update_attributes(param[:favorite]) so that they can definitely only update models that belong to them. Right?

Update Wasn't too happy with any of the answers, as no one really answered my question but instead went after the for-example-only Tags model suggesting better ways to do that. I'm assuming I was right, and models should belong_to :user. I also discovered some great security tips that address my questions here: http://asciicasts.com/episodes/178-seven-security-tips

A: 

It depends on your model. Both cases are valid but I'd discorage making a circular relationships like that. Having a hierarchy is more flexible. For example: User->Favorites->Tags (unless you want to tag users as well)

User.favorites.find(params[:id]).update_attributes(param[:favorite])

is what you mean I guess (syntax). Whoever calls the URL will perform that action. Dont rely on the fact that that URL is visible to one user only (owner of the favorite). You should have checks in place that the currently logged in user is the only one performing actions on the objects that belong to him.

Zepplock
My original code had a mistake: I normally do `current_user.favorites` rather than `User.favorites`. Is that what you mean by having checks in place? That's all I've currently done to ensure the user is editing their data and not some other user's.
Trevor Hartman
+1  A: 

As you describe the tags it seems that they are more of an aspect, so you can implement them as a polymorphic association. But you should do it many-to-many, as tags can be reused among users and taggable objects. Let's call the join model Tagging, which will be the one that belongs to user if you want to remember who created the tagging.

class Tag < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy
  has_many :colors, :through => :taggings, :source => :taggable, :source_type => "Color"
  has_many :favorites, :through => :taggings, :source => :taggable, :source_type => "Favorite"
end

class Tagging < ActiveRecord::Base
  belongs_to :user
  belongs_to :taggable, :polymorphic => true
  belongs_to :tag  
end

class Color < ActiveRecord::Base
  belongs_to :user
  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end

class Favorite < ActiveRecord::Base
  belongs_to :user
  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end

class User < ActiveRecord::Base
  has_many :favorites
  has_many :colors
  has_many :taggings
  has_many :tags, :through => :taggings
end

As for the Favorite updating, I agree with you: you will mostly work within the scope of a user (most likely the currently logged in user).

schastar
A: 

The proposed mechanism sounds a bit too complex for me. I prefer the current_user way. Assume there is a current_user (following the authlogic way) in your authentication system, then simple add a user references (user_id) in every relevant table. Update the current_user for new or update record via a controller filter.

In the models, put relevant belongs_to :users accordingly, put enough has_many in users model if needed.

ohho
A: 
Vamsi