【问题标题】:Rails 5 - Rake task to import data from CSV fileRails 5 - 从 CSV 文件导入数据的 Rake 任务
【发布时间】:2017-05-03 11:09:00
【问题描述】:

我正在尝试将保存在 xls 中的数据上传到我的 rails db。我已经尝试了几个不同的教程来完成这项工作,并概述了我在下面每个问题上遇到的问题。我不介意我最终使用哪种方法,我只是想不出如何尝试使用这些方法中的任何一种来解决这个问题。

Importing CSV files by RichonRails

型号:

class Randd::Field < ApplicationRecord

    require 'csv'


  def self.import(file)
    CSV.foreach(file.path, headers: true) do | row |
            randd_field_hash = row.to_hash
            randd_field = Randd::Field.where(id: randd_field_hash["id"])
            if randd_field.count == 1
                randd_field.first.update_attributes(randd_field_hash)
            else
                Randd::Fields.create!(randd_field_hash)
            # else
            # Randd::Field.create! row.to_hash
    end
  end
end


end

路线:

namespace :randd do
resources :fields do
      collection {post :import }#do
        # post :create
      end
end

控制器:

class Randd::FieldsController < ApplicationController

def index
    @randd_fields = Randd::Field.all
end

def new
    @field = Randd::Field.new
end

def create
    # @field = Randd::Field.new(randd_field_params)
    Randd::Field.create(params[:randd_field][:file])
    redirect_to action: "index", notice: "Data imported"
end

def show
    redirect_to action: "index"
end

def import
    Randd::Field.import(params[:file])
    # Randd::Field.create(params[:randd_field]['file'])
    redirect_to action: "index", notice: "Data imported"
end

private
 def randd_field_params
  params.fetch(:randd_field, {}).permit(:title, :anz_reference)
 end

end

当我保存并尝试时,我收到一条错误消息:

undefined method `path' for nil:NilClass

错误信息指向模型中的导入方法

GoRails 教程

我尝试按照 GoRails 教程从 csv 文件导入数据。

在我的 rails 应用程序中,我已将文件保存为 for_codes.csv。

在我的 lib/tasks 文件夹中,我创建了一个名为:import.rake 的文件

在我的 input.rake 文件中,我有:

require 'csv'
namespace :import do

  desc "import research fields from csv"
  task rannd_fields: :environment do
    filename = File.join Rails.root, 'for_codes.csv'
    counter = 0

    CSV.foreach(filename, headers: true) do | row |
      p row ["anz_reference"]
      for_code = Randd::Field.create(anz_reference: row["anz_reference"], title: title)
      counter += 1 if randd_field.persisted?
    end
    puts "Imported #{counter} field codes"
  end
end

当我在控制台中尝试这个时,使用:

bundle exec rake import:randd_fields

我收到一条错误消息:

NameError: undefined local variable or method `randd_fields' for main:Object

我要记录的模型被称为:

class Randd::Field < ApplicationRecord

数据库中的表被调用:

randd_fields

谁能看到我需要做什么才能完成这项任务?

回溯

bundle exec rake import:rannd_fields
rake aborted!
ArgumentError: invalid byte sequence in UTF-8
/Users/live/lib/tasks/import.rake:9:in `block (2 levels) in <top (required)>'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/exe/rake:27:in `<top (required)>'
/Users/.rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `eval'
/Users/.rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => import:rannd_fields
(See full trace by running task with --trace)
MacBook-Pro:live em$ bundle exec rake import:rannd_fields --trace
** Invoke import:rannd_fields (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute import:rannd_fields
rake aborted!
ArgumentError: invalid byte sequence in UTF-8
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:2016:in `=~'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:2016:in `init_separators'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:1538:in `initialize'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:1273:in `new'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:1273:in `open'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/csv.rb:1130:in `foreach'
/Users/live/lib/tasks/import.rake:9:in `block (2 levels) in <top (required)>'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:248:in `block in execute'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:243:in `each'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:243:in `execute'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:187:in `block in invoke_with_call_chain'
/Users/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:180:in `invoke_with_call_chain'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/task.rb:173:in `invoke'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:152:in `invoke_task'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:108:in `block (2 levels) in top_level'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:108:in `each'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:108:in `block in top_level'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:117:in `run_with_threads'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:102:in `top_level'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:80:in `block in run'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:178:in `standard_exception_handling'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/lib/rake/application.rb:77:in `run'
/Users/.rvm/gems/ruby-2.3.1@global/gems/rake-11.3.0/exe/rake:27:in `<top (required)>'
/Users/.rvm/gems/ruby-2.3.1@global/bin/rake:23:in `load'
/Users/.rvm/gems/ruby-2.3.1@global/bin/rake:23:in `<main>'
/Users/.rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `eval'
/Users/.rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => import:rannd_fields

下一次尝试

接下来我尝试在我的 rails 应用程序中创建一个全新的文件。我输入了这三行:

anz_reference |标题 010104p |组合数学和离散数学(不包括物理组合) 010107p |数理逻辑、集合论、格和通用代数

第一行是标题。它们匹配 Randd::Field 模型上的属性。

接下来的两行是我尝试导入的内容。单元格值由 | 分隔(如 GoRails 视频中所示)。

当我尝试这个时,我得到了与上面发布的相同的错误:

$ bundle exec rake import:randd_fields --trace ** 调用导入:randd_fields (first_time) ** 调用环境(first_time) ** 执行环境 ** 执行导入:randd_fields 零 耙中止! NameError: main:Object 的未定义局部变量或方法“标题”

谁能看出我做错了什么?

我也试过这个教程 How to import CSV files in Rails by Matt Morgante 并尝试使用 rails cast 和 Roo gem 来达到同样的目的。这些选项都不起作用 - Rails Cast 很旧,所以可能已经过时了,并且在另一个教程的帖子中的 cmets 显示许多其他人无法使用这种方法 - 也许 Rails 中的事情已经改变了被提议。

GoRails 论坛上建议该问题可能是由于 CSV 文件未编码为 UTF-8 规范。有人建议可以通过将数据传输到谷歌驱动器中的工作表然后将其下载为 csv 以与 rails 一起使用来克服这个问题。我试过这个。

当我使用在 xls 中创建的文件运行 rake 任务时,我遇到了同样的错误。

钟的建议

接受钟的建议,我尝试将 import.rake 任务更改为:

require 'csv'
namespace :import do

  desc "import research fields from csv"
  task randd_fields: :environment do
    filename = File.join Rails.root, 'for_codes.csv'
    counter = 0

    CSV.foreach(filename, headers: true) do | row |
      p row ["anz_reference"]
      # for_code = Randd::Field.create(anz_reference: row["anz_reference"], title: title)
      for_code = Randd::Field.create(anz_reference: row["anz_reference"], title: row['title'])
      counter += 1 if for_code.persisted?
    end
    puts "Imported #{counter} field codes"
  end
end

当我尝试时

bundle exec rake import:randd_fields

我得到同样的错误:

bundle exec rake import:randd_fields
NameError: undefined local variable or method `randd_fields' for main:Object
    from (irb):6

【问题讨论】:

  • 试试 RanndField 作为类名。
  • 我应该在哪里写那个汤姆?你的意思是:for_code = RanddField.create 在 import.rake 文件中?
  • 作为你的类名而不是 Randd::Field
  • 嗨,汤姆 - 不,那是不正确的。资源字段在 Randd 文件夹内命名空间,所以模型名称是正确的我有它的方式。还是谢谢。
  • 我明白了。对不起。如果你还没有得到答案,我明天晚上再看。

标签: ruby-on-rails ruby csv import


【解决方案1】:

这里可能有两个问题。

  1. 在您的 csv 文件中进行编码。 ArgumentError: invalid byte sequence in UTF-8

  2. 未定义的局部变量。 NameError: undefined local variable or method 'randd_fields' for main:Object

    我猜你正在尝试计算创建/导入的记录:

    for_code = Randd::Field.create(anz_reference: row["anz_reference"], title: title)
    counter += 1 if randd_field.persisted?
    

    您创建的记录是for_code,但是您正在检查randd_field。 这应该可以解决它

    counter +=1 if for_code.presisted?
    

更新:

$ bundle exec rake import:randd_fields --trace ** Invoke import:randd_fields (first_time) ** Invoke environment (first_time) ** Execute environment ** Execute import:randd_fields nil rake 中止! NameError: main:Object 的未定义局部变量或方法“标题”

这是因为title 变量未定义。我猜你想在这里使用row[]

for_code = Randd::Field.create(anz_reference: row["anz_reference"], title: row['title'])

更新 2:

你的 rake 任务名称有错别字

更新 3:

我认为您在 rails 控制台内调用 bundle exec rake import:randd_fields。 直接在终端运行它应该可以修复它。

【讨论】:

  • 您好钟,我尝试再次运行 rake 任务并进行了您建议的更改,但我得到了与使用 GoRails 教程中建议的公式相同的错误(这是我设置的在上面的帖子中).bundle exec rake import:randd_fields NameError: undefined local variable or method `randd_fields' for main:Object from (irb):5
  • 我猜你更新了 rake 任务,因为除了任务名称我找不到任何randd_fields。你能更新代码sn-p吗?我已经更新了关于 title 错误的修复。
  • 我将更新后的 import.rake 文件添加到上述帖子的末尾。我仍然得到同样的错误
  • 你有一个错字。您正在调用的那个与 rake 任务名称不匹配。更新了答案。
  • 我再次尝试了 - 使用名为 randd_fields 的任务,但我仍然得到:bundle exec rake import:randd_fields NameError: undefined local variable or method `randd_fields' for main:Object
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-12
  • 2012-09-09
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 2016-08-14
  • 2011-05-23
相关资源
最近更新 更多