ActiveRecord serialize using JSON instead of YAML

Tob*_*ede 55 serialization activerecord json yaml ruby-on-rails

I have a model that uses a serialized column:

class Form < ActiveRecord::Base
  serialize :options, Hash
end
Run Code Online (Sandbox Code Playgroud)

Is there a way to make this serialization use JSON instead of YAML?

Jus*_* L. 157

在Rails 3.1中你可以

class Form < ActiveRecord::Base
  serialize :column, JSON
end
Run Code Online (Sandbox Code Playgroud)

希望有所帮助

  • 为了澄清@BenAtkin所说的内容,如果传递给serialize调用的Class响应`.dump(obj)`和`.load(obj)`,它将被用作编码器/串行器.否则,默认的YAMLColumn类用作编码器/串行器.转储和加载方法也可以直接在模型类中实现,您不必*使用专用的单独类来进行编码. (4认同)
  • 它已在3.2.5中修复 (2认同)

bal*_*alu 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
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

参考文献:

定义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


St.*_*and 11

更新

请参阅下面的mid评分较高的答案,以获得更合适的Rails> = 3.1答案.这是Rails <3.1的一个很好的答案.

可能这就是你要找的东西.

Form.find(:first).to_json
Run Code Online (Sandbox Code Playgroud)

更新

1)安装'JSON' 宝石:

gem install json
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

4)测试一下!

User.create :name => {"a"=>"b", "c"=>["d", "e"]}
Run Code Online (Sandbox Code Playgroud)

PS:

它不是很干,但我尽了最大努力.如果任何人都可以修复after_findUser模型,这将是巨大的.

  • "加密/解密"是误导性的名称,因为不涉及加密.应该是"编码/解码".现在使用下面提到的Rails 3.1解决方案进行模拟. (3认同)

Tob*_*ede 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  
Run Code Online (Sandbox Code Playgroud)

干杯,到底相当容易!