【发布时间】:2016-04-12 20:32:20
【问题描述】:
我有这些模型:
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
我想知道向用户添加项目并在连接表中设置数量的最佳方法。
我正在做这样的事情:
user = User.first
item = Item.first
UserItems.create(user: user, item: item, amount: 5)
但我不太喜欢它,有时它不能正常工作,因为如果我运行
user.items #=> []
我得到一个空数组,它似乎没有在 DB 中得到新的变化。
那么,有没有简单的方法可以做到这一点?像这样直观的东西会很完美:
user.user_items << item, amount: 4
好的,所以我这样做了,它奏效了:
user.user_items.create!(item: item, amount: 5)
但是这样就没有了:
user.user_items << item, amount: 4
现在它更优雅了。但我仍然有关于缓存请求的问题。如果我运行 user.items。它仍然是空的。任何想法?我试过用 inverse_of 什么都没有。我想避免重新加载或类似的方法。如果可能的话,我想以透明的方式进行
【问题讨论】:
-
user.items.reload?我的意思是,一切都完美存储,user.items因为缓存返回一个空数组。 -
我个人会选择这个 SO 答案 (stackoverflow.com/questions/31982343/…),它将为您提供所需的一切(包括设置金额值)。否则,您仍然可以分两行完成。
-
@mudasobwa,是的,没错,一切都完美存储。但是我认为如果我必须写
reload这不是一个好习惯,你不觉得吗?这就是为什么我正在寻找一种干净的方式来做到这一点。谢谢! -
如果你想要一个明确的说法“用户有 5 个项目”,你可以使用
User.first.user_items << [item] * 5,但你仍然需要调用 save 来使更改持久化。 -
这就是鸡蛋鸡的问题。要么你想要缓存,要么你不想要。您可以覆盖
def items; super.reload; end以禁用此特定元素的缓存,但通常模型无法知道不同表的数据库内容已更改。
标签: ruby-on-rails ruby has-many-through