Удалить отношение в модели Rails - PullRequest
0 голосов
/ 03 июля 2018

Я использую рельсы 5 и у меня есть ActiveRecord 'Report' с отношением один-ко-многим, называемым дозировками.

Если в новом отчете:

report.dosages.size   # Returns 0
report.dosages.build
report.dosages.size   # 1, correct
report.dosages.first.destroy
report.dosages.size  # Still 1 !

Я понимаю, что он установил дозировку как "уничтоженную", но возможно на самом деле удалить ее из списка отношений? (Я не могу сохранить отчет на БД до позже)

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

TL; DR: это будет делать то, что вам нужно:

report = Report.first
dosage = report.dosages.build
report.dosages.size // 1
to_delete_dosage = report.dosages.first
report.dosages.delete(to_delete_dosage)
report.dosages.size // 0

Для получения дополнительной информации, проверьте документы для ActiveRecord_Associations_CollectionProxy::delete


Сначала ActiveRecord::Relation#build является псевдонимом для ActiveRecord::Relation#new:

Новые объекты могут быть созданы как пустые (не передавая параметр построения) или предварительно заданные с атрибутами, но еще не сохраненные (передайте хеш с именами ключей, соответствующими именам столбцов связанной таблицы). В обоих случаях допустимые ключи атрибутов определяются именами столбцов связанной таблицы - следовательно, у вас не может быть атрибутов, которые не являются частью столбцов таблицы.

Если вы хотите удалить первый элемент, вам нужно сохранить его в базе данных, в противном случае rails сделает именно то, что вы испытали, установите флаг уничтожения.

Попробуйте следующую последовательность:

report = Report.first
dosage = report.dosages.build
dosage.save
report.dosages.size   # 1
report.dosages.first.destroy
report.dosages.size  # 0

Я установил эквивалент вашего вопроса, и это вывод:

Ваш сценарий:

2.4.0 :007 > r.dosages.build
 => #<Dosage id: nil, title: nil, created_at: nil, updated_at: nil, report_id: 1>
2.4.0 :008 > r.dosages.size
 => 1
2.4.0 :009 > r.dosages.first.destroy
   (0.1ms)  begin transaction
   (0.0ms)  commit transaction
 => #<Dosage id: nil, title: nil, created_at: nil, updated_at: nil, report_id: 1>
2.4.0 :010 > r.dosages.size
 => 1

Мое предложение:

2.4.0 :005 > report = Report.first
  Report Load (0.1ms)  SELECT  "reports".* FROM "reports" ORDER BY "reports"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<Report id: 1, title: nil, date: nil, created_at: "2018-07-03 14:00:08", updated_at: "2018-07-03 14:00:08">
2.4.0 :006 > report.dosages.count
   (0.1ms)  SELECT COUNT(*) FROM "dosages" WHERE "dosages"."report_id" = ?  [["report_id", 1]]
 => 0
2.4.0 :007 > dosage = report.dosages.build
 => #<Dosage id: nil, title: nil, created_at: nil, updated_at: nil, report_id: 1>
2.4.0 :008 > dosage.save
   (0.1ms)  begin transaction
  SQL (0.7ms)  INSERT INTO "dosages" ("created_at", "updated_at", "report_id") VALUES (?, ?, ?)  [["created_at", "2018-07-03 14:06:08.709323"], ["updated_at", "2018-07-03 14:06:08.709323"], ["report_id", 1]]
   (0.9ms)  commit transaction
 => true
2.4.0 :009 > report.dosages.size
   (0.2ms)  SELECT COUNT(*) FROM "dosages" WHERE "dosages"."report_id" = ?  [["report_id", 1]]
 => 1
2.4.0 :010 > report.dosages.first.destroy
  Dosage Load (0.2ms)  SELECT  "dosages".* FROM "dosages" WHERE "dosages"."report_id" = ? ORDER BY "dosages"."id" ASC LIMIT ?  [["report_id", 1], ["LIMIT", 1]]
   (0.0ms)  begin transaction
  SQL (0.3ms)  DELETE FROM "dosages" WHERE "dosages"."id" = ?  [["id", 1]]
   (0.8ms)  commit transaction
 => #<Dosage id: 1, title: nil, created_at: "2018-07-03 14:06:08", updated_at: "2018-07-03 14:06:08", report_id: 1>
2.4.0 :011 > report.dosages.size
   (0.2ms)  SELECT COUNT(*) FROM "dosages" WHERE "dosages"."report_id" = ?  [["report_id", 1]]
 => 0

Я верю, что это то, что вам нужно. Отношения установлены как:

dosage.rb
class Dosage < ApplicationRecord
  belongs_to :report
end

report.rb
class Report < ApplicationRecord
  has_many :dosages
end

И следующие миграции:

class ManyDosagesToReport < ActiveRecord::Migration[5.0]
  def change
    add_column :dosages, :report_id, :integer
  end
end

На самом деле, если вы попытаетесь сохранить объект dosage, который вы создали, но не сохранили, Rails будет жаловаться:

RuntimeError: can't modify frozen Hash

из-за атрибута destroyed.

0 голосов
/ 03 июля 2018

Если я вас правильно понимаю, вы хотели бы удалить дозировку из БД, следовательно, отобразив дозировку как deleted, но все равно хотели бы сохранить объект отчета? Если это ваш вариант использования, то сначала вы должны знать, что отчет останется вне зависимости от удаляемой дозировки, так как это соотношение 1- * (один ко многим), однако вам нужно взглянуть на разницу между delete и destroy, на которое сообщество stackoverflow помогло ответить здесь Разница между уничтожением и удалением

В качестве бонуса, взгляните на метод Шебанга (!) В ruby ​​и когда его использовать, например. delete! destroy!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...