0

グラフに表示される日時とデータを含むドキュメントが与えられた場合、BSON から Ruby に変換してから最終的に JSON に変換せずに、クエリ結果を直接返すにはどうすればよいですか?

問題: クライアントの時刻値は BSON に正しく格納されていますが、Ruby を使用するとtime.to_i * 1000、返された JSON に正しく格納するために必要な Time オブジェクトに変換されます。いずれにせよ、データを変換する必要がないので、これはもったいない気がします。

Heroku + MongoHQ で Rails、Mongoid を実行しています。クエリの承認は Rails アプリに任せたいのですが、応答を Ruby オブジェクトに変換することはしません。

def show_graph
  raw_bson = TheModel.all_raw_documents_matching(query_params)
  raw_bson.to_json  
  # Alternatively, this BSON to JSON could be happening client side. 
  # side. Whatever, just don't convert to ruby objects...
end
4

1 に答える 1

0

あなたの問題には多くの視点があります。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 プロセスをスキップしたい場合はmongoizedemongoizeメソッドを定義する必要があります。ここでドキュメントを見つけることができます: Custom Field Serialization

**アップデート**

問題はデシリアライズではなくシリアライズです。クエリから生の BSON を取得した場合でも、TimeRuby オブジェクトの文字列表現が得られます。Timerubyクラスから渡さないと、時刻の文字列表現を整数表現に変換できないため、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} 
于 2013-04-30T14:11:12.857 に答える