DearDirtyController
DearDirtyControllerは1つのcontrollerに1つのアクションを実装する方法を提供します。
Example of use in rails
class GetUserController
include DearDirtyController::Mixin
before do
Rails.logger.info "[START] get user"
end
execute do
request = ActionDispatch::Request.new(@args)
params = ActionController::Parameters.new(request.params)
User.find(params[:id])
end
after do
Rails.logger.info "[END] get user"
end
serialize do |user|
{
user: {
last_name: user.last_name,
first_name: user.first_name,
name: user.name
}
}
end
endDearDirtyController::Mixinをincludeするだけなので、特定のcontrollerでのみ使用するという選択が可能です。
上記はrailsでの使用例ですが、ApplicationControllerを継承する必要はありません。
before, execute, after, serializeのうち必要なものにブロックを渡すだけでアクションを実装することができます。
Routing
railsの通常のルーティングにDearDirtyController::Mixinをincludeしたクラスを渡すだけです。
namespaceやscope, get等は変わらずに使えますが、resource, resourcesは使用できない点に注意してください。
この記載方法によりどのcontrollerに処理を実装されているのが明瞭であり、また、エディタのコードジャンプ等も使えるようになります。
scope :api do
get "/users/:id", to: GetUserController
post "users", to: PostUserController
endInstallation
Add this line to your application's Gemfile:
gem "dear-dirty-controller", require: "dear_dirty_controller"And then execute:
$ bundle install
Documentation
usable instance variables
| name | description |
|---|---|
| @args | .callに渡される引数の配列 |
| @context | before, execute, after, serializeブロック内で共有可能な変数 |
execute
class XxxController
include DearDirtyController::Mixin
execute do
# do anything
end
endbefore, after hook
before hook内ではskip_execution!メソッドを呼び出すことでexecuteブロックの実行をキャンセルできます。
class XxxController
include DearDirtyController::Mixin
before do
@context.current_user = get_user_method
if @context.current_user.nil?
skip_execution!
body { message: "User not found" }
status 404
end
end
# implement anything
after do
if @context.success? # success? is set by execute block
MailSender.call
end
end
endserialize, serializer
serialize, serializerを使用してexecuteの結果をserializeすることができます
serializeとserializerが同時に使用されている場合、serializeに渡したブロックが優先されます。
どちらも使用されていない場合、デフォルトで.to_jsonが呼び出されます。
class XxxSerializer
def self.serialize(user)
{
id: user.id,
name: user.name
}
end
end
def XxxController
include DearDirtyController::Mixin
serializer XxxSerializer, method: :serialize # method optionのデフォルト値は:call
serialize do |user|
{
id: user.id,
name: user.name
}
end
endrescue_from, rescue_all
class XxxController
include DearDirtyController::Mixin
rescue_from ActiveRecord::RecordNotFound do |_error|
status 404
body "record not found"
end
rescue_all do |_error|
status 501
body "something went wrong"
end
execute do
user = User.find(-1) # raise ActiveRecord::RecordNotFound
end
endheaders, content_type, status, body
headers, content_type, status, bodyメソッドを用いてレスポンスを設定することができます。
headers, content_type, statusはクラスメソッドも用意していますが、インスタンスメソッドが使用された場合はインスタンスメソッドに渡された値を優先します。
class XxxController
include DearDirtyController::Mixin
headers { "X-SOME-KEY": "xxxx" }
content_type "Application/json"
status 200
before do
user = User.find_by(id: 1)
end
execute do
if user.present?
body { id: user.id, name: user.name }
else
status 404
body "user not found"
end
end
endTips for rails
request
@argsに格納されているActionDispatch::Routingから渡される引数をActionDispatch::Requestのインスタンスにすることで
通常のApplicationControllerと同様にリクエストを扱うことができるようになります。
この処理をBaseControllerとして定義することをお勧めします。
class BaseController
include DearDirtyController::Mixin
attr_reader :request
def initialize(args)
super
@request = ActionDispatch::Request.new(args)
end
def params
ActionController::Parameters.new(request.params)
end
end
class XxxController < BaseController
execute do
User.find(params[:id])
end
end