ActiveRecordモデルの独自で作成したメソッドもjson(もしくはxml)で出力したい

シチュエーション的には、

class Book < ActiveRecord::Base
  attr_accessible :title, :author, :price

  def price_with_tax
    return self.price*1.05
  end
end

こんな感じでモデルに独自のメソッド(price_with_tax)がある場合、

  # GET /books/1
  # GET /books/1.json
  def show
    @book = Book.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @book}
    end
  end

上記のような自動で生成されるコントローラーでは、

http://localhost:3001/books/1.json
{"author":"aaa","created_at":"2013-01-04T07:49:50Z","id":1,"price":1000,"title":"aaa","updated_at":"2013-01-04T07:49:50Z"}

jsonに独自メソッドは出てきません。

そこでコントローラーを、

  # GET /books/1
  # GET /books/1.json
  def show
    @book = Book.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @book, :methods => [:price_with_tax]}
    end
  end

上記のようにjsonないしxmlに:methodsオプションで該当の独自メソッドを追加してあげると、

{"author":"aaa","created_at":"2013-01-04T07:49:50Z","id":1,"price":1000,"title":"aaa","updated_at":"2013-01-04T07:49:50Z","price_with_tax":1050.0}

出てきた!

これはActiveRecordのto_jsonないしto_xmlメソッドの、
オプションですので、

1.9.3-p194 :001 > book=Book.find(1)
  Book Load (5.7ms)  SELECT "books".* FROM "books" WHERE "books"."id" = ? LIMIT 1  [["id", 1]]
 => #<Book id: 1, title: "aaa", author: "aaa", price: 1000, created_at: "2013-01-04 07:49:50", updated_at: "2013-01-04 07:49:50"> 
1.9.3-p194 :003 > book.to_json
 => "{\"author\":\"aaa\",\"created_at\":\"2013-01-04T07:49:50Z\",\"id\":1,\"price\":1000,\"title\":\"aaa\",\"updated_at\":\"2013-01-04T07:49:50Z\"}" 
1.9.3-p194 :002 > book.to_json :methods => [:price_with_tax]
 => "{\"author\":\"aaa\",\"created_at\":\"2013-01-04T07:49:50Z\",\"id\":1,\"price\":1000,\"title\":\"aaa\",\"updated_at\":\"2013-01-04T07:49:50Z\",\"price_with_tax\":1050.0}" 
1.9.3-p194 :004 > 

このようにも可能!です!見にくっ!

参考ページ