LoginSignup
63
63

More than 5 years have passed since last update.

Railsで、URLにIDでなく名前を入力して、アクセスする方法

Last updated at Posted at 2012-12-26

showやeditなど、member系のアクションに、数値のIDなどではなく、TwitterIDのような一意の文字列でアクセスする方法。

例えば、

http://your.app.com/users/400

でなく

http://your.app.com/users/bob-smith

でアクセスできるようにする。

単純にURLのかっこ良さが上がる気がするし、文字列でのアクセスのみ受け入れるようにしたら、サイトの持っている情報のスクレイピング対策にもなる。

例として、適用するモデル名をUser、urlに使用するカラム名をcanonical_nameとする。ここではidcanonical_nameのどちらでもアクセスできるようにする例を書く。

モデル側のコード

app/models/user.rb
class User < ActiveRecord::Base
  validates :canonical_name,
    uniqueness: { case_sensitive: false },
    format: { with: /^[A-Za-z][\w-]*$/ },
    length: { minimum: 3, maximum: 25 }

  def to_param
    canonical_name ? canonical_name : id.to_s
  end

  def self.find_by_canonical_name_or_id(arg)
    find_by_canonical_name(arg) || find(arg)
  end
end

to_paramというActiveRecordのメソッドが肝。これで通常の表示がidからcanonical_nameに切り替わる。
validationは大体こんな感じにすると良いと思う。ここでは大文字小文字が違うだけのcanonical_nameは許さないようにしているが、そもそも大文字を禁止するのもありだと思う。
なお、ここではcanonical_nameが設定されていないUserもいることを前提としている。

コントローラー側のコード

app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_filter :load_user, only: [:show, :edit, :update, :destroy]
  ## if you use cancan
  # load_and_authorize_resource :user, find_by: 'find_by_canonical_name_or_id'

  private
  def load_user
    @user = User.find_by_canonical_name_or_id(params[:id])
  end
end

数字でなくてもidの情報はparams[:id]に入って渡される。
canonical_nameでしかアクセスできないようにしたい時はload_userUser.find_by_canonical_nameを使えば良い。

別案

探すときに、find_by_canonical_name_or_idというのを使うとto_paramを変更しているクラスだけ、findでModelを探せなくなってしまう。これだと困る場合は、

app/models/user.rb
  def self.find(arg)
    find_by_canonical_name(arg) || super
  end

とfindを上書きしてしまえばいいかもしれない。

追記

https://gist.github.com/agnellvj/1209733 にもっといろんな方法が載っているのを発見。興味ある人は見てみるべし。

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