Ruby on Rails-Import danych z pliku CSV
Chciałbym zaimportować dane z pliku CSV do istniejącej tabeli bazy danych. Nie chcę zapisywać pliku CSV, po prostu pobieram z niego Dane i umieszczam je w istniejącej tabeli. Używam Ruby 1.9.2 i Rails 3.
To jest mój stół:
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
Możesz dać mi jakiś kod, żeby pokazać mi jak najlepiej to zrobić, dzięki. 11 answers
require 'csv'
csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
Moulding.create!(row.to_hash)
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 00:18:01
Prostsza wersja odpowiedzi yfeldbluma, która jest prostsza i działa dobrze również z dużymi plikami:
require 'csv'
CSV.foreach(filename, headers: true) do |row|
Moulding.create!(row.to_hash)
end
Nie ma potrzeby stosowania with_indifferent_access
Ani symbolize_keys
, i nie ma potrzeby najpierw odczytywania w pliku do ciągu znaków.
Nie przechowuje całego pliku w pamięci na raz, ale czyta w linii po linii i tworzy formowanie w linii.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-10 20:16:07
Gem smarter_csv
został stworzony specjalnie dla tego przypadku użycia: do odczytu danych z pliku CSV i szybkiego tworzenia wpisów w bazie danych.
require 'smarter_csv'
options = {}
SmarterCSV.process('input_file.csv', options) do |chunk|
chunk.each do |data_hash|
Moulding.create!( data_hash )
end
end
Możesz użyć opcji chunk_size
, aby odczytać N wierszy csv naraz, a następnie użyć Resque w wewnętrznej pętli, aby wygenerować zadania, które utworzą nowe rekordy, zamiast tworzyć je od razu - w ten sposób możesz rozłożyć obciążenie generowania wpisów na wiele worków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-11 10:23:58
Możesz spróbować 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
Jeśli tego chcesz, możesz również rozważyć pozbycie się auto-inkrementacyjnego klucza podstawowego z tabeli i ustawienie klucza podstawowego na name
. Alternatywnie, jeśli istnieje pewna kombinacja atrybutów tworzących klucz podstawowy, użyj go jako selektora. Żaden indeks nie jest konieczny, po prostu przyspieszy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 21:05:53
To może pomóc. Ma też przykłady kodu:
Http://csv-mapper.rubyforge.org/
Lub za zadanie rake za zrobienie tego samego:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-10 16:14:56
Lepiej jest zawinąć proces związany z bazą danych wewnątrz transaction
bloku. Kod snippet blow to pełny proces zaszeregowania zestawu języków do modelu języka,
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
Poniżej fragment pliku languages.csv
,
aa,Afar
ab,Abkhazian
af,Afrikaans
ak,Akan
am,Amharic
ar,Arabic
as,Assamese
ay,Aymara
az,Azerbaijani
ba,Bashkir
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-03 03:27:42
Wiem, że to stare pytanie, ale nadal w pierwszych 10 linkach w google.
Nie jest zbyt wydajne zapisywanie wierszy jeden po drugim, ponieważ powoduje wywołanie bazy danych w pętli i lepiej tego unikać, zwłaszcza gdy trzeba wstawić ogromne porcje danych.
Lepiej (i znacznie szybciej) używać wsadowej wkładki.
INSERT INTO `mouldings` (suppliers_code, name, cost)
VALUES
('s1', 'supplier1', 1.111),
('s2', 'supplier2', '2.222')
Możesz zbudować takie zapytanie ręcznie i zrobić Model.connection.execute(RAW SQL STRING)
(nie polecane)
lub użyj gem activerecord-import
(został wydany po raz pierwszy 11 sierpnia 2010) w tym przypadku po prostu umieść dane w tablicy rows
i wywołaj Model.import rows
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 01:20:10
Użyj tego klejnotu: https://rubygems.org/gems/active_record_importer
class Moulding < ActiveRecord::Base
acts_as_importable
end
Wtedy możesz teraz użyć:
Moulding.import!(file: File.open(PATH_TO_FILE))
Upewnij się, że nagłówki pasują do nazw kolumn tabeli
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-28 07:53:01
Lepszym sposobem jest włączenie go do zadania rake. Utwórz import.plik rake w / lib / tasks / i umieść ten kod w tym pliku.
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
Następnie uruchom tę komendę w swoim terminalu rake csv_model_import[file.csv,Name_of_the_Model]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-24 07:26:19
Lepiej jest użyć CSV:: Table i użyć String.encode(universal_newline: true)
. Konwertuje CRLF i CR na LF
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-31 07:16:45
Jeśli chcesz użyć SmartCSV
all_data = SmarterCSV.process(
params[:file].tempfile,
{
:col_sep => "\t",
:row_sep => "\n"
}
)
Przedstawia dane rozdzielane tabulatorami w każdym wierszu {[1] } z wierszami oddzielonymi nowymi wierszami "\n"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 18:59:36