モデルのdeep copy

シリアライズしてデシリアライズすればいいじゃんと思って、まずMarshalを使ってみる。

obj2 = Marshal.load(Marshal.dump(obj1))

しかし、これだとobj2のidもobj1のidが復元されてしまう。というわけでこれはパス。


次、activerecord-2.3.2/lib/active_record/serializers/json_serializer.rbをみて

    #   konata.to_json(:include => { :posts => {
    #                                  :include => { :comments => {
    #                                                :only => :body } },
    #                                  :only => :title } })
    #   # => {"id": 1, "name": "Konata Izumi", "age": 16,
    #         "created_at": "2006/08/01", "awesome": true,
    #         "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
    #                    "title": "Welcome to the weblog"},
    #                   {"comments": [{"body": "Don't think too hard"}],
    #                    "title": "So I was thinking"}]}

こんなことができるんだーといそいそとやってみたら、to_jsonはできるものの、ネストしたモデルを含むjsonをfrom_jsonで読み込むと、

ActiveRecord::AssociationTypeMismatch: <モデル名>(#29678190) expected, got Hash(#101470)

とか出る。うーん、パス。


で、ググってみたらこんなの見つけました。
http://blog.defv.be/2008/3/27/activerecord-deepclone-plugin

インストールは

ruby script/plugin install git://github.com/DefV/deep_cloning.git

でオッケー。こりゃ楽かも。


P.S.
メソッド名がビミョー。cloneなのに、返ってきたオブジェクトが frozen? => false なのが気になる・・・。cloneじゃなくてdupじゃん。

PS2.
って思ってたら、ActiveRecord::Baseがそういう実装なのね。うーん、なんか気持ち悪。