web-dev-qa-db-ja.com

Rails serializeを使用してハッシュをデータベースに保存する

Railsアプリで、ハッシュマッピングIDをいくつかの試行に保存しようとしています。この新しい列に対応するためのデータベースへの移行:

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

ただし、Railsコンソールを使用してこれをテストするには、次のようにします。

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

出力は偽です。ここで何が問題になっていますか?

133
cmwright

列のタイプが間違っています。文字列の代わりにテキストを使用する必要があります。したがって、移行は次のようになります。

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

その後、Railsはそれを適切にYAMLに変換します(そして適切なシリアル化を実行します)。文字列フィールドのサイズには制限があり、特に小さい値のみが保持されます。

172

更新:

正確な実装はデータベースに依存しますが、PostgreSQLにはjsonおよびjsonb列があり、ハッシュ/オブジェクトデータをネイティブに保存して、 ActiveRecordでJSONに対してクエリ

移行を変更すれば完了です。

class Migration0001
  def change
    add_column :users, :location_data, :json, default: {}
  end
end

オリジナル:

詳細: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
66
Blair Anderson

Rails 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'
17
Aboozar Rajabi