programing

YAML 대신 JSON을 사용하여 ActiveRecord 시리얼화

shortcode 2023. 2. 23. 23:30
반응형

YAML 대신 JSON을 사용하여 ActiveRecord 시리얼화

직렬화된 열을 사용하는 모델이 있습니다.

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

이 시리얼화에 YAML이 아닌 JSON을 사용하는 방법이 있습니까?

Rails 3.1에서는

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

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

레일과 함께 제공되는 기본 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

갱신하다

훨씬 더 적절한 Rails > = 3.1 답변을 보려면 아래 중간 등급의 답변을 참조하십시오.이는 Rails < 3.1에 대한 훌륭한 답변입니다.

아마 이게 네가 찾고 있는 거겠지.

Form.find(:first).to_json

갱신하다

1) 'json' Gem 설치:

gem install json

2) Json Wrapper 클래스 만들기

# 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:

건조하진 않지만 최선을 다했어요.고칠 수 있는 사람이 있다면after_findUser모델님, 정말 멋질 거예요.

이 단계에서는 많은 코드를 재사용할 필요가 없었기 때문에 위의 답변에 따라 증류 코드를 변경했습니다.

  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  

건배, 결국엔 꽤 쉬웠죠!

serialize :attr, JSON사용.composed_of방법은 다음과 같습니다.

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

여기서 url은 json을 사용하여 serialize되는 Atribute이며 auth는 url Atribute에 json 형식으로 값을 저장하는 모델에서 사용할 수 있는 새로운 메서드입니다.(아직 완전히 테스트되지 않았지만 작동하는 것 같습니다.)

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인스턴스 메서드는 인스턴스를 두 번째 인수로 전달해야 합니다.serialize모델 정의에서 사용합니다.예를 들어 다음과 같습니다.

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

새 인스턴스를 만들고, 인스턴스를 로드하고, IRB에 인스턴스를 덤프하려고 했는데 모두 정상적으로 동작하는 것 같았습니다.저도 블로그에 글을 썼어요.

보다 간단한 해결책은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

알레란, 레일 3에서 이 방법을 사용해 본 적이 있나요?저도 같은 문제가 있어서 연재를 하려고 했는데 마이클 라이코프의 글을 우연히 보게 되었습니다만, 그의 블로그에 코멘트는 할 수 없습니다.제가 알기로는 Settings 클래스를 정의할 필요가 없다고 합니다만, 이것을 시도하면 Setting은 정의되어 있지 않다고 계속 표시됩니다.그래서 나는 단지 당신이 그것을 사용했는지 그리고 무엇을 더 설명해야 했는지 궁금했다.감사해요.

언급URL : https://stackoverflow.com/questions/2080347/activerecord-serialize-using-json-instead-of-yaml

반응형