Dinuz
Dinuz

Reputation: 400

Nested resources has many : through relationship issue

I am really stuck on this problem, and I can't find a way to come out from it:

I have an user model (built up with devise).

I have an item model that is a nested resource for user.

In the user model (user.rb):

# Setup the relations model
has_many :items, :dependent => :destroy

In the item model (item.rb):

# Setup the relations model
belong_to :user

in the routes.rb:

resources :users do
  resources :items
end

In this way an user is able to create an item and own it:

ex of path: user/1/items/1

Now I'd like that the user is able to share an item (created by him) with another user, but holding the ownership of the item (just the user that created the item can destroy it, and just the user that created the item can update some field of the item, instead other fields need to be updatable (editable) also by the user the received the item). In other words, I'd like that the permission on the item are different for the user that created it and the user that just received it.

In order to allow the sharing action of items between users, I build up the following as_many :through relationship:

I created another model, called sharing (that represent the joint table between the item model and the user model):

Then I modified the user.rb (the user model) in the following way:

# Setup the Item relations model
has_many :items, :dependent => :destroy # this to set up the item ownership

#This to set up the has_many :through realtionship
#(note I am calling a new model shared_items - that really doesn't exist - is an item model)
has_many :sharings
has_many :shared_items, :foreign_key => "shared_user_id", :through => :sharings

accepts_nested_attributes_for :items #This will work for the nested items resource
accepts_nested_attributes_for :sharings #Do I really need this line??

# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, 
                :items_attributes, #This will work for the nested items resource
                :sharings_attributes  #Do I really need this line??

Then I modified the item.rb (the item model) in the following way:

# Setup the relations model
belong_to :user

#this two lines are suppose to connect the two models (item and receiver) using a joint table
has_many :sharings
has_many :shared_users, :foreign_key => "shared_item_id", :through => :sharings

accepts_nested_attributes_for :sharings #Do I really need this line??

attr_accessible :user_id, :item_type, :reference_date, :title, 
                :sharings_attributes #Do I really need this line??

I wrote the sharing.rb (sharing model - joint table) in the following way:

belongs_to :shared_user, :class_name => "User"
belongs_to :shared_item, :class_name => "Item"

attr_accessible :shared_moment_id, :shared_user_id

After, I have had to consider the fact that the receiver is also an user (is a self reference relationship), and that in my app, there is still in place a friendship model (that allow an user to friend other users and this is working like a charm) - but I believe that Joel suggestion can help (or just changing the reference to my friend table).

With this in place I can create a restful controller for Item (ItemsController), and add a new, create, show, destroy etc actions that will allow an user (actually the current_user) to create an item, destroy or update it without any problems. (as you can see in the item model there is the foreign key user_id).

What instead I need to do, in order to create a restful controller to manage the sharing model (to create new shared items, and to assign them (share them) with other users)???

How after I can recall the database values? I mean, for example:

User with id 3 created five new items (with Item id 1, 2,3,4,5), now he also decide to share some of this item with other users (item 2 with user 6, item 4,5 with user 7,8,9)???

I pull out the nested resource for sharing,and now I just have:

item is a nested resource of user (user/2/item/5) sharing what will be??

Please someone help me....

Thanks a lot Dinuz

UPDATE I was able to let work properly the app, but as single pieces only:

The user create an item. After he decide to share the item with another user (and using the sharings controller - the joint table controller, I was able to create the record inside of the joint table (passing the user id and the item id specific).

Now I'd like to instead perform all the operation in just one shot:

The current_user (the user that is logged in) create an item, and he need to have in the same form the opportunity to share it with other users (array) or to just keep for himself.

I believe that this further step, require to melt together the item controller and the sharing controller, and to do the same in the new item view.

Well How I need to proceed? If someone can suggest a good tutorial for the has_many :through that could cover my case (I really need to understand how in this situation the controller and the view will look like), I think that the model association is set up well, but I can't really figure out how proceed with the controller and the view.

Upvotes: 0

Views: 557

Answers (1)

joelparkerhenderson
joelparkerhenderson

Reputation: 35453

You can use a custom validation like this:

class User < ActiveRecord::Base
  validate :sharing_with_friends_only

  def sharing_with_friends_only
    (receivers - friends).empty?
  end
end

As you mention, the easy way is to un-nest the resources.

This will also make your APIs cleaner.

Upvotes: 1

Related Questions