2011-07-14 8 views
119

私は、私のレールアプリでいくつかの試みにハッシュマッピング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 

出力はfalseです。ここで何がうまくいかないの?

+4

レコードを保存した後でuser.errorsに何かがありますか? – Martijn

+0

将来、bangメソッド(save!)を使用して例外を発生させ、エラーメッセージを表示することができます。 – leishman

答えて

162

カラムタイプが正しくありません。文字列の代わりにテキストを使用する必要があります。したがって、あなたの移行は次のようになります。

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

するとRailsが適切にあなたのためのYAMLに変換(および適切な直列化を実行)します。文字列フィールドのサイズは限られており、特に小さな値しか保持しません。詳細については

+1

@BenjaminTanなぜそれが背後にあるのか、 'string'データ型にハッシュを格納できないのはなぜですか? –

+7

データベースでは、Stringは固定長255です(私は思う)。しかし、比較サイズのハッシュをシリアル化する場合、これは簡単に長さを超えます。配列についても同じです。テキストはもっと大きな長さを許します。 –

56

$ rails g migration add_location_data_to_users location_data:text

rails docs & & apidock

は、あなたの列が:textなく:string

の移行であることを確認してください

は、作成する必要があります。

class User < ActiveRecord::Base 
    serialize :location_data 
end 

利用可能なアクション:

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

あなたのクラスは次のようになり

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

もっとすごいですの! hstoreので

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 

あなたは

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' 
関連する問題