尝试导入 CSV 文件会触发一个函数,该函数最终会操作导入到数据库中的数据

Pro*_*mer 5 ruby csv ruby-on-rails

就像问题所说,我正在尝试使用以下函数导入 CSV:

def import_users
  path = Rails.root.join('somePath')
  CSV.foreach(path, headers: true) do |row|
    usr = User.new(row.to_hash)
    usr.skip_callbacks = true
    usr.save
  end
  puts "inserts on table users complete"
end
Run Code Online (Sandbox Code Playgroud)

如您所知,这是一个简单的函数。

问题:

所有具有正确数据的列均已正确导入,但User Classpassword= function (setter)触发:

class User < ApplicationRecord

  attr_accessor :skip_callbacks
  validates :password, presence: true, unless: :skip_callbacks

  def password= password
    self[:password] = hash_password password
  end

  private
    
  def hash_password password
     Digest::MD5.hexdigest "#{Digest::MD5.hexdigest password}#{salt}"
  end
end
Run Code Online (Sandbox Code Playgroud)

这会导致数据库中的密码列被新的哈希值作为密码再次重写,从而阻止登录,因为列值已更改。数据库中的密码列不包含与 CSV 文件中相同的信息。

通常我实施了skip_callback绕过password validation但似乎不起作用。

我真的很感激任何形式的帮助,因为我已经尝试解决这个问题几天了,但似乎不明白为什么。

Pav*_*yan 1

看起来您想将密码按原样添加到数据库而不进行哈希处理,并且验证与此无关,因为它们不会改变函数的行为password=。您可以使用另一个实例变量来修补它,例如:

class User < ApplicationRecord

  attr_accessor :skip_callbacks
  attr_accessor :skip_password_hashing
  validates :password, presence: true, unless: :skip_callbacks

  def password= password
    self[:password] = skip_password_hashing ? password : hash_password(password)
  end

  private
    
  def hash_password password
     Digest::MD5.hexdigest "#{Digest::MD5.hexdigest password}#{salt}"
  end
end
Run Code Online (Sandbox Code Playgroud)

然后修补导入,例如:

def import_users
  path = Rails.root.join('somePath')
  CSV.foreach(path, headers: true) do |row|
    usr = User.new(row.to_hash)
    usr.skip_password_hashing = true
    usr.save
  end
  puts "inserts on table users complete"
end
Run Code Online (Sandbox Code Playgroud)

我不确定在已部署的应用程序中具有这种可能性是否是一个好主意,但它应该有效。