在Ruby on Rails上导入csv文件

时间:2014-09-23 08:12:39

标签: ruby-on-rails ruby csv

对不起我的简单问题,因为我对所有事情都是新手。

正如我的问题所说,我想将带有标题行的csv文件导入到现有数据表中。即使我尝试了4天这些答案(和其他谷歌搜索) Trouble importing csv file with ruby CSV ModuleRuby on Rails - Import Data from a CSV file ,但我找不到路。

# db/migrate/20140923064239_create_restaurants.rb
class CreateRestaurants < ActiveRecord::Migration
  def change
    create_table :restaurants do |t|
      t.string :restaurant_category
      t.string :restaurant_subcategory
      t.timestamps
    end
  end
end

# lib/tasks/import.rake
require 'csv'

CSV.foreach("english.csv", :headers => true) do |row|
  Restaurant.create!(row.to_hash)
end

# english.csv
restaurant_category,restaurant_subcategory
kor,bakban
kor,galbi
kor,gobchang
kor,hanjeong
kor,hajang
kor,dolsot
kor,bude
kor,jokbal
kor,sullung
chin,ssambab
chin,dubu
chin,jechum
chin,pajeon

然后我做了rake db:migrate,并收到错误消息NameError: uninitialized constant Restaurant。我在谷歌尝试了很多其他方法,但每次出现此错误消息。我现在假设我现有的餐桌表不适合这个rake过程(即使我不知道这个错误信息的真正含义)。

所以请帮助我解决这个问题,我很抱歉这可能很容易。但对我来说太难了,我无法解决它。感谢。

2 个答案:

答案 0 :(得分:2)

为此创建一个rake任务。将import.rake文件编辑为

require 'csv'
namespace :db do
  task :import_csv => :environment do
    CSV.foreach("english.csv", :headers => true) do |row|
      Restaurant.create!(row.to_hash)
    end
  end
end

并运行bundle exec rake db:import_csv

答案 1 :(得分:0)

如果您希望将餐厅数据跨两个或多个表导入-假设您有一个Category和Subcategory表或其他任何东西,然后有一个Restaurant表-那么有一个有用的gem DutyFree ,这使进出口变得相当轻松。例如,如果这是您的架构怎么办?

___________     _____________     _____________
|Category |     |Subcategory|     |Restaurant |
|         |     |           |     |           |
|         |---->|belongs_to |---->|belongs_to |
|         |     |   Category|     |Subcategory|
|         |     |           |     |           |
¯¯¯¯¯¯¯¯¯¯¯     ¯¯¯¯¯¯¯¯¯¯¯¯¯     ¯¯¯¯¯¯¯¯¯¯¯¯¯

此gem可以智能地分析模型上的has_many和belongs_to关联,并基于这些关系确定如何正确地跨多个目标表保存每个导入的行。根据数据是否存在执行创建或更新。

以下是您上面拥有的韩国食品类别的一些CSV样本数据,旨在针对诸如上述的模式。来自世界各地的餐馆都在提供这种食物:

Category,Subcategory,Name,Address
Korean,Bakban,Gajeongsik Bakban,"1555-6, Seocho-dong, Seocho-gu, Seoul (서울특별시 서초구 서초대로46길 19-7)"
Korean,Bakban,Sakunja,"17-1 jalan 26a-70a prismaville desa sri hartamas 50480 Kuala Lumpur, Malaysia"
Korean,Galbi,Kalbi Korean BBQ & Sushi,"36 Rosebery Avenue, London EC1R 5HP England"
Korean,Gopchang,Gombawie,"151-4, Samseong-dong, Gangnam-gu, Seoul South Korea"
Korean,Gopchang,Samsung Wonjo Yang Gobchang (삼성원조양곱창),"133-6, Cheongdam-dong, Gangnam-gu, Seoul (서울특별시 강남구 청담동 133-6)"
Korean,Gopchang,Hamji Gopchang (함지곱창),"144-5, Nonhyeon-dong, Gangnam-gu, Seoul (서울특별시 강남구 학동로2길 33)"
Korean,Hanjeongsik,Kkott Dolge Jang 1 Beonga,"210-2, Bongsan-dong, Yeosu-si, Jeollanam-do"
Korean,Hanjeongsik,Chaegeundam,"983, Daechi-dong, Gangnam-gu, Seoul"
Korean,Haejang,Sun Ha Jang,"4032 W Olympic Blvd, Los Angeles, CA 90019"
Korean,Dolsot,Sarangchae Korean Restaurant,"278-280 Huntingdon Street, Nottingham NG1 3NA England"
Korean,Budae-jjigae,Gimnejip,"322-38, Sinjang-dong, Pyeongtaek-si, Gyeonggi-do"
Korean,Budae-jjigae,Daewoo Budaejjigae,"641-18, Yeoksam-dong, Gangnam-gu, Seoul"
Korean,Jokbal,Jang Choong Dong Wong Jokbal,"425 S Western Ave. Los Angeles, CA 90020"
Korean,Seolleongtang,Uchon Dolsot Seolleongtang,"24, Eulji-ro 12-gil, Jung-gu, Seoul 04550"
Chinese,Ssambab,GAAE Ssambab,"No. 6, Lane 40, Section 2, Zhongcheng Road, Shilin District, Taipei City (台北市士林區忠誠路二段40巷6號)"
Chinese,Dubu,Tofu Tofu,"96 Bowery, New York, NY 10013"
Chinese,Cífàntuán,Shanghai Hong Kong Noodle Shop,"29 Jardine's Bazaar, Causeway Bay, Hong Kong"
Chinese,Pajeon,Madang,"Gneisenaustr. 8, 10961 Berlin Germany"
Chinese,Pajeon,FOMO Pancake,"No.333 Huaihai Middle Road Xintiandi Plaza B2-17, Shanghai 200000 China"

为了从上面演示您的示例,我将这个CSV放入了gem中的RSpec测试中。这是一个加载示例,首先从Restaurant开始,然后添加Subcategory和Category: https://github.com/lorint/duty_free/blob/master/spec/models/restaurant_spec.rb

这是从“类别”开始加载“子类别”和“餐馆”的另一个方向的示例: https://github.com/lorint/duty_free/blob/master/spec/models/restaurant_reverse_spec.rb

关于这个gem的一件好事是,在配置了列定义以进行导入之后,由于所有工作都来自同一模板,因此您可以免费获得导出。对于从类别到has_many关系再到子类别和餐厅的示例,此模板允许CSV中的列名与数据库列完美对齐:

IMPORT_TEMPLATE = {
  uniques: [:name, :subcategories_name, :subcategories_restaurants_name, :subcategories_restaurants_address],
  required: [],
  all: [:name,
    { subcategories: [:name,
      { restaurants: [:name, :address] }] }],
  # An alias for incoming columns
  as: {
        'Category' => 'Name',
        'Subcategory' => 'Subcategories Name',
        'Name' => 'Subcategories Restaurants Name',
        'Address' => 'Subcategories Restaurants Address'
      }
}

在Category模型中,您可以随后调用Category.df_import()和Category.df_export()。

P.S。很棒的食物选择-我喜欢美味的韩国料理!