Ruby on Rails URL 格式

Posted

技术标签:

【中文标题】Ruby on Rails URL 格式【英文标题】:Ruby on Rails URL Format 【发布时间】:2012-11-07 10:27:16 【问题描述】:

我有一个 Ruby on Rails 应用程序,您可以在其中创建“帖子”。我首先使用脚手架生成器来生成标题,它是一个字符串,正文是内容。

每个'post'都有一个id的url,例如/1、/2、/3等

有没有办法将其更改为一串随机字符,例如 /49sl、/l9sl 等?

更新

这是我为 posts_controller.rb 准备的内容

class PostsController < ApplicationController
  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all

    respond_to do |format|
      format.html # index.html.erb
      format.json  render json: @posts 
    end
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
    @post = Post.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json  render json: @post 
    end
  end

  # GET /posts/new
  # GET /posts/new.json
  def new
    @post = Post.new

    respond_to do |format|
      format.html # new.html.erb
      format.json  render json: @post 
    end
  end

  # GET /posts/1/edit
  def edit
    @post = Post.find(params[:id])
  end

  # POST /posts
  # POST /posts.json
  def create
   @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        format.html  redirect_to @post, notice: 'Post was successfully created.' 
        format.json  render json: @post, status: :created, location: @post 
      else
        format.html  render action: "new" 
        format.json  render json: @post.errors, status: :unprocessable_entity 
      end
    end
  end

  # PUT /posts/1
  # PUT /posts/1.json
  def update
    @post = Post.find(params[:id])

    respond_to do |format|
      if @post.update_attributes(params[:post])
        format.html  redirect_to @post, notice: 'Post was successfully updated.' 
        format.json  head :no_content 
      else
        format.html  render action: "edit" 
        format.json  render json: @post.errors, status: :unprocessable_entity 
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post = Post.find(params[:id])
    @post.destroy

    respond_to do |format|
      format.html  redirect_to posts_url 
      format.json  head :no_content 
    end
  end
end

【问题讨论】:

【参考方案1】:

Rails 使用 ActiveRecord 对象的 to_param 方法将其解析为 URL。

假设您有办法生成这些唯一 ID(将其称为 IdGenerator),您可以执行以下操作:

1- 当你持久化一个 Post 对象并将其保存到数据库时生成这个 id,比如说在 url_id 列下

class Post < ActiveRecord::Base
  before_create :generate_url_id
  def generate_url_id
    self.url_id = IdGenerator.generate_id
  end
end

2- 在 Post 模型中覆盖 to_param 方法:

class Post < ActiveRecord::Base
  def to_param
    return url_id
  end
end

现在post_path(@post) 将解析为 /posts/url_id

顺便说一句,如果您还没有 ID 生成器,可以使用 SecureRandom.urlsafe_base64 或 look here。

阅读更多关于documentation for to_param的信息。

【讨论】:

我目前没有办法生成 id,你知道我该怎么做吗?另外,我已经用posts_controller.rb 中的内容更新了我的问题 你可以使用SecureRandom.urlsafe_base64 没有 gem 可以自动完成这一切吗?它应该存在。我遇到了错误。 为什么要使用宝石?自己实现并不难。 我尝试添加 ID 生成器,然后包含您给我的代码,但它不起作用。【参考方案2】:

希望这两个资源对你有所帮助:

    宝石,名为 obfuscate_id 。它以如下格式表示 ID:

    http://tennisfans.eu/products/4656446465

    另一个宝石 - masked_id 。它提供了类似的功能。您可以控制 url 创建的格式,在类中定义它。查看源代码,这个 gem 使用了 obfuscate_id gem 的策略。

【讨论】:

【参考方案3】:

您可以按照以下 3 个步骤为您的帖子提供随机 URL:

1- 在您的模型 (Post.rb) 中,在保存之前为每个帖子生成一个随机字符串。例如,

class Post < ActiveRecord::Base
  before_create :generate_url_id
  def generate_url_id
    self.url_id = SecureRandom.urlsafe_base64
  end
end

2- 在您的模型 (Post.rb) 中,提供 to_param method 以覆盖 Rails 默认 URL 生成。例如:

class Post < ActiveRecord::Base
  def to_param
    self.url_id
  end
end

3- 在您的控制器 (PostsController.rb) 中,使用动态查找器通过其随机字符串查找您的帖子。例如,

class PostsController < ApplicationController
  def show
    @post = Post.find_by_url_id(params[:id])
    ...
  end
end

我继续整理a complete example and posted it to Github。

【讨论】:

Github 上的例子帮助很大,谢谢!我们可以聊天吗?如果可以,我有几个问题。 谢谢。嗯,它似乎并没有让我创建一个聊天。【参考方案4】:

在 Erez 手动方式旁边,您可以使用 friendly_id gem,并使用唯一 id 作为您的 slug。

class Post < ActiveRecord::Base
  # FriendlyId
  friendly_id :uid

  # Set a unique user id on create
  before_save :set_uid, on: :create

  def set_uid
    self[uid] = rand(36**8).to_s(36)
  end
end

请注意这里设置的uid并不能保证唯一性。您当然需要添加某种验证,但整个主题与 google 不同。

【讨论】:

那会创建一个随机的字符串和数字吗? 是的,只需在 irb / rails 控制台中尝试一下。这是我所知道的最短的方法,我会努力寻找它的灵感来源。 rand(36**8).to_s(36) 中的 8 决定了随机字符串的长度。 没有找到帖子,而是here's a nice *** discussion on the topic Ruby 中的随机字符串。 当我将它添加到模型时出现此错误:路由错误 undefined method `friendly_id' for #<0x007f8bc94a4af0> 【参考方案5】:

Friendly_id 是一个很好的解决方案,如果你想使用 gem 的话。

关注此截屏视频:

http://railscasts.com/episodes/314-pretty-urls-with-friendlyid

(视频或 asciicast,随您的喜好)

Ryan Bates 的屏幕截图做得非常好。

【讨论】:

这显示友好的 URL,我正在寻找随机生成的 URL,例如/sfk23a9cdc6【参考方案6】:

如果您仍需要其他选项来生成 id,您可以尝试使用 UUID:

https://en.wikipedia.org/wiki/Universally_unique_identifier

还有一个可以轻松生成它们的红宝石:

https://github.com/assaf/uuid

但是,我会问:为什么要让它们随机呢?如果你想要做什么 是为了避免您的用户在 url 中键入另一个 id 并访问不属于他们的数据,那么您可能希望通过限定查找器来限制控制器中的访问,如下所示:

def show
    @post = current_user.posts.where(:id => params[:id]).first
    respond_to do |format|
       format.html # show.html.erb
       format.json  render json: @post 
    end
end

在这种情况下,current_user 是一个函数,它返回当前经过身份验证的用户(来自会话,或者您的应用程序逻辑规定的任何内容)。

【讨论】:

以上是关于Ruby on Rails URL 格式的主要内容,如果未能解决你的问题,请参考以下文章

Airbnb案例:Ruby on Rails YAML格式化字符串时导致的远程代码执行

从 ruby​​ on rails 重定向到 angular 给 preflight 的响应是无效错误

Elasticsearch 的_msearch介绍及在ruby on rails 中的使用

尝试使用to_json生成嵌套的json格式时,ruby on rails中的未定义方法错误?

有没有办法在 mp4 中使用 ruby​​ on rails / web / html5 录制音频

Ruby on Rails 如何获取当前 URL?