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
도움이 될 수 있습니다. 코드 예제도 있습니다.
http://csv-mapper.rubyforge.org/
또는 같은 일을하는 갈퀴 작업 :
http://erikonrails.snowedin.net/?p=212
시도해 볼 수 있습니다 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
. 또는 기본 키를 구성하는 속성 조합이 있으면 선택기로 사용하십시오. 색인이 필요하지 않으며 더 빨라집니다.
It is better to wrap the database related process inside a transaction
block. Code snippet blow is a full process of seeding a set of languages to Language model,
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
Snippet below is a partial of languages.csv
file,
aa,Afar
ab,Abkhazian
af,Afrikaans
ak,Akan
am,Amharic
ar,Arabic
as,Assamese
ay,Aymara
az,Azerbaijani
ba,Bashkir
...
Use this gem: https://rubygems.org/gems/active_record_importer
class Moulding < ActiveRecord::Base
acts_as_importable
end
Then you may now use:
Moulding.import!(file: File.open(PATH_TO_FILE))
Just be sure to that your headers match the column names of your table
The better way is to include it in a rake task. Create import.rake file inside /lib/tasks/ and put this code to that file.
desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, [:filename, :model] => [:environment] do |task,args|
lines = File.new(args[:filename], "r:ISO-8859-1").readlines
header = lines.shift.strip
keys = header.split(',')
lines.each do |line|
values = line.strip.split(',')
attributes = Hash[keys.zip values]
Module.const_get(args[:model]).create(attributes)
end
end
After that run this command in your terminal rake csv_model_import[file.csv,Name_of_the_Model]
I know it's old question but it still in first 10 links in google.
It is not very efficient to save rows one-by-one because it cause database call in the loop and you better avoid that, especially when you need to insert huge portions of data.
It's better (and significantly faster) to use batch insert.
INSERT INTO `mouldings` (suppliers_code, name, cost)
VALUES
('s1', 'supplier1', 1.111),
('s2', 'supplier2', '2.222')
You can build such a query manually and than do Model.connection.execute(RAW SQL STRING)
(not recomended) or use gem activerecord-import
(it was first released on 11 Aug 2010) in this case just put data in array rows
and call Model.import rows
It's better to use CSV::Table and use String.encode(universal_newline: true)
. It converting CRLF and CR to LF
If you want to Use SmartCSV
all_data = SmarterCSV.process(
params[:file].tempfile,
{
:col_sep => "\t",
:row_sep => "\n"
}
)
This represents tab delimited data in each row "\t"
with rows separated by new lines "\n"
참고URL : https://stackoverflow.com/questions/4410794/ruby-on-rails-import-data-from-a-csv-file
'IT' 카테고리의 다른 글
현재 내 애플리케이션을 실행중인 Android API 수준의 휴대 전화를 가져옵니다. (0) | 2020.05.12 |
---|---|
C 프로그램의 실행 시간 (0) | 2020.05.12 |
콘 다를 실행하는 방법? (0) | 2020.05.12 |
동적 (C # 4)과 var의 차이점은 무엇입니까? (0) | 2020.05.12 |
NPM이 종속성을 설치할 수 없음-잠기지 않은 것을 잠금 해제하려고했습니다. (0) | 2020.05.12 |