1

バックアップを作成するために、一連のオブジェクトをファイルにシリアル化することを目指しています。モデルのメソッドを使用して、その作業を開始しました (ここでは、2 つの ActiveRecords foo と bar があると仮定して簡略化します)。

def backup(file, foo, bar)  
  file.write(foo.to_json(root: true))
  file.write(bar.to_json(root: true))  
end  

これにより、必要に応じてファイルが得られます。この場合、2 つのレコードがあります。

{"foo":{"Account_id":1,"Name":"F","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}}  
{"bar":{"Account_id":1,"Name":"B","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}}  

後日、そのバックアップを読み込んでそれらのオブジェクトを再インスタンス化し、おそらくそれらをデータベースに永続化したいと考えています。私の目的は、ファイルを反復処理して各オブジェクトのタイプをチェックし、適切なオブジェクトをインスタンス化することです。

私はロジックの一部を持っていますが、まだすべてではありません。インスタンス化する前に、シリアル化された各オブジェクトのタイプを決定する方法を理解していません。復元用のコードは次のとおりです。

def restore(file)
  file.each_line do |line|  
    **<some magic that parses my line into objectType and objectHash>**
    case objectType
    when :foo
      Foo.new.from_json(objectHash)
      Foo.process
      Foo.save!
    when :bar
      Bar.new.from_json(objectHash)
      Bar.process
      Bar.save!
    end
  end
end  

私が探しているのは、「いくつかの魔法」セクションに入るビットです。行を直接解析して foo か bar かを判断するコードを書くことはできますが、Rails/Ruby でこれを自動的に行うためのトリッキーな方法がおそらくあると思います。残念ながら、この場合、Google は私の味方ではありません。私が見ることができるのは、Web 要求で json に焦点を当てているページだけですが、この方法で json を解析していません。不足しているものはありますか、または文字列を直接分割してオブジェクト型を読み取るコードを書く必要がありますか?

文字列を直接分割するコードを書くとしたら、次のように書きます。

objectType = line[/^{"(\w*)"=>(.*)}/, 1]  
objectHash = line[/{"(\w*)"=>(.*)}/, 2]

これはかなり醜く、もっと良い方法があると確信しています(私はまだ調査中です)が、これが正しいアプローチであるかどうかはわかりません.json表現を自動的に見て、インスタンス化するオブジェクトのルート値。

最後に、from_json を使用した実際のインスタンス化も機能していません。ActiveRecord のどのフィールドにもデータが入力されていません。nil パラメーターが返されるので、解析構文が正しくないと思います。

したがって、次の 3 つの質問があります。

  1. どのオブジェクトが欠けているのかを判断する方法はありますか?
  2. 存在せず、正規表現を使用する必要がある場合、同じ正規表現を持つ2行ではなく、行の両方のビットを一度に解析する構文はありますか?
  3. from_json 構文は不満に見えます。ここに欠けている構文はありますか? (もはや質問ではありません-上記のコードは修正されました。to_jsonであるべきときにas_jsonを使用していましたが、ドキュメントはそれについてかなり不明確です....)

(注:私の質問を明確にするために時間をかけて編集します。また、機能する正規表現を取得したため(以前は機能しませんでした)、それでも非常にエレガントかどうかはわかりません。)

詳細情報-ここでさらに掘り下げた問題の1つは、as_jsonが実際にjsonを提供していないことです-ファイルにあるのはハッシュであり、jsonではありません。さらに、ハッシュ内の created_at と lastupdated_at の値は引用符で囲まれていないため、基本的にはそれが途中で解析が失敗する原因となっています。as_json の代わりに to_json を使用する必要があることがわかりましたが、ドキュメントでは as_json が機能するはずです。

4

2 に答える 2

0

OK、それで私はうまくいくものを持っていると思います。それがエレガントであるとはまったく確信していませんが、結果は得られます。後で時間をかけて、きれいにしようと思います。

コードは次のようになります。

file.each_line do |line|
  objectType = line[/^{"(\w*)":(.*)}/, 1]
  objectJSON = line[/{"(\w*)":(.*)}/, 2]
  objectHash = JSON.parse(objectJSON)
  case objectType
  when 'foo'
    restoredFoo = Foo.new(objectHash.except('id', 'created_at', 'updated_at'))
    restoredFoo.created_at = objectHash['created_at']
    restoredFoo.updated_at = objectHash['updated_at']
    restoredFoo.save!
  end
  when 'bar'
    restoredBar = Bar.new(objectHash.except('id', 'created_at', 'updated_at'))
    restoredBar.created_at = objectHash['created_at']
    restoredBar.updated_at = objectHash['updated_at']
    restoredBar.save!
  end
end

注意事項:

  1. JSON.parse ではなく、モデルで from_json メソッドを使用するオブジェクトを作成する方法が必要だと思います。これをしないと from_json が何の役に立つのかわかりません!!
  2. mass_assignment を楽しんでいます。:without_protection => true は実際には使用したくありませんが、これはオプションです。私の懸念は、created_at と updated_at を元の状態に戻したいということですが、新しい ID が必要です。私は自分のアプリケーションのいくつかのエンティティに対してこれを行う予定です。コードで attributes_protected を複製することは本当に望んでいませんでした。あまり DRY ではないようです。
  3. 私の正規表現が1回の呼び出しでobjectTypeとobjectJSONの両方を提供できることはまだかなり確信しています

しかし、そうは言っても、それは機能します。これは良い一歩です。

于 2013-04-21T06:42:46.600 に答える