【问题标题】:If User exists update variables, else Create new (find_or_create_by)如果用户存在更新变量,否则创建新的(find_or_create_by)
【发布时间】:2014-05-06 17:04:11
【问题描述】:

我正在从 CSV 文件导入数据(使用 Smarter CSV)。我在任务中按如下方式处理此文件:

require 'smarter_csv'

desc "Import Players from World data"

task :import => [:environment] do

  file = "db/data/players.txt"

  SmarterCSV.process(file, {
    :user_provided_headers => [
      "grepo_id", "name", "alliance_id", "points", "rank", "towns"
    ], headers_in_file: false
  }) do |array|

    # post-process the data from each row
    array.each do |a|
      a[:name] = CGI::unescape(a[:name]).force_encoding('UTF-8')
    end

    # Create Player
    Player.create(array.first)

  end

end

:user_provided_headers 可以看到传递给每个玩家的变量。

变量'grepo_id''name' 始终保持不变,但其他变量会随着时间而变化。

我正在尝试Find_or_createUpdate 给定用户。对于引用用户,我使用'grepo_id',因为这个变量对每个玩家都是唯一的。

但似乎我错过了一些东西,无论我尝试什么都去游泳,我认为我在这里弄错了方法。

在这种情况下我能做什么:

  • Find_by 'grepo_id'
  • 如果存在更新其他变量(如果有任何变化)
  • 如果不存在,则创建。

干杯

编辑:来自 Smarter CSV 文档

SmarterCSV.process(filename) do |array|
  # we're passing a block in, to process each resulting hash / =row (the block takes array of hashes)
  # there is only one hash in each array
  MyModel.create( array.first )
end

【问题讨论】:

    标签: ruby-on-rails ruby csv import


    【解决方案1】:

    试试这个 - 我假设你想对这里的所有行都这样做,而不是第一行,但如果不是这样,你可以更改

    @users = []
    array.each do |row|
      row[:name] = CGI::unescape(row[:name]).force_encoding('UTF-8')
      user = User.find_by_grepo_id(row[:grepo_id]) || User.new
      user.update_attributes(row)
      @users << user
    end
    

    【讨论】:

    • 你能解释一下为什么我们需要使用 player = [] 和 player
    • 您可以在这里使用map,然后将数组返回给@users
    • 确实如此,但通常您可能希望在结果视图页面上显示新创建的播放器,或类似的东西。如果不是,那么是的,您不需要将它们收集在变量中。
    • @engineersmrsky 你可以,但我从不喜欢在地图块内进行永久性更改:感觉不对。对我来说,“地图”应该只用于获取数据,而不是进行更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    相关资源
    最近更新 更多