如何同时使用活动记录更新列?

时间:2019-05-18 08:14:57

标签: ruby-on-rails activerecord concurrency

这是我的模特-用户,用户设备,设备。

表中包含以下列:

用户-ID,姓名,电子邮件,电话等

设备-ID,IMEI,型号等

user_devices-ID,user_id,device_id等。

现在,我在设备trk中添加了新列,并希望将其更新为1,以供大量用户使用。

这是我的模特的样子。

class User < ActiveRecord::Base
  has_many :user_devices
  has_one :some_model
  # ....
end

class Device < ActiveRecord::Base
  has_many :user, through: :user_devices
  attr_accessor :device_user_phone
  # ....

  # some callbacks which depend on on trk & device_user_phone
end

class UserDevice < ActiveRecord::Base
  belongs_to :device
  belongs_to :user
  # ....
end

csv文件中提供了用户ID列表,如下所示:

1234
1235
1236
....

这是我到目前为止尝试过的方法,但是它一次又一次地更新,并且花费很多时间。另外,我不能使用update_all,因为我想触发call_backs。

def update_user_trk(user_id)
  begin
    user = User.find_by(id: user_id)
    user_devices = user.user_devices
    user_devices.each do |user_device|
      user_device.device.update(trk: 1, device_user_col: user.some_model.col) if user_device.device.trk.nil?
    end
  rescue StandardError => e
    Rails.logger.error("ERROR_FOR_USER_#{user_id}::#{e}")
  end
end

def read_and_update(file_path)
  start_time = Time.now.to_i
  unless File.file? file_path
    Rails.logger.error("File not found")
  end
  CSV.foreach(file_path, :headers => false) do |row|
    update_user_trk(row[0])
  end
  end_time = Time.now.to_i
  return end_time-start_time
end

由于这会顺序更新一行,所以要花很多时间,我想知道是否可以同时执行以加快速度。

Ruby版本:ruby-2.2.3 rails版本:Rails 4.2.10

1 个答案:

答案 0 :(得分:0)

这至少要快一点,这样您就不必在每次更新时都创建和提交新事务。

user = User.find_by(id: user_id)
user.user_devices.each do |user_device|
  if user_device.device.trk.nil?
    user_device.device.trk = 1
    user_device.device_user_col = user.some_model.col
  end
end

user.save