2011-07-14 94 views
119

我試着在我的Rails應用程序中保存一個哈希映射id到一定數量的嘗試。我對數據庫遷移,以適應這個新列:使用Rails序列化將散列保存到數據庫

class AddMultiWrongToUser < ActiveRecord::Migration 
    def self.up 
    add_column :users, :multi_wrong, :string 
    end 

    def self.down 
    remove_column :users, :multi_wrong 
    end 
end 

在我的模型,我有:

class User < ActiveRecord::Base 
serialize :multi_wrong, Hash 
end 

但是當我使用的鐵軌控制檯邊做邊測試:

user = User.create() 
user.multi_wrong = {"test"=>"123"} 
user.save 

輸出錯誤。這裏有什麼問題?

+4

嘗試保存記錄後user.errors中是否有任何內容? – Martijn

+0

將來,您可以使用bang方法(save!)來引發異常並顯示錯誤消息。 – leishman

回答

162

列類型錯誤。您應該使用文本而不是字符串。因此,遷移應該是:

def self.up 
    add_column :users, :multi_wrong, :text 
end 

然後Rails會適當地將其轉換成YAML你(和執行正確的序列化)。字符串字段的大小有限,只能保存特別小的值。

+1

@BenjaminTan背後的原因是什麼,爲什麼我不能在'字符串'數據類型中存儲散列。 –

+7

因爲在數據庫中,字符串的固定長度爲255(我認爲)。但是如果你要序列化一個比較大小的散列,這很容易超過這個長度。數組的情況相同。文字允許更大的長度。 –

56

有關詳細信息:rails docs & & apidock

確保您的列:text而不是:string

遷移:

$ rails g migration add_location_data_to_users location_data:text

應該創建:

class Migration0001 
    def change 
    add_column :users, :location_data, :text 
    end 
end 

你的類會是什麼樣子:

class User < ActiveRecord::Base 
    serialize :location_data 
end 

可用操作:

b = User.new 
b.location_data = [1,2,{foot: 3, bart: "noodles"}] 
b.save 

更多真棒?

使用PostgreSQL的hstore

class AddHstore < ActiveRecord::Migration 
    def up 
    enable_extension :hstore 
    end 

    def down 
    disable_extension :hstore 
    end 
end 

class Migration0001 
    def change 
    add_column :users, :location_data, :hstore 
    end 
end 

隨着hstore您可以在序列化領域

class User < ActiveRecord::Base 
    # setup hstore 
    store_accessor :location_data, :city, :state 
end 
+2

真的很棒!謝謝! –

+0

這適用於導軌4? –

11

軌道4有一個新的功能,稱爲Store設置屬性,讓您可以輕鬆地使用它來解決你的問題。您可以爲其定義一個訪問器,並且建議您將用於序列化商店的數據庫列作爲文本聲明,因此有足夠的空間。原始示例:

class User < ActiveRecord::Base 
    store :settings, accessors: [ :color, :homepage ], coder: JSON 
end 

u = User.new(color: 'black', homepage: '37signals.com') 
u.color       # Accessor stored attribute 
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor 

# There is no difference between strings and symbols for accessing custom attributes 
u.settings[:country] # => 'Denmark' 
u.settings['country'] # => 'Denmark' 
相關問題