将用户定义的Ruby对象序列化为Riak时堆栈溢出

时间:2014-06-22 07:58:38

标签: ruby class stack-overflow riak

通过http://docs.basho.com/riak/latest/dev/taste-of-riak/querying-ruby工作 我注意到我出于某种原因无法将时间对象存储在riak中。

[3] pry(main)> client = Riak::Client.new(:protocol => "pbc", :pb_port => 8087, :host => "192.168.145.34")
=> #<Riak::Client [#<Node 192.168.145.34:8098:8087>]>
[4] pry(main)> 
[5] pry(main)> 
[6] pry(main)> tt = client.bucket('test')
=> #<Riak::Bucket {test}>
[7] pry(main)> v = tt.new("ttt")
=> #<Riak::RObject {test,ttt} [#<Riak::RContent [application/json]:nil>]>
[8] pry(main)> v.data = 1
=> 1
[9] pry(main)> v.store
=> #<Riak::RObject {test,ttt} [#<Riak::RContent [application/json]:1>]>
[10] pry(main)> v.data = Time.now
=> 2014-06-22 11:34:01 +0400
[11] pry(main)> v.store
SystemStackError: stack level too deep
from /home/maus/.gem/ruby/1.9.1/gems/pry-0.10.0/lib/pry/pry_instance.rb:353

之后我发现了用户定义类的情况:

[16] pry(main)> class Tst
[16] pry(main)*   def initialize(x)
[16] pry(main)*     @x = x
[16] pry(main)*   end  
[16] pry(main)* end  
=> nil
[17] pry(main)> t111 = Tst.new(111)
=> #<Tst:0x9b13f4c @x=111>
[18] pry(main)> v.data = t111
=> #<Tst:0x9b13f4c @x=111>
[19] pry(main)> v.store
SystemStackError: stack level too deep
from /home/maus/.gem/ruby/1.9.1/gems/pry-0.10.0/lib/pry/pry_instance.rb:353
[20] pry(main)> 
[21] pry(main)> v.data = [1,2,3]
=> [1, 2, 3]
[22] pry(main)> v.store
=> #<Riak::RObject {test,test_key} [#<Riak::RContent [application/json]:[1, 2, 3]>]>

我的安装看起来非常糟糕。但是如何调查呢?我使用riak-1.3.2和ruby 1.9.3p194以及以下版本的gem: 国际化-0.6.9 建设者-3.2.2 远扬-0.3.7 multi_json-1.10.1 内胎-1.0.2 了Riak-客户1.4.4.1

1 个答案:

答案 0 :(得分:2)

store方法代码路径中唯一的位置是我看到正在使用的值在BeefcakeProtobuffsBackend.ObjectMethods::dump_object中,RpbContent:value => maybe_encode(robject.raw_data)实例化,所以这似乎是是序列化自定义数据的问题。

RContent.raw_data来电Serializers::serialize

def serialize(content_type, content)
  serializer_for(content_type).dump(content)
end

Serialize只能理解很少的内容类型:

  • Serializers ['text / plain'] = TextPlain
  • Serializers ['application / json'] = ApplicationJSON
  • Serializers ['application / x-ruby-marshal'] = :: Marshal

content_type的默认值为application/json,其dump方法为:

  def dump(object)
    object.to_json(Riak.json_options)
  end

检查v.raw_data是否返回您期望的值,如果没有,请尝试设置v.content_type='text/plain'

对于您的自定义类,请确保它具有返回字符串的to_jsonto_s方法,并选择相应的content_type。