【问题标题】:Rails csv import with associations带有关联的 Rails csv 导入
【发布时间】:2016-11-09 22:17:57
【问题描述】:

我正在构建一个将帖子与许多不同类别相关联的 Rails 应用程序。例如,我有一个帖子,需要能够通过 csv 导入(通过 rake 任务)将其分配给体育、新闻和科学类别。

我的问题是如何将多个 category_id 的数组导入我的 Post 模型?我可以在其中手动创建一个新帖子并将多个类别分配给该帖子,但我对如何通过 csv 完成此操作感到困惑。我需要帮助找出完成此任务的最佳方法。

这是我目前所拥有的:

架构

  create_table "posts", force: :cascade do |t|
    t.string   "name"
    t.text     "description"
  end

  create_table "styles", force: :cascade do |t|
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.integer  "post_id"
    t.integer  "category_id"
  end

  create_table "categories", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at",        null: false
    t.datetime "updated_at",        null: false
  end

Post.rb

class Post < ApplicationRecord  
  has_many :styles
  has_many :categories, through: :styles
end

Category.rb

class Category < ApplicationRecord
  has_many :styles
  has_many :posts, through: :styles
end

Style.rb

class Style < ApplicationRecord
  belongs_to :post
  belongs_to :category
end

耙任务

require 'csv'
require 'open-uri'
namespace :post_import do
  desc "Import posts daily"
  task posts: :environment do
    filename = File.join Rails.root, "posts.csv"
    counter = 0

    CSV.foreach(filename) do |row|
      name, category, description = row
      post = Post.create(name: name, category_ids: category, description: description)
      counter += 1 if post.persisted?
    end

    puts "Imported #{counter} [posts]"
  end
end

【问题讨论】:

    标签: ruby-on-rails ruby csv


    【解决方案1】:

    在 gorails.com 的 Chris 的帮助下,我得以解决这个问题。这是我的(粗略)工作解决方案。希望这可以帮助其他人解决这个问题!

    require 'csv'
    require 'open-uri'
    namespace :post_import do
      desc "Import posts daily"
      task posts: :environment do
        filename = File.join Rails.root, "posts.csv"
        counter = 0
    
        CSV.foreach(filename) do |row|
          name, category_ids, description = row
          post = Post.new(name: name, description: description) if post == nil
          post.save 
    
          #separate string of category ids into array
          a_categories = category_ids.split(",")
    
          a_categories.each do |category_id|
            post.styles.where(category_id: category_id).first_or_create
          end
    
          counter += 1 if post.persisted?
        end
    
        puts "Imported #{counter} [posts]
      end
    end
    

    【讨论】:

      【解决方案2】:
      require 'csv'
      require 'open-uri'
      namespace :post_import do
        desc "Import posts daily"
        task posts: :environment do
          filename = File.join Rails.root, "posts.csv"
          counter = 0
      
          CSV.foreach(filename) do |row|
            name, category, description = row
      
            #you can user find or create, but for clarity I split it
            post = Post.where(name: name).first
            post = Post.new(name: name, description: description) if post == nil
      
            #now we can simply add the style which joins to the category
            post.styles.build(category_id: category)
            post.save
            counter += 1 if post.persisted?
          end
      
          puts "Imported #{counter} [posts]"
        end
      end
      

      【讨论】:

      • 解释为什么这是一个合适的答案。而不是扔掉代码帮助教育。
      • 如何将帖子分配到多个类别?例如,在类别行的 csv 中,我有“1,2,3”代表 3 个单独类别的 ID,但只记录第一个 ID。另外,你为什么使用 .new 和 .create?感谢您的帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 2013-02-02
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多