[ruby-on-rails] Ruby on Rails-CSV 파일에서 데이터 가져 오기

CSV 파일의 데이터를 기존 데이터베이스 테이블로 가져오고 싶습니다. CSV 파일을 저장하고 싶지 않고 데이터를 가져 와서 기존 테이블에 넣습니다. Ruby 1.9.2와 Rails 3을 사용하고 있습니다.

이것은 내 테이블입니다.

create_table "mouldings", :force => true do |t|
  t.string   "suppliers_code"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "name"
  t.integer  "supplier_id"
  t.decimal  "length",         :precision => 3, :scale => 2
  t.decimal  "cost",           :precision => 4, :scale => 2
  t.integer  "width"
  t.integer  "depth"
end

이 작업을 수행하는 가장 좋은 방법을 보여주는 코드를 제공해 주시겠습니까? 감사합니다.



답변

require 'csv'

csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
  Moulding.create!(row.to_hash)
end


답변

yfeldblum의 대답의 간단한 버전. 더 간단하고 큰 파일에서도 잘 작동합니다.

require 'csv'

CSV.foreach(filename, :headers => true) do |row|
  Moulding.create!(row.to_hash)
end

with_indifferent_access 또는 symbolize_keys가 필요 없으며 파일에서 먼저 문자열을 읽을 필요가 없습니다.

전체 파일을 한 번에 메모리에 보관하지 않지만 한 줄씩 읽고 한 줄에 몰딩을 만듭니다.


답변

smarter_csv보석은 특히이 사용 사례 만들었습니다 : CSV 파일에서 데이터를 읽고 신속하게 데이터베이스 항목을 만들 수 있습니다.

  require 'smarter_csv'
  options = {}
  SmarterCSV.process('input_file.csv', options) do |chunk|
    chunk.each do |data_hash|
      Moulding.create!( data_hash )
    end
  end

이 옵션 chunk_size을 사용하여 한 번에 N csv 행을 읽은 다음 내부 루프에서 Resque를 사용하여 새 레코드를 즉시 작성하지 않고 새 레코드를 작성하는 작업을 생성 할 수 있습니다.이 방법으로 항목 생성로드를 분산시킬 수 있습니다 여러 근로자에게.

참조 :
https://github.com/tilo/smarter_csv


답변

시도해 볼 수 있습니다 Upsert:

require 'upsert' # add this to your Gemfile
require 'csv'

u = Upsert.new Moulding.connection, Moulding.table_name
CSV.foreach(file, headers: true) do |row|
  selector = { name: row['name'] } # this treats "name" as the primary key and prevents the creation of duplicates by name
  setter = row.to_hash
  u.row selector, setter
end

이것이 원하는 경우, 테이블에서 자동 증가 기본 키를 제거하고 기본 키를로 설정하는 것도 고려할 수 있습니다 name. 또는 기본 키를 구성하는 속성 조합이 있으면 선택기로 사용하십시오. 색인이 필요하지 않으며 더 빨라집니다.


답변

도움이 될 수 있습니다. 코드 예제도 있습니다.

http://csv-mapper.rubyforge.org/

또는 같은 일을하는 갈퀴 작업 :

http://erikonrails.snowedin.net/?p=212


답변

데이터베이스 관련 프로세스를 transaction블록 안에 넣는 것이 좋습니다 . 코드 스 니펫 블로우는 언어 모델에 언어 세트를 시드하는 전체 프로세스입니다.

require 'csv'

namespace :lan do
  desc 'Seed initial languages data with language & code'
  task init_data: :environment do
    puts '>>> Initializing Languages Data Table'
    ActiveRecord::Base.transaction do
      csv_path = File.expand_path('languages.csv', File.dirname(__FILE__))
      csv_str = File.read(csv_path)
      csv = CSV.new(csv_str).to_a
      csv.each do |lan_set|
        lan_code = lan_set[0]
        lan_str = lan_set[1]
        Language.create!(language: lan_str, code: lan_code)
        print '.'
      end
    end
    puts ''
    puts '>>> Languages Database Table Initialization Completed'
  end
end

아래 스 니펫은 languages.csv파일 의 일부입니다 .

aa,Afar
ab,Abkhazian
af,Afrikaans
ak,Akan
am,Amharic
ar,Arabic
as,Assamese
ay,Aymara
az,Azerbaijani
ba,Bashkir
...


답변

이 보석을 사용하십시오 :
https://rubygems.org/gems/active_record_importer

class Moulding < ActiveRecord::Base
  acts_as_importable
end

그러면 다음을 사용할 수 있습니다.

Moulding.import!(file: File.open(PATH_TO_FILE))

헤더가 테이블의 열 이름과 일치하는지 확인하십시오.