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>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中的未定义方法错误?