57

シリアル化された列を使用するモデルがあります。

class Form < ActiveRecord::Base
  serialize :options, Hash
end

このシリアル化でYAMLの代わりにJSONを使用する方法はありますか?

4

8 に答える 8

161

Rails 3.1では、次のことができます

class Form < ActiveRecord::Base
  serialize :column, JSON
end

それが役立つことを願っています

于 2011-08-07T08:44:55.023 に答える
58

Rails 3.1 では、カスタム コーダーを で使用できますserialize

class ColorCoder
  # Called to deserialize data to ruby object.
  def load(data)
  end

  # Called to convert from ruby object to serialized data.
  def dump(obj)
  end
end

class Fruits < ActiveRecord::Base
  serialize :color, ColorCoder.new
end

お役に立てれば。

参考文献:

の定義serialize: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb#L556

Rails に同梱されているデフォルトの YAML コーダー: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/coders/yaml_column.rb

そして、これが呼び出しが行われる場所loadです: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132

于 2011-05-12T14:55:16.537 に答える
11

アップデート

より適切な Rails >= 3.1 の回答については、以下の mid の高評価の回答を参照してください。これは、Rails < 3.1 に対する優れた回答です。

おそらくこれはあなたが探しているものです。

Form.find(:first).to_json

アップデート

1) 「json」gemをインストールします。

gem install json

2) JsonWrapper クラスを作成する

# lib/json_wrapper.rb

require 'json'
class JsonWrapper
  def initialize(attribute)
    @attribute = attribute.to_s
  end

  def before_save(record)
    record.send("#{@attribute}=", JsonWrapper.encrypt(record.send("#{@attribute}")))
  end

  def after_save(record)
    record.send("#{@attribute}=", JsonWrapper.decrypt(record.send("#{@attribute}")))
  end

  def self.encrypt(value)
    value.to_json
  end

  def self.decrypt(value)
    JSON.parse(value) rescue value
  end
end

3) モデル コールバックを追加します。

#app/models/user.rb

class User < ActiveRecord::Base
    before_save      JsonWrapper.new( :name )
    after_save       JsonWrapper.new( :name )

    def after_find
      self.name = JsonWrapper.decrypt self.name
    end
end

4) テストしてみよう!

User.create :name => {"a"=>"b", "c"=>["d", "e"]}

PS:

DRYとまではいきませんが、頑張りました。誰かがモデルを修正できればafter_findUserそれは素晴らしいことです。

于 2010-01-17T08:18:27.950 に答える
8

私の要件では、この段階で多くのコードを再利用する必要はありませんでした。そのため、私の抽出したコードは上記の回答のバリエーションです。

  require "json/ext"

  before_save :json_serialize  
  after_save  :json_deserialize


  def json_serialize    
    self.options = self.options.to_json
  end

  def json_deserialize    
    self.options = JSON.parse(options)
  end

  def after_find 
    json_deserialize        
  end  

乾杯、最後はとても簡単です!

于 2010-01-19T00:40:02.280 に答える
3

デフォルトを使用する独自のYAMLコーダーを作成しました。クラスは次のとおりです。

class JSONColumn
  def initialize(default={})
    @default = default
  end

  # this might be the database default and we should plan for empty strings or nils
  def load(s)
    s.present? ? JSON.load(s) : @default.clone
  end

  # this should only be nil or an object that serializes to JSON (like a hash or array)
  def dump(o)
    JSON.dump(o || @default)
  end
end

loadおよびはインスタンスメソッドであるため、モデル定義dumpの2番目の引数としてインスタンスを渡す必要があります。serializeその例を次に示します。

class Person < ActiveRecord::Base
  validate :name, :pets, :presence => true
  serialize :pets, JSONColumn.new([])
end

新しいインスタンスを作成し、インスタンスをロードし、IRBにインスタンスをダンプしようとしましたが、すべて正常に機能しているように見えました。私もそれについてブログ記事を書きました。

于 2011-11-07T22:01:48.093 に答える
3

serialize :attr, JSONusingcomposed_ofメソッドは次のように機能します。

  composed_of :auth,
              :class_name => 'ActiveSupport::JSON',
              :mapping => %w(url to_json),
              :constructor => Proc.new { |url| ActiveSupport::JSON.decode(url) }

ここで、url は json を使用してシリアル化される属性であり、auth はモデルで使用できる新しいメソッドであり、その値を json 形式で url 属性に保存します。(まだ完全にはテストされていませんが、動作しているようです)

于 2011-05-22T12:23:15.377 に答える
1

より簡単な解決策は、MichaelRykovによるこのブログ投稿composed_ofで説明されているように使用することです。使用するコールバックが少ないため、このソリューションが気に入っています。

その要点は次のとおりです。

composed_of :settings, :class_name => 'Settings', :mapping => %w(settings to_json),
                       :constructor => Settings.method(:from_json),
                       :converter   => Settings.method(:from_json)

after_validation do |u|
  u.settings = u.settings if u.settings.dirty? # Force to serialize
end
于 2011-01-28T06:58:13.353 に答える
0

アレラン、Rails 3 でこの方法を使ったことはありますか? 私はいくぶん同じ問題を抱えており、Michael Rykov によるこの投稿に出くわしたときに連載に向かっていましたが、彼のブログ、または少なくともその投稿にコメントすることはできません。私の理解では、彼は設定クラスを定義する必要はないと言っていますが、これを試してみると、設定が定義されていないことがわかります。それで、あなたがそれを使用したかどうか、さらに何を説明すべきか疑問に思っていましたか? ありがとう。

于 2011-04-15T14:41:29.220 に答える