【问题标题】:Rails - how to update existing record in database with a newly created objectRails - 如何使用新创建的对象更新数据库中的现有记录
【发布时间】:2019-08-28 02:34:22
【问题描述】:

我正在从 CSV 文件中获取数据并将它们保存到数据库中。这是简化的代码结构(这是一个 rake 任务):

... loading CSV tools...
car = Car.new
car.tender_load_id = data.element[8]
car.brand = data.element[2]
car.color = 'green'
...
car.build_car_metadata(mbol: help_var[:mbol], ...)
car.first_registration = data.element[21]

car.skip_registration_code_validation = true # for not creating registration_code

if existing_car = Car.where("cars.tender_load_id ILIKE ?", "%#{car.tender_load_id}%").first
  # car already exists => update
  existing_car.update(car)
  puts "Car exists, updating car with ID #{existing_car.id}."
else
  car.save!            
end

当我运行这个拍摄任务时,我收到以下错误消息:

NoMethodError: undefined method `reject' for #<Car:0x007fa3e2063a78>

它指出了这一行:

existing_car.update(car)

我该如何进行这项工作?不幸的是,我不能将if-else 部分放在 rake 任务的开头,结构需要是这样的。

提前谢谢你。

【问题讨论】:

  • @anothe 否,如果未找到记录,则不会“返回”true。不过我会添加括号。

标签: ruby-on-rails ruby activerecord


【解决方案1】:

你需要只用属性更新现有的汽车,你不能传入一个完整的模型。

构建属性,然后根据汽车是否已经存在来创建或更新:

attributes = {}
attributes[:color] = ...
attributes[:brand] = ...
attributes[:tender_load_id] = ...


if (car = Car.where("cars.tender_load_id ILIKE ?", "%#{attributes[:tender_load_id]}%").first)
  car.update(attributes)
else
  Car.create!(attributes)
end

注 1:似乎可以有多辆汽车具有相同的tender_load_id。这意味着对现有汽车的查询将返回任意记录。也许您想在该查询中添加order

注意 2:您查询的方式似乎很脆弱。 CSV中没有更好的ID吗?

注意 3:以_id 结尾的属性通常是外键。所以也许为这个属性找到一个更好的名字。

【讨论】:

  • 嗨@Pascal,谢谢你的回答。因为Car 模型的属性太多,所以我用car.attributes.except!("id") 转换了它们,它就像一个魅力。但是,有没有办法自动更新具有has_many 关系的模型?
  • 您能否详细说明您想要更新的关系?
  • 都是Car -> has_many -> car_metadata等等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
相关资源
最近更新 更多