RailsでN+1が出ないようにas_jsonぽくする奴を作った

smart_json: RailsでN+1が出ないas_jsonぽい奴作りました。
https://github.com/tompng/smart_json
ちょくちょく直しながら作ってます。んで、実践投入しようかなと思ってるので記事書いとこうと。

smart_json?

gem 'smart_json', github: 'tompng/smart_json'
blogs.as_smart_json(posts: [:タイトル日付のみ, author: :詳細, comments: {user: :名前だけ}])

と指定してjsonを作れる、そして必要なincludesを自動でやってくれるのでN+1問題も起きない(はず)

smart_jsonが解決する問題:その1

posts.as_json(include: {comments: {include: :user}})

とかするとN+1クエリが出る、かといって

posts.includes(comments: :user).as_json(include: {comments: {include: :user}})

とするのはだるい。Don't repeat yourselfだくそ野郎

smart_jsonを使うと...

posts.as_smart_json(comments: :user)

smart_jsonが解決する問題:その2

as_jsonでonlyやmethodsに指定する内容は数通りしかないので、そのままだと

user.as_json(only: [:id, :name])
comment.as_json(only: [:id, :text], include: {user: {only: [:id, :name]}})
posts.as_json(include: {comments: {only: [:id, :text]}})
blogs.as_json(include: {owner: {only: ...}, posts: {include: {author: {only: ...}, comments: {only: ...}}}})

と重複だらけになってひどいしN+1対策でさらに長くなる。

smart_jsonでスタイルを定義しておけば...

class User
  smart_json_style(:default){as_json only: [:id, :name]}
end
class Comment
  smart_json_style(:default){as_json only: [:id, :text]}
  smart_json_style(:詳細, :user)
end
class Post
  smart_json_style(:簡易){{title: title, body: body[0..30]}}
  smart_json_style(:コメントなど含む, :簡易, :author, comments: :詳細)
end
user.as_smart_json
comment.as_smart_json(:詳細)
posts.as_smart_json(:comments)
blogs.as_smart_json(:owner, posts: :コメントなど含む)

とすっきり書ける。これまた依存関係全部includesしてくれる。

誰か実験台になってくれちょ
(あと似たようなのが既にあれば教えてほしい)