In a Rails project, i need a user to have an inventory and a warehouse. Items can be exchanged. The question is, what is the most efficient way to handle this ? I thought of :
User has one inventory -> inventory has many items through inventory_item
User has one warehouse -> warehouse has many items through warehouse_item
However, i’m not so sure whether this is the most efficient way. Another idea would be so have a user_item with a field like location that can either be inventory or warehouse.
What do you think is the best practice ?
I would probably do a combination of both. I would have an association for the owner for every item and then an association for the place or position of the item. Both of those would probably be polymorphic. I think that would be the best way to fit some of the likely scenarios like:
Thinking of these scenarios I think it is more db query effective to be able to load all items owned by a player without looping through inventories, warehouses etc or to be able to get all items equipped by a player without looping through different owners etc.
Edit
Here is an example:
In the above example I left out the possibility of a guild or something similar being the owner of an item but I added comments on where it could easily be adapted to support such a thing.
So if you look at the OwnedItem class, position is the polymorphic association the specifies where the item is located at the moment (an inventory, a warehouse, etc) and then it also belongs_to a user which specifies who the owner of the item is. Now you asked about it being redundant and I assume you mean that it could potentially be found by checking the item’s inventory and see who that inventory belongs_to. Yes, of course that is possible. But then it would not be possible to have an item in the inventory that does not belong to you, i.e. a “guild item”.
But even if you choose not to add something like guilds, I would still recommend to have the OwnedItem belong_to a user. An example to support that would be if you plan on some items being “unique” as in a user can only have one item of that kind. Instead of check both the invetory and warehouse (and possible something else) you can just specify:
in the OwnedItem class and you’re good to go.
My point being that all restrictions, queries and comparisons can be made more db time saving if you have both an owner and a position for an item.