복붙노트

[RUBY-ON-RAILS] JSON 대신 YAML을 사용하여 액티브의 직렬화

RUBY-ON-RAILS

JSON 대신 YAML을 사용하여 액티브의 직렬화

나는 직렬화 된 열을 사용하는 모델을 가지고 :

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

대신 YAML의 직렬화를 사용 JSON을 만들 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.레일 3.1 당신은 할 수

    레일 3.1 당신은 할 수

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

    희망이 도움이

  2. ==============================

    2.레일 3.1에서는 직렬화와 사용자 정의 코더를 사용할 수 있습니다.

    레일 3.1에서는 직렬화와 사용자 정의 코더를 사용할 수 있습니다.

    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
    

    도움이 되었기를 바랍니다.

    참고 :

    직렬화의 정의 : 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

    부하에 대한 호출이 발생되는 곳이 있습니다 : https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods/read.rb#L132

  3. ==============================

    3.최신 정보

    최신 정보

    훨씬 더 적절한 레일> = 3.1 답변을 아래 중반의 높은 평가 대답을 참조하십시오. 이 레일 <3.1에 대한 좋은 대답이다.

    아마 이것은 당신이 찾고있는 것입니다.

    Form.find(:first).to_json
    

    최신 정보

    1) 'JSON'보석을 설치합니다 :

    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"]}
    

    그것은 매우 건조하지,하지만 난 내 최선했다. 누군가가 사용자 모델에 after_find 해결할 수 있으면 좋을 것이다.

  4. ==============================

    4.내 증류수 코드는 위의 대답에 변화가 그래서 내 요구 사항은이 단계에서 코드 재사용이 많이 필요하지 않았다 :

    내 증류수 코드는 위의 대답에 변화가 그래서 내 요구 사항은이 단계에서 코드 재사용이 많이 필요하지 않았다 :

      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  
    

    건배, 아주 쉽게 결국!

  5. ==============================

    5.나는 기본 소요 내 자신의 YAML 코더를 썼다. 다음은 클래스입니다 :

    나는 기본 소요 내 자신의 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
    

    부하 덤프가 인스턴스 메소드이기 때문에이 모델 정의 직렬화에 두 번째 인수로 전달되는 인스턴스를 필요로한다. 여기의 예입니다 :

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

    나는, 새로운 인스턴스를 생성 인스턴스를로드하고, IRB의 인스턴스를 덤핑했는데, 모두 제대로 작동하는 것 같았다. 나도 그것에 대해 블로그에 글을 남긴 바있다.

  6. ==============================

    6.직렬화 : ATTR는 JSON 사용 composed_of 방법은 다음과 같이 작동합니다 :

    직렬화 : 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을 사용하여 직렬화 및 인증은 url 속성에 JSON 형식의 값을 저장 모델에서 사용할 수있는 새로운 방법입니다. (완벽하게 작동하는 것으로 아직 테스트하지만 보인다되지 않음)

  7. ==============================

    7.간단한 해결책은 마이클 Rykov하여이 블로그 게시물에 설명 된대로 composed_of 사용하는 것입니다. 이 적은 콜백의 사용을 필요로하기 때문에 나는이 솔루션을 좋아한다.

    간단한 해결책은 마이클 Rykov하여이 블로그 게시물에 설명 된대로 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
    
  8. ==============================

    8.Aleran, 당신은 레일 3이 방법을 사용하는가? 나는 다소 동일한 문제가 있는데 나는 마이클 Rykov에 의해이 게시물에 실행할 때 직렬화 향하고했지만, 자신의 블로그에 코멘트하는 것은 해당 게시물에 적어도 수 없습니다, 또는. 내 그는 그러나, 당신은 설정 클래스를 정의 할 필요가 없습니다 것을 말하고 이해하는 나는이가 그 설정이 정의되지 않은 말해 유지하려고 할 때. 그래서 난 그냥 당신이 그것을 사용하고 무엇을 더 설명해야하는 경우 궁금 해서요? 감사.

    Aleran, 당신은 레일 3이 방법을 사용하는가? 나는 다소 동일한 문제가 있는데 나는 마이클 Rykov에 의해이 게시물에 실행할 때 직렬화 향하고했지만, 자신의 블로그에 코멘트하는 것은 해당 게시물에 적어도 수 없습니다, 또는. 내 그는 그러나, 당신은 설정 클래스를 정의 할 필요가 없습니다 것을 말하고 이해하는 나는이가 그 설정이 정의되지 않은 말해 유지하려고 할 때. 그래서 난 그냥 당신이 그것을 사용하고 무엇을 더 설명해야하는 경우 궁금 해서요? 감사.

  9. from https://stackoverflow.com/questions/2080347/activerecord-serialize-using-json-instead-of-yaml by cc-by-sa and MIT license