I am trying to make an application wherein Users have many Items, and each Item they have through Possession is an entity in its own right. The idea behind this is if I have a MacBook item, eg, and a user adds it to their inventory, they may apply attributes (photos, comments, tags, etc) to it without directly affecting them Item itself, only their Possession.
The Item will in turn aggregate attributes from its corresponding Possessions (if you were to go to /item/MacBook, rather than /user/101/possession/5). I have the following models setup (ignoring attributes like photos for now).
class U开发者_如何学Cser
has_many :possessions
has_many :items, :through => :possessions
end
class Item
has_many :possessions
has_many :users, :through => possessions
end
class Possession
belongs_to :user
belongs_to :item
end
My first question is, am I doing this right at all. Is has_many :through the right tool here?
If so, how would I deal with class inheritance here? I might not be stating this right, but what I mean is, if I were to do something like
@possession = Possession.find(params[:id])
@photos = @possession.photos.all
and there were no photos available, how could it fall back to the corresponding Item and search for photos belonging to it?
Your initial data structure seems appropriate.
As for the second part, with the "fall back" to a corresponding item, I don't think there would be a direct Active Record way of doing this. This behavior seems pretty specific, and may be confusing to future developers working on your app unless you have a clear method for this.
You could create a method inside Possession
like:
def photos_with_fallback
return self.photos if self.photos.size > 0
self.item.photos
end
There is a huge consequence to doing this. If you have a method like this, you won't be able to do any write activities down the wrode like @photos.build
or @photos.create
because you won't know where you're putting them. They could be linked to the Item
or the Posession
.
I think you're better of pushing the conditional logic out to your controller and checking for photos on the Posession
first and then on the Item
.
#In the controller
@photos = @posession.photos
@photos = @posession.item.photos if @photos.size == 0
This will be more clear when you go to maintain your code later, and it will allow you to make other decisions down the road.
精彩评论