如何模糊网址中的id(ruby on rails)

时间:2011-09-23 10:44:41

标签: ruby-on-rails url-shortener

我有一个使用Ruby On Rails创建的Web应用程序。现在,当我想显示一个对象时,我必须访问以下页面:http://mywebapp.com/object/1234,其中1234是对象的id。

我想对该对象id进行编码并得到以下结果:http://mywebapp.com/object/5k(这只是一个例子)。

怎么做?

非常感谢,
马丁

2 个答案:

答案 0 :(得分:5)

所有这些转换方法都是可逆的,所以恕我直言,如果你的对象有一些名称或标题或其他什么,那么最好的方法是添加一个slug。 在这种情况下,向对象添加一个新属性:slug,让它自动从模型上的对象名称(或其他东西)生成它的值:

class MyObject

  validates_format_of :slug, :with => /\A[a-z\-0-9]*\Z/
  before_validation :generate_slug, :on => :create    

  def generate_slug
    if self.slug.blank?
      slug = self.name.mb_chars.downcase.normalize(:kd).to_s.gsub(/-/, " ").squeeze(" ")
      slug = slug.gsub(/\s/, "-").gsub(/[^a-z\-0-9]/, "")

      current = 1
      self.slug = slug
      while true
        conflicts = MyObject.where("slug = ?", self.slug).count
        if conflicts != 0
          self.slug = "#{slug}-#{current}"
          current += 1
        else
          break
        end
      end
    end
  end
end

然后网址可以是http://mywebapp.com/object/my_object_slug,因为在行动中你可以通过这个slug找到对象:

class MyObjectController

  def some_action
    my_object = MyObject.find_by_slug(params[:slug])

    ...

  end
end

不要忘记修改routes.rb:

match "object/:slug", :to => "my_objects#some_action"

答案 1 :(得分:1)

您可以使用Base64编码执行此操作(尽管如果您真的想保持内部ID秘密,有人可能会猜测您正在使用Base64编码并轻松确定ID。)

您的控制器需要看起来有点像这样

class ThingsController < ApplicationController
  require 'base64'

  def show
    @thing = Thing.find Base64.urlsafe_decode64(params[:id])
  end

  def edit
    @thing = Thing.find Base64.urlsafe_decode64(params[:id])
  end

  #These are just a couple of very simple example actions

end

现在实际编码你的网址会变得有点棘手 - 我会调查它,因为它似乎是一个有趣的问题(但我没有做出任何承诺)。

  • 编辑 -

一些阅读揭示了ActionView使用url_for中的to_param方法来获取对象的id。我们可以在模型本身中覆盖它,以便像这样编码id

class Thing < ActiveRecord::Base

  def to_param
    Base64.urlsafe_encode64 self.id.to_s
  end

end

我在这里写的所有东西都是猜测的。我之前没有这样做或测试过代码,所以我不能保证它是否会起作用或是否会引入无法预料的问题。我很想知道你怎么走。