Quin
Quin

Reputation: 83

Has many through: How to Add record and fill fields in join table

I have these models:

class Item < ActiveRecord::Base
  has_many :users, through: :user_items
  has_many :user_items
end

class User < ActiveRecord::Base
  has_many :items, through: :user_items
  has_many :user_items
end

class UserItem < ActiveRecord::Base
  belongs_to :user
  belongs_to :item
end

create_table "user_items", force: :cascade do |t|
  t.integer  "user_id",
  t.integer  "item_id",
  t.integer  "amount"
end

I'd like to know the best ways to add an item to a user an also set an amount in the join table.

I was doing something like this:

user = User.first
item = Item.first
UserItems.create(user: user, item: item, amount: 5)

but I don't like it so much, and sometimes it doesn't work properly, because if I run

user.items   #=> []

I get empty array, it seems like it doesn't get the new changes in DB.

So, is there an easy way to do that? something intuitive like this would be perfect:

user.user_items << item, amount: 4

Ok, so I did this way and it worked:

user.user_items.create!(item: item, amount: 5) 

But This way it didn't:

user.user_items << item, amount: 4 

Now it's more elegant. But I still have the problem about the caching request. If I run user.items. it is still empty. Any idea? I tried with inverse_of and nothing. I would like to avoid reload or some methods like this. I would like to do in a transparent way, if it is possible

Upvotes: 2

Views: 2001

Answers (2)

ZX12R
ZX12R

Reputation: 4828

Try this

user.user_items.push(item: item, amount: 5)

Or if you want to reflect items without pushing new values try this

UserItem.create(user: user, item: item, amount: 5)
user.reload
user.items # this will reflect newly loaded values now

Upvotes: 0

Muhammad Ali
Muhammad Ali

Reputation: 2183

You can do this like :

user = User.first
item = Item.first
user.user_items.create!(item_id: item.id, amount: 5)

or:

user.items.push(items)

Upvotes: 1

Related Questions