2

我有一个使用 Ruby On Rails 制作的网络应用程序。现在,当我想显示一个对象时,我必须访问以下页面: http: //mywebapp.com/object/1234和 1234 对象的 id。

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

如何做呢?

非常感谢,
马丁

4

2 回答 2

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

那么 URL 可以是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"
于 2011-09-23T11:20:29.487 回答
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

现在,实际上对您的 URL 进行编码会有点棘手 - 我会研究它,因为这似乎是一个有趣的问题(但我没有做出任何承诺)。

  • 编辑 -

一点阅读表明 ActionView 使用 url_for 中的 to_param 方法来获取对象的 id。我们可以在模型本身中覆盖它以像这样对 id 进行编码

class Thing < ActiveRecord::Base

  def to_param
    Base64.urlsafe_encode64 self.id.to_s
  end

end

我在这里写的一切都是推测性的。我之前没有这样做过,也没有测试过代码,所以我不能保证它是否会起作用,或者它是否会引入不可预见的问题。我很想听听你的情况。

于 2011-09-23T11:11:08.090 回答