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))
헤더가 테이블의 열 이름과 일치하는지 확인하십시오.