Кодировать идентификатор модели рельсов в URL с помощью base36

Я пытаюсь закодировать идентификатор модели для приложения rails, используя base36 после первого ответа, но я не уверен, что мне нужно делать.

Куда я положу id.to_s(36)? Нужно ли добавлять столбец в мою базу данных?

Я хотел бы, чтобы мои URL были domain.com/user/rD4g35tQ вместо domain.com/user/3,

Ruby 1.9.3 Rails 3.2.16

Вот мое шоу-действие в моем контроллере:

  def show
    @user = User.find(params[:id])
  end

Изменить: вот мое действие создать:

  def create
    @user = User.new(params[:user])
    if @user.save
      sign_in @user
      redirect_to @user
    else
      render 'new'
    end
  end

2 ответа

Решение

to_param для этого. Он используется маршрутизацией для генерации путей. По умолчанию он возвращает идентификатор объекта, но вы можете переопределить его в модели так, как вам будет угодно:

class User < ActiveRecord::Base

  def to_param
    id.to_s(36)
  end

end

В контроллерах params[:id] теперь будет той строкой, которую вы хотели, но вам нужно преобразовать обратно в реальный первичный ключ:

def show
  @user = User.find(params[:id].to_i(36))
end

Да, я бы создал уникальный столбец, например, 'uuid', в таблице пользователей, чтобы сохранить закодированную строку и запросить ее у пользователя.

в конфиге /ways.rb

resources :users

в приложении / controllers / users_controller.rb

def show
  @user = User.where(uuid: params[:uuid]).first
end

def create
  @user = User.new(params[:user])
  if @user.save
    sign_in @user
    redirect_to user_path(@user)
  else
    redirect_to new_user_path
  end
end

На самом деле причина использования закодированной строки вместо идентификатора связана с соображениями безопасности. Я предлагаю не использовать для этой цели кодировку base36. Вы можете использовать случайную строку и назначить ее при создании пользователя, например:

в приложении /models/user.rb

class User < ActiveRecord::Base

  attr_readonly :uuid

  before_validation :gen_uuid, on: :create

  validates :uuid, presence: true, uniqueness: true

  # ...

  def to_param
    self.uuid
  end

  private
  def gen_uuid
    self.uuid = RandomToken.genf(32)
  end
end

ОБНОВИТЬ:

Недостатком индивидуального маршрута является потеря _url а также _path помощники, лучший способ - сохранить оригинальные маршруты, созданные resources и использовать ответ Тима, чтобы переопределить to_param,

Другие вопросы по тегам