Reputation: 37
I am building a rails application that associates posts with many different categories. For example, I have a Post and need to be able to assign it to the categories Sports, News and Science through csv import via rake task.
My question is how can I import an array of multiple category_ids into my Post model? I have it working where I can manually create a new Post and assign multiple categories to the post, but I am confused as to how to complete this through csv. I need help figuring out the best way to accomplish this.
Here is what I have so far:
Schema
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
Rake Task
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
Upvotes: 1
Views: 985
Reputation: 37
I was able to solve this with help from Chris at gorails.com. Here is my (rough) working solution. Hope this helps anyone else with this issue!
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
Upvotes: 1
Reputation: 1
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
Upvotes: 0