Assign_attributes назначает дочерние значения attr_accessor, только если столбец таблицы изменяется при обновлении - PullRequest
0 голосов
/ 25 апреля 2020

Вот настройка

class Order
  has_many :items
  accepts_nested_attributes_for :items
end

class Item
  belongs_to :order
  attr_accessor :discount # this is NOT a table column, just a virtual attribute I want to be able to assign
end

Допустим, у меня есть существующий заказ @order. Я заметил, что если бы я попытался присвоить discount дочернему элементу Item из модели Order, это работает, только если какой-либо другой атрибут дочернего элемента Item изменяется.

@order.assign_attributes({"items_attributes"=>[{"id"=>40, "discount"=>"test"}]})
@order.items.first.discount
=> nil

@order.assign_attributes({"items_attributes"=>[{"id"=>40, "discount"=>"test", "admin_notes"=>"hello}]})
# where admin_notes is a table column for Item
@order.items.first.discount
=> "test
@order.items.first.admin_notes
=> "hello"

Есть ли быстрое изменение настроек или что-то, чтобы это изменить? Мне бы хотелось, чтобы атрибуты attr_accessor назначались всегда, даже если атрибуты не меняются?

1 Ответ

0 голосов
/ 25 апреля 2020

Я вижу, что ваш оригинальный вопрос попросил использовать attr_accessor, однако это не представляется возможным. Я смог заставить это работать, только удалив attr_accessor.

Похоже, что attr_accessor на самом деле имеет противоположное поведение - сделать атрибут недоступным вместо того, чтобы разрешить его при использовании accepts_nested_attributes_for. Возможно, ошибка? Документы не дают никаких примеров. Пока вы делаете params.permit на стороне контроллера, все еще безопасно использовать без attr_accessor.

class Order
  has_many :items
  accepts_nested_attributes_for :items
end

class Item
  belongs_to :order
end

Вызов его из консоли Rails:

@order = Order.find(1)
@order.assign_attributes({"items_attributes"=>[{"id" => 1, "discount_cents" => "234"}]})
@order.save

#  Order Load (0.4ms)  SELECT "orders".* FROM "orders" WHERE "orders"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
#  Item Load (0.3ms)  SELECT "items".* FROM "items" WHERE "items"."order_id" = $1 AND "items"."id" = $2  [["order_id", 1], ["id", 1]]
#   (0.1ms)  BEGIN
#  Item Update (0.3ms)  UPDATE "items" SET "discount_cents" = $1 WHERE "items"."id" = $2  [["discount_cents", 234], ["id", 1]]
# => true
#   (5.8ms)  COMMIT

@order.assign_attributes({"items_attributes"=>[{"id" => 1, "discount_cents" => "789"}]})
# => nil
#  Item Load (0.4ms)  SELECT "items".* FROM "items" WHERE "items"."order_id" = $1 AND "items"."id" = $2  [["order_id", 1], ["id", 1]]
@order.items.first.attributes
# => {"order_id"=>1, "id"=>1, "discount_cents"=>789}

Надеюсь, что это даст решение вашего вопроса:)

...