3

在此处的第一个答案之后,我正在尝试使用 base36 对 rails 应用程序的模型 ID 进行编码, 但我不确定我需要做什么。

我放在哪里id.to_s(36)?我需要在我的数据库中添加一列吗?

我想让我的网址domain.com/user/rD4g35tQ代替domain.com/user/3.

红宝石 1.9.3 轨道 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
4

2 回答 2

3

to_param 就是为了这个。路由使用它来生成路径。默认情况下,它返回一个对象的 id,但您可以在模型中将其覆盖为您想要的任何内容:

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
于 2014-01-03T03:51:08.930 回答
0

是的,我会在用户表中创建一个唯一列,例如“uuid”,以存储编码字符串并使用它查询用户。

在 config/routes.rb

resources :users

在 app/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

实际上,使用编码字符串而不是 id 的原因是出于安全考虑。我建议不要为此使用 base36 编码。您可以使用随机字符串并在创建用户时分配它,例如:

在 app/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并使用 Tim 的答案覆盖to_param.

于 2014-01-03T02:11:19.563 回答