我正在使用rails 5,并且有一个ActiveRecord“报告”,具有一对多关系,称为“剂量”。
如果是新报告:
report.dosages.size # Returns 0
report.dosages.build
report.dosages.size # 1, correct
report.dosages.first.destroy
report.dosages.size # Still 1 !
我了解它已将剂量设置为“已销毁”,但实际上有可能将其从关系列表中删除吗? (我无法将报告保存到db上)
答案 0 :(得分:2)
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
有关更多信息,请检查文档中的https://github.com/yiisoft/yii2/issues/15776
首先,ActiveRecord::Relation#build
是ActiveRecord_Associations_CollectionProxy::delete
的别名:
新对象可以实例化为空(不传递任何构造参数)或具有属性的预设,但尚未保存(传递具有与关联表列名匹配的键名的散列)。在这两种情况下,有效的属性键均由关联表的列名确定-因此,您不能拥有不属于表列的属性。
如果要删除第一个元素,则必须将其持久保存到数据库中,否则rails会完全按照您的经验进行操作,请设置destroy flag。
尝试以下顺序:
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
属性。
答案 1 :(得分:0)
如果我对您的理解正确,您想从数据库中删除剂量,因此将剂量显示为deleted
,但仍然希望保留报告对象?如果这是您的用例,那么首先您应该知道该报告将保留,无论其删除的剂量是多少,因为它是1-*(一对多关系),但是您需要查看delete
之间的区别和destroy
,stackoverflow社区在这里Difference between Destroy and Delete
作为奖励,请看看ruby中的shebang(!)方法以及何时使用它,例如delete!
destroy!