2015-11-07 112 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