2015-11-07 110 views
1

在这种情况下,更新方法失败,因为唯一约束失败:items.id

product = <Item id: 4, url: nil, memo: nil, created_at: "2015-11-07 09:48:36", updated_at: "2015-11-07 09:48:36", Totalweight: 390.0, Perweight: nil, price: 1000> 
attr = {"id"=>4, "tag_list"=>"peanuts", "price"=>1000, "url"=>nil, "Totalweight"=>390, "memo"=>nil} 

我做了更新项目的记录。因为我想更新的记录

product.update!(attr) 

但错误说,

SQLite3::ConstraintException UNIQUE constraint failed: items.id 
!! #<ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: items.id: INSERT INTO "items" ("id", "price", "Totalweight", "created_at", "updated_at", "url") VALUES (?, ?, ?, ?, ?, ?)> 

当然ID是一样的。 我试过

product.update_attributes(attr) 

也显示同样的错误。

问题是如何更新这个Item对象?

如果未设置id,ActiveRecord的保存方法正在工作。

此外,更多信息, 我使用gem'roo'导入Excel,CSV文件并且可以解析。 https://github.com/roo-rb/roo 参数行从宝石“袋鼠”

这里是代码,

COLUMN = ["id","tag_list","price","url","Perweight","Totalweight", "memo", "id", "created_at", "updated_at"] 

    def self.import(file) 
    spreadsheet = open_spreadsheet(file) 
    header = spreadsheet.row(1) 
    (2..spreadsheet.last_row).each do |i| 
     row = Hash[[header, spreadsheet.row(i)].transpose] 
     if Item.find(row["id"]) then 
     product = Item.new 
     attr = row.slice(*COLUMN) 
     # product.attributes = attr 
     product.update(attr) 
     else 
     product = Item.new 
     attr = row.slice(*COLUMN) 
     product.attributes = attr 
     product.save! 
     end 
    end 
    end 

    def self.open_spreadsheet(file) 
    case File.extname(file.original_filename) 
    when ".csv" then 
     Roo::Spreadsheet.open(file.path, extension: :csv) 
    when ".xls" then 
     Roo::Spreadsheet.open(file.path, extension: :xls) 
    when ".xlsx" then 
     Roo::Spreadsheet.open(file.path, extension: :xlsx) 
    else raise "Unknown file type: #{file.original_filename}" 
    end 
    end 

回答

1

你已经检查的项目是否存在 - 这是好的。 但是,您并未升级现有项目,即使已经存在具有相同ID的人员,也要创建一个新项目,这就是为什么您会收到错误。

有解决这个两个方法 - 第一个是更详细一点,但更接近你已经拥有:

product = Item.find(row["id"]) 
if product then 
    attr = row.slice(*COLUMN) 
    # Update the existing product 
    product.update(attr) 
else 
... 
end 

不过,既然你做同样的事情到产品对象,无论如何,不管是否存在,你也可以这样做:

# This will either find an existing product, or initialize a new one with the ID 
product = Item.find_or_initialize_by(id: row["id"]) 
attr = row.slice(*COLUMN) 
product.attributes = attr 
product.save! 
+0

谢谢先生尼尔斯!我花了6个小时解决这个问题! – YOSUKE

+0

非常感谢你这么多!你是我的英雄! – YOSUKE

+1

我并不需要创建两个相同的ID实例!我不知道! – YOSUKE