如何更新连接模型的额外属性?

How to update extra attributes on a join model?

我有三个使用 has_many through 关联关联的模型。在阅读了一些文档后,我决定使用这个模型:"You should use has_many :through if you need validations, callbacks, or extra attributes on the join model."

Docs

user.rb

has_many :orders
has_many :vendors, through: :orders

order.rb

belongs_to :user
belongs_to :vendor

vendor.rb

has_many :orders
has_many :users, through: :orders

模式看起来像这样

  create_table "orders", force: :cascade do |t|
    t.integer "vendor_id"
    t.integer "user_id"
    t.integer "servings", default: 1, null: false
    t.string "location"
    t.string "payment_method"
    t.boolean "paid", default: false, null: false
    t.boolean "dispatched", default: false, null: false
    t.boolean "delivered", default: false, null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "meal_id"
    t.index ["user_id"], name: "index_orders_on_user_id"
    t.index ["vendor_id"], name: "index_orders_on_vendor_id"
  end

所以现在,我正在寻找如何更新订单模型中的属性,特别是布尔值。

我尝试过的:

def dispatched
    v = Vendor.find_by(vendorname: params[:_vendorname])
    order= Order.where(id: params[:order_id], vendor_id: v.id)

    order.dispatched = !order.dispatched

    json: order, status: :ok 
end

当这不起作用时,我想如果我从模型本身调用一个函数,我就可以更新它。

#order_controller.rb

def dispatched
    v = Vendor.find_by(vendorname: params[:_vendorname])
    order= Order.where(id: params[:order_id], vendor_id: v.id)

    order.order_dispatched!

    json: order, status: :ok 
end

#order.rb
 def order_dispatched!
    self.dispatched = !self.dispatched
    save!
end

第一次尝试时,我得到的错误是 undefined_method for dispatched,在第二次尝试中,我得到的错误是 undefined_method for order_dispatched!

我想我可能没有完全理解文档中传递的内容。或者,这可能不是处理此类关系的理想方式。我也查过答案,但是有几个老问题没有答案

Order.where(id: params[:order_id], vendor_id: v.id) returns ActiveRecord::Relation,不是 Order 实例。

如果你不关心性能,你可以使用each迭代关系。

# Before
order.order_dispatched!

#After
order.each {|o| o.order_dispatched!}

如果您打算 Order.where(id: params[:order_id], vendor_id: v.id) 到 return 只有一个实例,您应该使用 find_by 而不是 wherefind_by return只有一条记录符合给定的条件。

# Before
order= Order.where(id: params[:order_id], vendor_id: v.id)

#After
order= Order.find_by(id: params[:order_id], vendor_id: v.id)