Rails 5 - 从CSV文件

时间:2016-12-18 02:34:31

标签: ruby-on-rails ruby csv import

我正在尝试将我保存在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:未定义的局部变量或方法`title&#39; for main:Object

任何人都可以看到我做错了吗?

我也尝试过本教程 How to import CSV files in Rails by Matt Morgante ,并试图将rails cast和Roo gem用于同一目的。这两个选项都不起作用--Rails Cast很旧,所以可能已经过时了,其他教程的帖子中的注释显示许多其他人无法使用这种方法 - 也许Rails中的东西已经改变了,因为它提出了。

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

我得到了与使用xls创建的文件运行rake任务时相同的错误。

ZHONG&#39; S建议

根据钟的建议,我尝试将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

1 个答案:

答案 0 :(得分: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?
    
  3. <强>更新

      

    $ bundle exec rake import:randd_fields --trace **调用import:randd_fields(first_time)**调用环境(first_time)**执行环境**执行导入:randd_fields nil rake aborted! NameError:未定义的局部变量或main:Object

    的方法`title'

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

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

    更新2:

    您的佣金任务名称中有拼写错误

    更新3:

    我认为你在rails console中调用了bundle exec rake import:randd_fields。 直接在终端运行它应该修复它。