Open5

controllerを綺麗に書けるgemを作りたい

youtamanyoutaman

gemの作り方をさっと調べてみた感じ

gemは以下のいずれかに該当し、下に行くほど規模がデカくなるイメージ。

  • Railtie
  • Engine
  • MountableEngine

https://qiita.com/kidach1/items/565c2c077ae8d15fe3a8
https://speakerdeck.com/onunu/railtiedepluginwozuo-rou

もしくはPOROを提供するだけもある。

自分の思想的にEngine, MountableEngineはできるだけ使いたくない。
Railtie or POROのgemを作りたい。

POROで作れないか試してみてrailsの力を借りたくなったらRailtieで実装する方向で

youtamanyoutaman

なんで作りたいか

以下のようなcontrollerが嫌だから

  • def indexdef index_paramsが離れている ( エンドポイントのみをpublicにする都合上 )
  • fat controllerを避けるために別の場所をfatにして、結局コードリーディングの手間を増やしているだけ

イメージしている完成系

controller

class GetUserController < ApplicationController
  include GemModule # このモジュールを作る

  content_type 'application/json'
  serializer :XxxSerializer, method: :serialize # XxxSerializerのserializeメソッドにcallの戻り値を渡す

  params :id, :integer, required: true

  def call
    User.find(params[:id])
  end

  def headers
    {
      key: 'value'
    }
  end
end

config/routes.rb

Rails.application.routes.draw do
  # registerメソッドは{ action: :call, controller: 'get_user_controller' }を返す
  get '/users/:id', **GetUserController.register
end

controllerの書き方(DSLとか)はmoduleの実装次第でどうにでもなりそう。
routes.rbの書き方はできるだけ既存の記法を活かしたかった。namespaceやscope, get等は使えるが、resource, resourcesは難しそう。

controller内でurlを設定するのは個人的には嫌。routes.rb内でurlと実装しているcontrollerが対になって記載されている方が好み。

# これはしない
class GetUserController < ApplicationController
  include GemModule

  url '/user/:id'
end

routes.rbでresource, resourcesも使えるようしたいが、railtie, engineで実装する必要がありそうなので後回し。

youtamanyoutaman

将来的に追加したいDSL

  • post, patchなどのmutationではform: CreateUserFormでform objectパターンを簡単に呼び出せる
  • getの際はquery: SearchUsersQueryでquery objectパターンを簡単に呼び出せる