6

我有一个 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
4

6 回答 6

15

Rails 使用to_paramActiveRecord 对象的方法将其解析为 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查看这里。

阅读有关to_param 文档的更多信息。

于 2012-11-19T13:38:05.847 回答
2

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

  1. 名为obfuscate_id的 gem 。它以如下格式表示 ID:

    http://tennisfans.eu/products/4656446465

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

于 2012-11-28T23:03:27.473 回答
0

在 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的设置并不能保证唯一性。您当然需要添加某种验证,但整个主题与谷歌不同。

于 2012-11-19T13:42:14.647 回答
0

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

关注此截屏视频:

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

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

Ryan Bates 的截屏视频做得非常好。

于 2012-12-03T06:00:22.420 回答
0

如果您仍然想要另一个选项来生成 id,您可以尝试使用 UUID:

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

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

https://github.com/assaf/uuid

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

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 是一个函数,它返回当前经过身份验证的用户(来自会话,或者您的应用程序逻辑规定的任何内容)。

于 2012-12-04T04:55:43.317 回答
0

您可以按照以下 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 方法来覆盖 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

我继续整理了一个完整的示例并将其发布到 Github

于 2012-12-06T18:37:05.917 回答