検索APIの追加
一覧、詳細、作成、更新、削除のための基本的なAPIはScaffoldingによって簡単に実装できました。ただし実用的なWebサービスでは、検索や一括更新、一括削除といったAPIも必要になってくるでしょう。ここからは検索APIを実装し、独自のAPIの実装手順を紹介します。
APIの仕様
検索APIは、検索語を受け取り、それをnameフィールド、contentフィールドに含むものを配列で返すものとします。アクションは、GETメソッドでもPOSTメソッドでも受け付けるものとします。クエリパラメータは「q=keyword」のように指定するとします。
アクションを追加する
既定で存在するリソースベースのルーティングルールに、searchアクションを追加します。config/routes.rbファイルのresourcesメソッドにdoブロックを続けて、collectionブロックを追記してさらにsearchアクションを追記します。
resources :messages do
collection do
get 'search' # messageコントローラのsearchアクション(GET)
post 'search' # messageコントローラのsearchアクション(POST)
end
end
[NOTE]collectionブロックとmemberブロック
ここではcollectionブロックを追記しましたが、これはresourcesメソッドで定義されるもの以外のルートを定義したい場合に用います。対となるものにmemberブロックがあります。これらの違いは以下の通りです。APIの機能によって使い分ける必要があります。
- collection…search(検索)のように、ルートに対象のレコードを表すパラメータを含まない
- member…info(情報取得)のように、ルートに対象のレコードを表すパラメータを含む
app/controllers/messages_controller.rbファイルには、アクションの処理内容を追記します。クエリパラメータが指定されている場合のみnameフィールドとcontentフィールドにあいまい検索を実行し、見つかればレコードの配列をJSON形式で返します。
…略…
# GET /messages/search
# POST /messages/search
def search
@messages = [] # 既定値は空の配列
@query = params[:q]
if !@query.blank? # クエリパラメータが存在する場合のみ
@query = '%' + @query + '%'
begin
@messages = Message.where(["name like ? or content like ?", @query, @query])
rescue # 例外発生時には既定値を返す
end
end
render json: @messages
end
private
…略…
アクション(API)を呼び出す
Pumaサーバを起動し、curlコマンドでリクエストを発行してみましょう。GETメソッドとPOSTメソッドの両方のケースを試しています。GETメソッドで呼び出す場合には、URLを引用符で囲む必要があることに注意してください。検索語を含むレコードがあればその結果が配列で返り、見つからない、検索語が指定されていないという場合には空の配列が返ります。
% curl 'http://localhost:3000/messages/search?q=Nao'
[{"id":1,"name":"Nao","content":"こんにちは!","posted":"2022-12-19T18:01:34.000Z","created_at":"2022-12-19T09:07:34.682Z","updated_at":"2022-12-19T09:07:34.682Z"}]
% curl 'http://localhost:3000/messages/search' -X POST -d "q=Nao"
…同様なので略…
% curl 'http://localhost:3000/messages/search?q=Zeus'
[]
% curl 'http://localhost:3000/messages/search?q='
[]
% curl 'http://localhost:3000/messages/search'
[]
このように、簡単な手順でAPIが実装できました。
まとめ
今回は、RailsのAPIモードを紹介しました。APIモードにおいても、通常のRailsアプリケーションの開発ノウハウがそのまま活用できることをお伝えできたのではないかと思います。次回からは、Action Cableを用いたリアルタイムWebを紹介します。
