在 rails 中,模型的实例没有出现在我的 table 中。当控制台显示 "COMMIT" 和“=>true”时发生了什么?

In rails, the instance of the model doesn't show up in my table. What is happening when the console says "COMMIT" and "=>true"?

我是 Rails 上 Ruby 的新手,遇到了一些问题。 我已经签出:This Whosebug question about cloning a model

我正在为如下所示的模型创建新方法:

def copy(new_period)
@copy = self.clone
@copy.report_id = Report.maximum(:report_id).next
@copy.period_id = new_period
@copy.save
end

我正在尝试创建一个可以移动到下一年(期间)的新报告实例。当我在 irb 中 运行 这个方法时,我得到:

irb(main):003:0> c = r.copy(5)

(1.8ms) SELECT MAX("reports"."report_id") AS max_id FROM "reports"

(0.8ms) BEGIN

(1.0ms) UPDATE "reports" SET "period_id" = 5 WHERE "reports"."report_id" = 438

(1.1ms) COMMIT

=> true

当我查看 pgAdmin 时,新报告不存在。有人可以向我解释当控制台显示“commit”和“=> true”时发生了什么吗?这不是说已经存入数据库了吗?

您正在更新旧模型,因为模型的 id 仍然设置。您可以看到,因为您的控制台显示 UPDATE 而不是 INSERT 语句。

来自Docs for ActiveRecord::Core#clone:

Identical to Ruby's clone method. This is a “shallow” copy. Be warned that your attributes are not copied. That means that modifying attributes of the clone will modify the original, since they will both point to the same attributes hash. If you need a copy of your attributes hash, please use the dup method.

ActiveRecord::Core#dup 但是会产生新记录:

Duped objects have no id assigned and are treated as new records. Note that this is a “shallow” copy as it copies the object's attributes only, not its associations. The extent of a “deep” copy is application specific and is therefore left to the application to implement according to its need. The dup method does not preserve the timestamps (created|updated)_(at|on).


关于你的附带问题:

  • BEGINCOMMIT用于开始和结束SQL中的事务。
  • truer.copy 的结果,它隐含 returns @copy.safe 的值,如果模型保存成功,则 returns 为真。

把方法改成这样试试:

def copy(new_period)
  @copy = self.dup
  @copy.report_id = Report.maximum(:report_id).next
  @copy.period_id = new_period
  @copy.save
end

因为要获得副本,请使用克隆(或 rails 3.1 的复制)方法:

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup

那么您正在克隆的当前情况是什么,它没有创建新记录,它只是每次都更新以前的记录。如果您仔细阅读您的查询:

(1.8ms) SELECT MAX("reports"."report_id") AS max_id FROM "reports"
(0.8ms) BEGIN
(1.0ms) UPDATE "reports" SET "period_id" = 5 WHERE "reports"."report_id" = 438
(1.1ms) COMMIT

首先选择记录,然后更新它,而不是创建新记录 (INSERT) 查询。

希望对您有所帮助。