settheline
settheline

Reputation: 3383

Creating an auto-updating list in Rails

I have three relevant models:

class InventoryItem < ActiveRecord::Base
    belongs_to  :item, :foreign_key => :item_id
    belongs_to  :vendor
    has_many    :shopping_list_items

class ShoppingList < ActiveRecord::Base
    has_many    :shopping_list_items
    belongs_to  :user
end

class ShoppingListItem < ActiveRecord::Base
  belongs_to    :shopping_list
  belongs_to    :inventory_item
end

What I am trying to do is create a sidebar shopping list that will autoupdate ShoppingListItem attributes (specifically price) when a respective attribute is changed in the InventoryItem table (again, price). My thinking was to have these three classes and map ShoppingListItems directly to InventoryItems, but I'm unsure of how to proceed with that. Alternatively, is it possible to do away with the ShoppingListItem class entirely and make ShoppingList be a collection of InventoryItems specified by the user? Any input is much appreciated. Thanks in advance!

Upvotes: 0

Views: 184

Answers (1)

DigitalCora
DigitalCora

Reputation: 2232

To redo my comments as a real answer, yes, it is possible to forego the ShoppingListItem model in this case, as long as you don't need to attach any data to that model itself (e.g. the time the item was added to the list). You could link your models as follows with a has_and_belongs_to_many association:

class InventoryItem < ActiveRecord::Base
    belongs_to :item
    belongs_to :vendor
    has_and_belongs_to_many :shopping_lists
end

class ShoppingList < ActiveRecord::Base
    belongs_to :user
    has_and_belongs_to_many :inventory_items
end

This will allow you to assign an array of inventory items to the inventory_items attribute of a shopping list, and Rails will create or delete the necessary join records automatically. More information from the Rails guides. Note that you'll still need a join table in your schema -- there just isn't a model associated with it. In your case, the migration might look like this:

create_table :inventory_items_shopping_lists, id: false do |t|
  t.references :inventory_item
  t.references :shopping_list
end

add_index :inventory_items_shopping_lists, :inventory_item_id
add_index :inventory_items_shopping_lists, :shopping_list_id
add_index :inventory_items_shopping_lists, [:inventory_item_id, :shopping_list_id], unique: true

Note that in order for Rails to auto-detect the table, its name should be the combined plural forms of both models in alphabetical order. Otherwise you need to specify the table name using the join_table option when defining the association.

Upvotes: 1

Related Questions