【问题标题】:How can I update specific row in db with csv file?(rails)如何使用 csv 文件更新 db 中的特定行?(rails)
【发布时间】:2025-12-22 07:25:07
【问题描述】:

我使用 csv 文件作为 MySQL 数据库的初始数据。下面的方法是针对那个导入过程的。(我之前在这里*问过,所以可能是我直到现在才完全理解这个过程..)

# lib/tasks/import.rake
require 'csv'

namespace :db do
  task :restaurants => :environment do
    CSV.foreach('public/seed_data/restaurants.csv') do |row|
      record = Restaurant.new(
        :name => row[0],
        :addr => row[1]
      )
      record.save!
    end
  end
end

但现在我必须更新一些在我第一次导入数据库后发生变化的特定行。所以我只是改变了我的第一种方法,如下所示。我的 update.csv 文件有 id、name(updated)、addr(updated) 列,没有头。

# lib/tasks/import.rake
require 'csv'

namespace :db do
  task :restaurants_update => :environment do
    CSV.foreach('public/seed_data/update.csv') do |row|
      n = row[0]
      record = Restaurant.find(n)
      record.update_attributes(
        :name => row[1],
        :addr => row[2]
      )
      record.save!
    end
  end
end

我认为它可以读取具有要更新餐厅 ID 的 row[0] 的特定行,然后使用以下内容(row[1] 和 row[2])更新名称和地址。但是,当我执行 rake db:restaurants_update 时,它会显示 ActiveRecord::RecordNotFound: Couldn't find Restaurant with id=1000001(这是我在 csv 文件中的第一行,我的数据库中有这条 id 为 1000001 的记录。我在控制台Restaurant.find(1000001) 中检查了它。我认为 import.rake 可能会丢失我的记录。(无法读取现有数据库?)

谁能指出我的错误?

【问题讨论】:

  • 我不确定但是,你可以尝试使用Restaurant.find_by_id(n),我认为存储在 CSV 中的值是不同的格式
  • 可以查看row[0]的值,row是hash所以r_hash = row.to_hash, rest = Restaurant.where(id: r_hash["id"]), rest.first.update_attributes(r_hash)
  • @Sontya 我试过你说的,得到了​​这个NoMethodError: undefined method to_hash for ["1000001", nil, nil]:Array。这样对吗?当我尝试find_by_id(n)时,我得到了NoMethodError: undefined method 'update_attributes' for nil:NilClass
  • 对不起老兄,我的坏,行是一个数组n = row[0], record = Restaurant.where(id: n), record.first.update_attributes(attributes u want to update),如果它适合你试试这个
  • 之前多亏了你们的cmets,我也可以尝试一下(我不知道查找方法会产生一些问题)。但是弹出同样的错误no method for nil .....................有没有其他建议寻找?

标签: mysql ruby-on-rails csv rake rails-activerecord


【解决方案1】:

如果您只是更新,请使用find_by(id: n)。就个人而言,我推荐find_or_create_by,它会更新该字段或创建一个新字段(如果它不存在)。

# lib/tasks/import.rake
require 'csv'

namespace :db do
  task :restaurants_update => :environment do
    CSV.foreach('public/seed_data/update.csv') do |row|
      n = row[0]
      record = Restaurant.find_or_create_by(id: n)
      record.update_attributes(
        :name => row[1],
        :addr => row[2]
      )
      record.save!
    end
  end
end

【讨论】: