##環境
- ruby歴 初心者
- rails5
- ruby 2.4.1p111
##これはなに?
grape を用いた api 開発時にヘルパーメソッドを別ファイルに切り出して活用する方法のメモです。
「ここ間違ってるよ!」
「ここはこうした方がいいんじゃん?」
などなどあればコメントお願い致しますm(_ _)m
##発端
grape を用いた api 開発を進めていく中で、共通の処理、独自エラーなどをルートファイルに書きまくって
fat & unreadable になったため切り出しを考えました。
ディレクトリ状況としては下記のとおりです。
├── app
│ ├── apis
│ │ └── api
│ │ ├── concerns
│ │ ├── root.rb
│ │ └── v1
│ │ └── sample.rb
##実装
はまった部分はありましたが、先に結果を書きます。
※はまった部分に関しては、後述しますので興味があれば!
まず、共通処理部分をモジュールとして切り出します。
今回、バージョンごとのヘルパーメソッドとするので
モジュール名は V1::Helpers::AuthenticateHelper
とします。
名前空間を V1::Helpers
としているので
下記のように配置します。
├── app
│ ├── apis
│ │ └── api
│ │ ├── concerns
│ │ ├── root.rb
│ │ └── v1
│ │ ├── sample.rb
│ │ └── helpers
│ │ └── authenticate_helper.rb
あとは、それぞれの実装
module V1
module Helpers
module AuthenticateHelper
def authenticate!
# someting proccess...
end
def current_user
# someting proccess...
end
end
end
end
class API::ROOT < Grape::API
helpers V1::Helpers::AuthenticateHelper # -> ここに追加
version "v1", using: :path
format :json
formatter :json, Grape::Formatter::Rabl
prefix "api"
namespace :sp do
mount API::V1::Sample
end
# something method & proccess
end
実際の利用シーン
※ rable を組み合わせて実装しています。
class API::V1::CalendarPhotoAssets < Grape::API
before { authenticate! }
get :samples, rabl: "samples/index" do
@samples = current_user.samples
end
end
##名前空間とMix-in
モジュールには名前空間
とMix-in
という複数の役割があるという理解ができておらずハマってしまいました。
自分はMix-in
のみで考えていたため、うまく読み込めずメソッドをコールしても「そんなメソッドねえよ」と怒られるばかりでした。
V1::Helper
の部分は名前空間なのでMix-in
する対象とは何も関係ありません。
##GrapeにおけるMix-in
最初、 include V1::Helpers::AuthenticateHelper
と宣言していましたが、エラーしていました。
これは grape の実装手順に則っていたためですが include
ではなく helpers
でモジュールを Mix-in
します。
include
する場合は、ROOT を継承すれば問題ありません。
##おまけ
ヘルパーモジュールが増えてくると
下記のように箇条書きされていき fat 要因になります。
class API::ROOT < Grape::API
helpers V1::Helpers::AuthenticateHelper
helpers V1::Helpers::Sample1Helper
helpers V1::Helpers::Sample2Helper
helpers V1::Helpers::Sample3Helper
version "v1", using: :path
format :json
formatter :json, Grape::Formatter::Rabl
prefix "api"
namespace :sp do
mount API::V1::Sample
end
# something method & proccess
end
なので、宣言自体を切り出して
1行の宣言で済むようにします。
※ namespace名と同じファイル名にしてください
├── app
│ ├── apis
│ │ └── api
│ │ ├── concerns
│ │ ├── root.rb
│ │ └── v1
│ │ ├── sample.rb
│ │ ├── helpers.rb # -> ここに namespace名.rb を追加
│ │ └── helpers
│ │ └── authenticate_helper.rb
module V1
module Helpers
# helpers は grape だけなので include で Mix-inします
include V1::Helpers::AuthenticateHelper
include V1::Helpers::Sample1Helper
include V1::Helpers::Sample2Helper
include V1::Helpers::Sample3Helper
end
end
class API::ROOT < Grape::API
helpers V1::Helpers
version "v1", using: :path
format :json
formatter :json, Grape::Formatter::Rabl
prefix "api"
namespace :sp do
mount API::V1::Sample
end
# something method & proccess
end
##学んだこと
・モジュールの役割について
・Grape における Mix-in
##参考
・RubyのModuleの使い方とはいったい
・rubyのモジュールを名前空間で使っているのかmix-inで使っているのか