LoginSignup
4
2

More than 1 year has passed since last update.

railsのconstraintsを使って、ルーティングを制限する

Posted at

おはようございます!
朝から警察の方に職務質問を受けてしまった、プレイライフの熊崎です。

そんな怪しさ全開の雰囲気が出ていた僕ですが、引き続きアウトプットを行なっていきたいと思います。

constraintsとは?

:constraintsオプションを使って、動的セグメントのURLフォーマットを特定の形式に制限できます。
ref: https://railsguides.jp/routing.html#セグメントを制限する

→ ルーティングに制限を設定するオプション。constraintsの和訳が制約なので、そのまんま。

制限の仕方

routes.rb
get '/articles/:id' , to: 'articles#show', constraints: { id: /[A-Z]\d{5}/ }
# match => /articles/A11111, not_match => /articles/111

また、リクエスト内容に応じて制限を加えることができる。
ref: https://railsguides.jp/routing.html#リクエスト内容に応じて制限を加える

routes.rb
get '/articles/:id' , to: 'articles#show', constraints: { port: 3000 }
# ポート番号が3000以外の場合、マッチしない。

また、以下のようにmatchesメソッドを使用して制限を加えることができる。

routes.rb
get '/articles/:id' , to: 'articles#show', constraints: ArticleIdRestrict.new

class ArticleIdRestrict
  def matches?(request)
    # URLの後ろについているidが、記事テーブルのidの中に含まれているか?
    Article.pluck(:id).include?(request[:id])
  end
end

どんな時に使用するのか?

→ ルーティングを制限したいとき。

例: 記事を、ジャンルで絞り込みを行う際。

genresテーブル

id name
1 SQL
2 Rails
routes.rb
get '/articles/:genre_name', to: 'articles#index', constraints: ArticleGenreRestrict.new

class ArticleGenreRestrict
  def matches?(request)
    # ジャンル名がSQLかRailsの場合のみマッチする。
    Genre.pluck(:name).include?(request[:genre_name])
  end
end

メリット

  • コントローラー側で、クエリパラメータが正しいかどうかを判断する必要がなくなる。

注意点

  • 以下のように書くと、指定したルーティングが無効になる。
routes.rb
resources :articles, only: %i[index]
get '/articles/:genre_name', to: 'articles#index', constraints: ArticleGenreRestrict.new

class ArticleGenreRestrict
  def matches?(request)
    # ジャンル名がSQLかRailsの場合のみマッチする。
    Genre.pluck(:name).include?(request[:genre_name])
  end
end

理由

Railsのルーティングは、ルーティングファイルの「上からの記載順に」マッチします。このため、たとえばresources :photosというルーティングがget 'photos/poll'よりも前の行にあれば、resources行のshowアクションがget行の記述よりも優先されますので、get行のルーティングは有効になりません。これを修正するには、get行をresources行 よりも上 の行に移動してください。これにより、get行がマッチするようになります。
ref: https://railsguides.jp/routing.html#crud、動詞、アクション

参考記事

https://railsguides.jp/routing.html#セグメントを制限する

https://railsguides.jp/routing.html#リクエスト内容に応じて制限を加える

https://railsguides.jp/routing.html#crud、動詞、アクション

最後に

ルーティング周りでこんな機能があるとは思わなかった。
まだまだ知らない機能がいっぱいあるので、1つ1つ覚えていく必要があると感じた。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2