【问题标题】:Associated object not created, duplicate empty insert statement created for original object created (Rails)未创建关联对象,为创建的原始对象创建了重复的空插入语句(Rails)
【发布时间】:2014-05-01 13:36:49
【问题描述】:

我有一个相当简单的有很多/属于关系模型:报告有很多记录有很多相关发布者。所属对象有一个外键来标识它们的父对象。

但是,我无法保存任何“相关发布者”。或者更确切地说,我“可以”,提交事务返回 true,但未创建相关记录,相应的 SQLite3 命令没有意义。

为什么 Rails 生成的 SQLite 动作是创建空 Record 的命令?为什么要绕过相关发布者的保存?

rails console,部分输出被截断

> @report = Report.new => #<Report id: nil, ... >
> @record = @report.records.build(leid: 1234567890) => #<Record id: nil, leid: 1234567890, ...>
> @related_publisher = @record.related_publishers.build(sid: 9876)
 => #<RelatedPublisher id: nil, ..., sid: 9876, ...>
> @report.save
   (0.1ms)  begin transaction
  SQL (4.5ms)  INSERT INTO "reports" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Wed, 07 May 2014 11:20:50 UTC +00:00], ["updated_at", Wed, 07 May 2014 11:20:50 UTC +00:00]]
  SQL (0.2ms)  INSERT INTO "records" ("created_at", "leid", "report_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Wed, 07 May 2014 11:20:50 UTC +00:00], ["leid", 1234567890], ["report_id", 22], ["updated_at", Wed, 07 May 2014 11:20:50 UTC +00:00]]
  SQL (0.3ms)  INSERT INTO "records" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Wed, 07 May 2014 11:20:50 UTC +00:00], ["updated_at", Wed, 07 May 2014 11:20:50 UTC +00:00]]
   (0.7ms)  commit transaction
 => true
> RelatedPublisher.all
RelatedPublisher Load (0.3ms)  SELECT "related_publishers".* FROM "related_publishers"
 => #<ActiveRecord::Relation []>

(在 Mac OSX 10.9.2 上使用 Rails 4.0.4 和 sqlite3 3.7.13 以及 gem 版本 1.3.9 和 Ruby 2.0.0p353


app/models/report.rb

class Report < ActiveRecord::Base
  has_many :records
end

app/models/record.rb

class Record < ActiveRecord::Base
  belongs_to :report

  has_many :related_publishers
end

app/models/related_publisher.rb

class RelatedPublisher < ActiveRecord::Base
  belongs_to :record
end

来自schema.rb

  create_table "records", force: true do |t|
    t.integer  "leid"
    t.integer  "sid"
    t.string   "name"
    t.string   "url"
    t.string   "join_date"
    t.string   "join_ip"
    t.string   "country"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "report_id"
    t.boolean  "ipAddressMatch"
    t.boolean  "whoisAddressMatch"
    t.integer  "recommendation"
  end

  add_index "records", ["report_id"], name: "index_records_on_report_id"

  create_table "related_publishers", force: true do |t|
    t.integer  "leid"
    t.integer  "sid"
    t.string   "name"
    t.string   "url"
    t.string   "join_date"
    t.string   "join_ip"
    t.string   "country"
    t.integer  "record_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "related_publishers", ["record_id"], name: "index_related_publishers_on_record_id"

  create_table "reports", force: true do |t|
    t.integer  "report_type"
    t.string   "upload_data_file_path"
    t.string   "completed_data_file_path"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "ltn_username"
  end

【问题讨论】:

  • 你做了x = @record.related_records.new,这将创建一个新的空白对象。然后你x.save,它保存了空白对象。
  • 谢谢,@JustinWood 你是对的:那是构建对象的错误方法。不幸的是,问题仍然存在——请查看已编辑的问题。

标签: ruby-on-rails ruby activerecord ruby-on-rails-4 sqlite


【解决方案1】:

我在建立关联时没有看到#new。引用Active Record Associations docs你会发现

4.3.1.14 collection.build(attributes = {}, ...)

collection.build 方法返回一个或多个相关类型的新对象。这些对象将从传递的属性中实例化,并通过其外键创建链接,但尚未保存关联的对象。

这似乎是您希望在 irb 会话中实现的目标。在你的情况下,这应该转化为

@record.related_records.build(val: "related")
@record.save

(注意你save父母,它也会存储它改变的孩子)

你也可以使用

4.3.1.15 collection.create(attributes = {})

collection.create 方法返回关联类型的新对象。该对象将从传递的属性中实例化,通过其外键的链接将被创建,并且一旦它通过关联模型上指定的所有验证,关联的对象将被保存。

如果应该立即保存新创建的记录(并且已经保存了父对象)。

【讨论】:

  • 非常有帮助,谢谢@Patru。不幸的是,可用的方法似乎落后了,因此 build_related_record 不可用:/(参见对原始问题的编辑。)你能再帮忙吗?
  • 对不起,我引用了错误的部分,4.1 处理belongs_to,正如你正确确定的那样,4.3 处理has_many,在那里你会发现4.3.1.14 collection.build(attributes = {}, …) 转换为@record.related_records.build(…)你的情况。所以你比我想象的要近得多。晚餐后将不得不更新我的答案......
  • 很抱歉这样做,但我仍然遇到非常相似的怪异现象:INSERT INTO "records" 正在该表中生成错误数据,并且没有任何相关记录的迹象——请参阅最新的编辑。
  • 好吧,那我很抱歉。我刚刚在我的一个has_many-relations 上尝试了这个,它生成了一个完美的insert。我真的很茫然,为什么您的模型会尝试插入 records 表。 insert 似乎很空,你能在你的.build 调用中添加一个RelatedRecord 的属性吗?我简直不敢相信这张桌子弄错了并且它试图将insert 转换为records 而不是update。你能打印@record 对象吗?
  • 我想我现在已经有了所有的细节,你可以看到我正在将一个属性传递给构建。我还重新构建了应用程序以尝试降低调查错误的复杂性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多