1

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

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

有没有办法将其更改为生成一串随机字符和数字,例如 /49slc8sd、/l9scs8dl 等?

这是我所拥有的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

这就是我在post.rb模型中所拥有的

class Document < ActiveRecord::Base
  attr_accessible :content, :name
end
4

5 回答 5

1

如果您希望您的模型的主键 id 不以可预测的顺序排列,您可以借助http://codesnipers.com/?q=using-uuid-guid-之类的工具根据 uuid 或 guid 生成 id作为轨道中的主键

但是,如果您不想在路由中公开数据库标识符,您也可以基于唯一标识资源的任何其他属性进行路由,这是推荐的方法

person/:person_random_token, :controller => :persons, :action => :show #adding this in your route file directing to the controller where you can use params[:person_random_token] to uniquely identify your person object in Persons model

在控制器的操作中,您可以说

Person.find_by_random_token(params[:person_random_token]) #assuming random_token is your column name

获取 Person 对象

于 2012-11-23T20:20:44.057 回答
1

如果您想混淆数字 ID,可以查看这个有趣的讨论

于 2012-11-23T20:24:27.120 回答
1

您还应该了解 ActiveRecord::Base 对象的to_param方法。

基本上,Rails 在你的对象上调用这个方法来知道在 URL 和 params[:id] 中放入什么。默认情况下,它只是数据库中记录的主键。假设您这样覆盖它:

class Post < ActiveRecord::Base

  def to_param
    return id*100
  end

  def self.find_by_new_id(n)
    return self.find(n/100) # really you'd want to handle strings and integers
  end
end

数据库中的第一条记录将具有 url /posts/100

在您的控制器中,检索您刚刚执行的对象

@post = Post.find_by_new_id(params[:id])

(当然,您也可以覆盖默认find方法,但这可能会令人不悦。)基本上,该to_param方法会转换您的 id,而新的 finder 会撤消它。通常,您只需指向另一个在创建记录时已通过挂钩自动填充的数据库列。这就是 Qumara otBurgas 发布的链接中描述的内容。

于 2012-11-24T08:46:45.403 回答
0

不清楚你在这里问什么。路由中指定的操作的路径不需要传递的 id 为某种格式。如果您愿意,您可以传递非数字 id,并在您的操作中使用您喜欢的 id。也许如果您提供有关路线和操作的更多信息,我们可以理解您的要求。

于 2012-11-23T19:59:44.933 回答
0

多种方法可以在 Ruby 中生成随机字符串。

现在,到你问题的第二部分。如果你想使用类似的路由来访问你的帖子/post/rndm5tr,你可以简单地在你的控制器中更改这行代码:

@post = Post.find(params[:id])

@post = Post.find_by_randomness(params[:id])

现在,只需创建一个迁移:rails g migration AddRandomnessToPost randomness:string并运行rake db:migrate(或bundle exec rake db:migrate,取决于它的设置方式)。

当然,您可以随意命名该字段,randomness这只是我使用的随机名称。我认为常见的约定是称它们为蛞蝓或令牌,但我可能错了。

现在,在您的模型中添加一个方法以before_create生成随机字符串并将其添加到即将保存的Post对象中(使用上述链接中的示例之一)。检查您正在生成的字符串是否已经被使用是明智的(如果帖子已经具有随机标记,您可以编写一个递归方法再次调用自身)。

于 2012-11-24T02:17:31.697 回答