রেলগুলিতে রুবি - একটি সিএসভি ফাইল থেকে ডেটা আমদানি করুন


205

আমি একটি বিদ্যমান ডাটাবেস সারণিতে একটি সিএসভি ফাইল থেকে ডেটা আমদানি করতে চাই। আমি সিএসভি ফাইলটি সংরক্ষণ করতে চাই না, কেবল এটি থেকে ডেটা নিয়ে এটি বিদ্যমান সারণীতে রাখি। আমি রুবি 1.9.2 এবং রেল 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

ধন্যবাদ আমাকে ধন্যবাদ দেওয়ার জন্য আমাকে কিছু কোড দিতে পারেন?

উত্তর:


380
require 'csv'    

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

2
আপনি এটিকে একটি রেক টাস্কে, বা একটি নিয়ামক পদক্ষেপে বা আপনার যে কোনও জায়গায় রাখতে পারেন ....
yfeldblum

1
এটি পুরোপুরি কাজ করেছে। তবে আমার কাছে একটি প্রাথমিক স্তরের প্রশ্ন রয়েছে - যখন আমি রুবি এবং রেলস এপিআই ডকুমেন্টেশনে বর্ণিত পদ্ধতিগুলি ব্রাউজ করার চেষ্টা করেছি তখন আমি সেগুলিতে খুঁজে পেতে অক্ষম ছিলাম (আমি সরকারী রুবি এবং রেলস সাইটগুলি, এপিআই ডক্সের দিকে চেয়েছিলাম)। উদাহরণস্বরূপ, আমি কী জিনিস CSV.parse () প্রদান করে তা খুঁজে পেলাম না, আমি to_hash () এবং_indifferent_access () পদ্ধতিগুলি খুঁজে পেলাম না ... সম্ভবত আমি ভুল জায়গায় তাকিয়েছি বা রুবি এবং রেলস এপিআই কীভাবে ট্র্যাভার করতে হবে তার কোনও মূল নীতি মিস করেছি ডক্স। রুবি এপিআই ডক্স কীভাবে পড়তে হয় কেউ সেরা অনুশীলনটি ভাগ করে নিতে পারেন?
ভ্লাদিমির ক্রোজ

2
@ ডেভিয়েটফ্লো: হ্যাঁ, নীচে আমার উত্তরটি দেখুন, যা ফাইলটিতে একবারে এক লাইনে পড়ে।
টম দে লিউ

1
@ লোকেশজাইন ২০০৮, এটি ওপি-র মডেলকে বোঝায়।
জাস্টিন ডি

3
এই পদ্ধতিটি অদক্ষ! বিশাল সিএসভি ফাইলগুলিতে ভেড়ার ব্যবহারের স্ক্রোককেট। নীচের একটি ভাল।
আনম

206

Yfeldblum এর উত্তরের সহজ সংস্করণ, এটি সহজ এবং বড় ফাইলগুলির সাথেও ভাল কাজ করে:

require 'csv'    

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

_ফরমে_অ্যাক্সেস বা প্রতীকী_কিগুলি সহ কোনও প্রয়োজন নেই এবং প্রথমে কোনও স্ট্রিংয়ে ফাইলটিতে পড়ার দরকার নেই।

এটি একবারে পুরো ফাইলটিকে স্মৃতিতে রাখে না, তবে প্রতিটি লাইনে লাইন পড়ে এবং প্রতি লাইনে একটি oldালাই তৈরি করে।


1
বড় ফাইল মাপ পরিচালনা করার জন্য এটি আরও ভাল? এটি কি একবারে এক লাইনে পড়ে?
নোটসিমন

1
@ সিমন: আসলেই। এটি একবারে পুরো ফাইলটিকে স্মৃতিতে রাখে না, তবে প্রতিটি লাইনে লাইন পড়ে এবং প্রতি লাইনে একটি oldালাই তৈরি করে।
টম দে লিউ

আমার এই ত্রুটি রয়েছে, আপনি কি জানেন ?: অ্যাক্টিভমডেল :: অজানাঅ্যাট্রিবিউট এরিয়ার: অজানা বৈশিষ্ট্য 'সাইরেন; নাম_এন্ট; অ্যাড্রেস; পরিপূরক_আড্রেস; সিপি_ভিল; প্রদান করে; অঞ্চল; প্রস্থান; অ্যাক্টিভেট; তারিখ ; শ্রেণীবদ্ধ; লেনদেনের জন্য টেলিফোন
nico_lrx

1
@ আলফাNico আপনার সমস্যা নিয়ে একটি প্রশ্ন তৈরি করুন। এই ত্রুটিটি এর সাথে সম্পর্কিত নয়, আপনার মডেল অবজেক্টগুলি সিঙ্কের বাইরে রয়েছে।
আনোম

এই ক্ষেত্রে, আপনি এটির জন্য টেস্ট কেসগুলি কীভাবে লিখবেন?
আফোলাবি ওলাওলুয়া আকিনওয়ুমি

11

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একবারে এন সিএসভি-সারিগুলি পড়ার বিকল্পটি ব্যবহার করতে পারেন , এবং তারপরে কাজটি তৈরি করতে অভ্যন্তরীণ লুপে রেসেক ব্যবহার করুন যা এখুনি তৈরির পরিবর্তে নতুন রেকর্ড তৈরি করবে - এভাবে আপনি উত্পন্ন এন্ট্রিগুলির বোঝা ছড়িয়ে দিতে পারবেন একাধিক কর্মী।

আরও দেখুন: https://github.com/tilo/smarter_csv


3
সিএসভি শ্রেণীর অন্তর্ভুক্ত হওয়ায়, অতিরিক্ত মণি যুক্ত বা ইনস্টল করার পরিবর্তে এটি ব্যবহার করা ভাল বলে আমি অনুভব করি। মঞ্জুর, আপনি অ্যাপ্লিকেশনটিতে একটি নতুন রত্ন যুক্ত করার প্রস্তাব করেন নি। একেকটি নির্দিষ্ট রৌপ্যগুলির নির্দিষ্ট সিরিজ যুক্ত করার জন্য এটি এত সহজ এবং আপনি এটি জানার আগে আপনার প্রয়োগের অত্যধিক নির্ভরতা রয়েছে। (আমি নিজেকে সচেতনভাবে কোনও রত্ন সংযোজন এড়িয়ে চলতে দেখি my আমার দোকানে আমাদের সতীর্থদের
সংযোজনকে

1
@ তাস এটি নির্দিষ্ট উদ্দেশ্যে পৃথক পৃথক পদ্ধতিগুলির একটি সিরিজ যুক্ত করাও বেশ সহজ এবং এটি জানার আগে আপনার অ্যাপ্লিকেশনটিতে অতিরিক্ত যুক্তি রয়েছে যা আপনাকে বজায় রাখতে হবে। যদি কোনও রত্ন কাজ করে, ভালভাবে রক্ষণাবেক্ষণ করা হয়, এবং অল্প সংস্থান ব্যবহার করে বা প্রাসঙ্গিক পরিবেশের সাথে পৃথক করা যায় (অর্থাত্ উত্পাদন কাজের জন্য মঞ্চায়ন) আমার কাছে রত্নটি ব্যবহার করার জন্য এটি সর্বদা আরও ভাল বিকল্প বলে মনে হয় । রুবি এবং রেলগুলি কম কোড লেখার বিষয়ে।
বৃহস্পতিবার

আমি নিম্নলিখিত ত্রুটি আছে, আপনি জানেন কেন? ActiveModel :: UnknownAttributeError: অজানা অ্যাট্রিবিউট 'সাইরেন; nom_ent; Adresse; complement_adresse; cp_ville; বহন করেনা; অঞ্চল; departement;' সক্রিয় করুন; তারিখ; nb_salaries; Nom; prenom; civilite; adr_mail; libele_acti; categorie; টেল 'লেনদেন জন্য
nico_lrx

আমি এটি একটি রেক টাস্কে চেষ্টা করেছিলাম, কনসোল ফেরত: রেকটি বাতিল! NoMethodError: অনির্ধারিত পদ্ধতি `শূন্য জন্য বন্ধ ': NilClass stackoverflow.com/questions/42515043/...
মারকোস আর গেভারা

1
@ তাসকে সিএসভি প্রসেসিংকে ছড়িয়ে দেওয়া, গতির উন্নতি করা এবং মেমরির সঞ্চয় করা কোনও নতুন রত্ন যুক্ত করার পক্ষে ভাল ন্যায়সঙ্গত হতে পারে;)
টিলো

5

আপনি চেষ্টা করতে পারেন 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। বিকল্পভাবে, যদি প্রাথমিক কী তৈরি করে এমন কিছু বৈশিষ্ট্যের সংমিশ্রণ থাকে তবে এটি নির্বাচক হিসাবে ব্যবহার করুন। কোনও সূচকের প্রয়োজন নেই, এটি কেবল এটি দ্রুততর করবে।


4

এটি সাহায্য করতে পারে। এর কোডের উদাহরণও রয়েছে:

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

বা একই কাজ করার জন্য রেক টাস্কের জন্য:

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


erikonrails.snowedin.net/?p=212 নষ্ট হয়ে গেছে, দয়া করে, আমি একটি বিষয় মই দিয়া আহরণ করা কাজের সঙ্গে কাজ এখানে জন্য খোলা stackoverflow.com/questions/42515043/...
মারকোস আর গেভারা

2

একটি 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
...

0

এই রত্নটি ব্যবহার করুন: https://rubygems.org/gems/active_record_importer

class Moulding < ActiveRecord::Base
  acts_as_importable
end

তারপরে আপনি এখন ব্যবহার করতে পারেন:

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

আপনার শিরোনামগুলি আপনার টেবিলের কলামের নামের সাথে মেলে তা নিশ্চিত হয়ে নিন


0

আরও ভাল উপায় এটি একটি রেক টাস্কে অন্তর্ভুক্ত করা হয়। Import /rake ফাইলটি / lib / Tasks / এর ভিতরে তৈরি করুন এবং এই কোডটি সেই ফাইলে রাখুন।

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

এর পরে আপনার টার্মিনালে এই কমান্ডটি চালান rake csv_model_import[file.csv,Name_of_the_Model]


0

আমি জানি এটি পুরানো প্রশ্ন তবে এটি গুগলে প্রথম 10 লিঙ্কে রয়েছে।

একের পর এক সারিগুলি সংরক্ষণ করা খুব দক্ষ নয় কারণ এটি লুপে ডেটাবেস কল সৃষ্টি করে এবং আপনি এটিকে আরও ভাল এড়াতে পারেন, বিশেষত যখন আপনাকে বিপুল পরিমাণে ডেটা সন্নিবেশ করা প্রয়োজন।

ব্যাচ সন্নিবেশ ব্যবহার করা আরও ভাল (এবং উল্লেখযোগ্যভাবে দ্রুত)।

INSERT INTO `mouldings` (suppliers_code, name, cost)
VALUES
    ('s1', 'supplier1', 1.111), 
    ('s2', 'supplier2', '2.222')

আপনি ম্যানুয়ালি এই জাতীয় একটি কোয়েরি তৈরি করতে পারেন এবং না করে Model.connection.execute(RAW SQL STRING)(পুনরায় সংশোধনযোগ্য) বা মণি ব্যবহার করতে পারেন activerecord-import(এটি প্রথম প্রকাশিত হয়েছিল ১১ আগস্ট ২০১০ এ) এই ক্ষেত্রে কেবল অ্যারে rowsএবং কল এ ডেটা রাখুনModel.import rows

বিশদ জন্য রত্ন ডক্স দেখুন


-2

সিএসভি :: টেবিল এবং ব্যবহার ব্যবহার করা আরও ভাল String.encode(universal_newline: true)। এটি সিআরএলএফ এবং সিআরকে এলএফতে রূপান্তর করে


1
আপনার প্রস্তাবিত সমাধান কি?
তাস

-3

আপনি চাইলে স্মার্টসিএসভি ব্যবহার করুন

all_data = SmarterCSV.process(
             params[:file].tempfile, 
             { 
               :col_sep => "\t", 
               :row_sep => "\n" 
             }
           )

এটি "\t"নতুন লাইনের দ্বারা পৃথক করা সারিগুলির সাথে প্রতিটি সারিতে ট্যাব সীমিত ডেটা উপস্থাপন করে"\n"

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.