1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsでto_paramメソッドが呼び出せない

Posted at

概要

SEO対策の一環として、RailsアプリケーションのURLに含まれるidを固有名詞に置き換える実装を行いました。
例えば、以下のようなケースです。

# これを
https://spocale.com/fruit/1
# 以下の形式にしたい。
https://spocale.com/fruit/apple

フルーツに関する一覧ページがあり、そこから「りんご」を選択して詳細ページに飛ぶ場合を想定します。このとき、URLのid部分をappleという固有の文字列に変えたいとします。

ただし、既存のURLを突然変更すると、ブックマークなどで保存されている従来のURLが使えなくなる可能性があります。そこで、id付きの従来のURLも維持しつつ、新しい形式のURLも利用できるように実装しました。この記事では、その過程で直面した課題と解決方法についてまとめます。

対象読者

  • Railsアプリケーションでid付きのURLを固有名詞で表示する方法を知りたい方
  • 既存のURL形式を維持しつつ、新しいURL形式を導入したいと考えている方

実装内容

to_paramメソッドの定義

まず、モデル内でto_paramメソッドをオーバーライドし、URL生成時にid以外の値を使うように定義します。今回は、Fruitモデルにtype_stringというURLで使用する文字列を保存するカラムがあるとします。

# app/models/fruit.rb

class Fruit < ActiveRecord::Base
  # to_paramをオーバーライドしてtype_stringを返すようにする
  def to_param
    type_string.present? ? type_string : id.to_s
  end
end

ポイントは三項演算子で条件分岐をしている部分です。

type_string.present? ? type_string : id.to_s

このように書くことで、type_stringが存在する場合にはその値を、存在しない場合には従来のidを使ったURLを生成することができます。これによって、新しい形式のURLと既存のid形式のURLの両方に対応が可能となります。

コントローラーの修正

従来はパラメーターでidが渡ってきていましたが、今回の変更により、URLの一部が文字列に変わるため、パラメーターの取得ロジックを修正する必要があります。このとき、文字列でパラメーターが渡ってくる場合に、それをidに変換する処理をbefore_actionで定義することで、既存のコントローラーのロジックを大きく変更せずに対応できます。

class FruitsController < ApplicationController

  # 追加
  before_action :set_params_fruit_id, only: [:show]

  # 既存のコード
  def show
    @fruit = Fruit.find_by(id: params[:fruit_id])
  end

  private

  # 追加
  def set_params_fruit_id
    return true if params[:fruit_id].to_i.to_s == params[:fruit_id]
    params[:fruit_id] = Sport.find_by(name: params[:fruit_id])&.id
  end
end

従来通り、パラメーターでidが渡ってきた場合はreturnで処理を終了し、type_stringの文字列が渡ってきた場合には、それをidに変換しています。

詰まった部分

ここまでの修正を行い、URLが変わるか試してみましたが、従来通りid付きのURLしか生成されず、そこで詰まってしまいました。特にエラーも表示されないため悩んでいましたが、URL生成部分に問題があることに気づきました。

<%= link_to "詳細", fruit_path(@fruit.id) %>

このように、link_toredirect_toの中で手動でidを指定してURLを生成している場合、to_paramは呼び出されず、to_paramが適用されるのは、Railsのパスヘルパー(例: fruit_path(@fruit))を使ってURLを生成する場面のようです。
そのため、以下のように_pathヘルパーを適切に使うように修正しました。

<%= link_to "詳細", fruit_path(@fruit) %>

終わりに

今回は、Railsアプリケーションでidを固有の文字列に置き換える実装の方法をまとめました。to_paramメソッドを活用することで、既存のid形式のURLを維持しつつ、新しいURL形式にも対応できるような実装が可能です。この記事がお役に立てば幸いです。

参考

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?