あなたの問題には多くの視点があります。BSON デシリアライゼーションの代わりに、メソッドがRuby オブジェクトto_json
のシリアライゼーションをどのように処理するかがより重要にDate
なります。Time
私の頭に浮かぶ最も簡単でトリッキーな方法は、クラスのas_json
メソッドをオーバーライドすることです。Time
class Time
def as_json(options={})
self.to_i * 1000
end
end
hash = {:time => Time.now}
hash.to_json # "{\"a\":1367329412000}"
イニシャライザに入れることができます。これは非常に簡単な解決策ですが、アプリ内のすべての RubyTime
オブジェクトがカスタム メソッドでシリアル化されることに注意する必要があります。これは問題ないかもしれませんが、言うのは本当に難しいです.gemがこれに依存する可能性があるかどうか.
より安全な方法は、ラッパーを作成し、代わりに呼び出すことですto_json
。
def to_json_with_time
converted_hash = self.attributes.map{|k,v| {k => v.to_i * 1000 if v.is_a?(Time)} }.reduce(:merge)
converted_hash.to_json
end
最後に、Mongoid がオブジェクトをシリアライズおよびデシリアライズする方法を本当にオーバーライドしたい場合、および BSON プロセスをスキップしたい場合はmongoize
、demongoize
メソッドを定義する必要があります。ここでドキュメントを見つけることができます: Custom Field Serialization
**アップデート**
問題はデシリアライズではなくシリアライズです。クエリから生の BSON を取得した場合でも、Time
Ruby オブジェクトの文字列表現が得られます。Time
rubyクラスから渡さないと、時刻の文字列表現を整数表現に変換できないため、BSON を直接 JSON に変換することはできません。
Mongoid カスタム フィールド シリアル化の使用例を次に示します。
class Foo
include Mongoid::Document
field :bar, type: Time
end
class Time
# The instance method mongoize take an instance of your object, and converts it into how it will be stored in the database
def mongoize
self.to_i * 1000
end
# The class method mongoize takes an object that you would use to set on your model from your application code, and create the object as it would be stored in the database
def self.mongoize(o)
o.mongoize
end
# The class method demongoize takes an object as how it was stored in the database, and is responsible for instantiating an object of your custom type.
def self.demongoize(object)
object
end
end
Foo.create(:bar => Time.now) #<Foo _id: 518295cebb9ab4e1d2000006, _type: nil, bar: 1367512526>
Foo.last.as_json # {"_id"=>"518295cebb9ab4e1d2000006", "bar"=>1367512526}