Ruby on rails 如何隐藏url中的id(ruby on rails)

Ruby on rails 如何隐藏url中的id(ruby on rails),ruby-on-rails,url-shortener,Ruby On Rails,Url Shortener,我有一个用Ruby On Rails制作的web应用程序。现在,当我想显示一个对象时,我必须访问以下页面:使用1234对象id 我想对该对象id进行编码,并得到以下结果:(这只是一个示例) 怎样才能做到呢 非常感谢, Martin您可能可以使用Base64编码来实现这一点(尽管如果您真的试图对内部id保密,可能有人会猜测您使用的是Base64编码,并很容易确定id) 您的控制器需要看起来有点像这样 class ThingsController < ApplicationController

我有一个用Ruby On Rails制作的web应用程序。现在,当我想显示一个对象时,我必须访问以下页面:使用1234对象id

我想对该对象id进行编码,并得到以下结果:(这只是一个示例)

怎样才能做到呢

非常感谢,

Martin

您可能可以使用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_中的to_param方法来获取对象的id。我们可以在模型本身中覆盖它,这样编码id

class Thing < ActiveRecord::Base

  def to_param
    Base64.urlsafe_encode64 self.id.to_s
  end

end
class Thing

我在这里写的一切都是猜测。我以前没有这样做过,也没有测试过代码,所以我不能保证它是否会工作,或者它是否会带来不可预见的问题。我很想知道你是怎么做的。

你可以用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_中的to_param方法来获取对象的id。我们可以在模型本身中覆盖它,这样编码id

class Thing < ActiveRecord::Base

  def to_param
    Base64.urlsafe_encode64 self.id.to_s
  end

end
class Thing

我在这里写的一切都是猜测。我以前没有这样做过,也没有测试过代码,所以我不能保证它是否会工作,或者它是否会带来不可预见的问题。我很想知道你是怎么做的。

所有这些转换方法都是可逆的,所以如果你的对象有名字或标题或其他什么,那么最好的方法就是添加一个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可以是,因为在实际操作中,您可以通过此slug找到对象:

class MyObjectController

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

    ...

  end
end
不要忘记修改路由。rb:

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

所有这些转换方法都是可逆的,因此,如果您的对象有一些名称或标题,那么最好的方法就是添加一个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可以是,因为在实际操作中,您可以通过此slug找到对象:

class MyObjectController

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

    ...

  end
end
不要忘记修改路由。rb:

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

这会延长URL的长度!我猜你的意思是想用可逆编码方案以某种方式隐藏对象的id?@nurinur-最古老的问题真的应该被标记为最新问题的副本吗?那是胡说八道。我想是的,但显然我错了。对不起,这是我的第一面旗帜,我想另一个问题更丰富。我的错!这会延长URL的长度!我猜你的意思是想用可逆编码方案以某种方式隐藏对象的id?@nurinur-最古老的问题真的应该被标记为最新问题的副本吗?那是胡说八道。我想是的,但显然我错了。对不起,这是我的第一面旗帜,我想另一个问题更丰富。我的错!谢谢你,布拉德。在风景区有什么特别的事情要做吗?谢谢你,布拉德。这里有什么特别的事吗?谢谢!我将在几分钟内尝试并让您知道。您还可以通过覆盖模型的
:to_param
方法来返回slug值,从而继续使用资源丰富的路由。然后Rails将使用它而不是“ID”,但仍然会在
参数
散列中传递它ias
:ID
!我将在几分钟内尝试并让您知道。您还可以通过覆盖模型的
:to_param
方法来返回slug值,从而继续使用资源丰富的路由。然后Rails将使用它而不是“ID”,但仍会在
参数
散列中传递它ias
:ID
。您可以让Rails(实际上是ActiveSupport)为您实现字符串魔术:并且ruby本身支持重试逻辑,请参阅: