从CSV导入,无意中保存多次的对象

时间:2013-02-14 00:40:37

标签: ruby-on-rails csv hash import ruby-on-rails-3.2

我正在尝试向我的应用添加“通过CSV导入”功能。我一直在玩代码来弄清楚它是如何工作的。在我的应用中User has_many :websitesWebsite has_many :links。这就是我目前所拥有的:

def create
  file = params[:file]
  @hash = {} 
  CSV.foreach(file.path, headers: true) do |row|
    hash = row.to_hash.slice("link", "project", "comment", "email")
    site = row["website"]
    @hash.has_key?(site) ? @hash[site] << hash : @hash.merge!(site => [hash])
    @hash.keys.each { |key| create_site(key, @hash[key]) }
  end
  flash[:success] = "File imported successfully! Links are currently being processed."
  redirect_to new_import_site_path
end

private

def create_site(site_link, links_array)
  website = current_user.websites.build(link: site_link)
  links_array.each do |link|
    website.links.build(page: link["link"], validation_id: current_user.id)
  end
  website.save
end

代码生成正确的散列,例如:

{"http://google.com"=>[{"link"=>"http://stackoverflow.com", "project"=>"Test", "comment"=>"this is a comment", "email"=>"email@gmail.com"}, {"link"=>"http://golf.com", "project"=>nil, "comment"=>"this is a comment", "email"=>"email@gmail.com"}], "http://yahoo.com"=>[{"link"=>"http://bing.com", "project"=>"Test", "comment"=>"this is a comment", "email"=>"email@gmail.com"}]}

如果我使用上面的哈希在我的rails控制台中运行代码,它会按预期创建2个网站和3个链接,但是在我的应用程序中它创建了5个网站和6个链接:

Website             ID   Associated Link            ID
http://yahoo.com  | 406  http://bing.com          | 1223
http://google.com | 405  http://golf.com          | 1222
http://google.com | 405  http://stackoverflow.com | 1221
http://yahoo.com  | 404  http://bing.com          | 1220
http://google.com | 403  http://stackoverflow.com | 1219
http://google.com | 402  http://stackoverflow.com | 1218

我做错了什么?

1 个答案:

答案 0 :(得分:1)

对于CSV文件中的每一行,您将重新创建前一行中显示的所有网站。我认为这不是你的意图。

答案是将罪魁祸首的代码行移出循环,这样你只需要在完成链接数组之后创建一次。

def create
  file = params[:file]
  @hash = {} 
  CSV.foreach(file.path, headers: true) do |row|
    hash = row.to_hash.slice("link", "project", "comment", "email")
    site = row["website"]
    @hash.has_key?(site) ? @hash[site] << hash : @hash.merge!(site => [hash])
  end

  # moved this out
  @hash.keys.each { |key| create_site(key, @hash[key]) }

  flash[:success] = "File imported successfully! Links are currently being processed."
  redirect_to new_import_site_path
end