https://github.com/norman/friendly_id
一般用来隐藏真实的主键 id, 比如 把 http://www.example.com/users/123 变成 http://www.example.com/users/joe-schmoe
用来防止按 ID 采集,或者暴露真实用户或商品销售数目等
部署完一切看上去都很完美,但我今天试着用 http://www.example.com/users/123 访问一下,结果发现完全可用!!!
请问如何禁用用户用 123 作参数访问,只能通过 http://www.example.com/users/joe-schmoe 来访问呢?
谢谢
可以不用这个 friendly_id gem
然后 routes.rb 里面删掉默认的 users#show,添加一个 get 'user/:username' => 'users#show'
class UsersController < ApplicationController
def show
@user = User.where('lower(username) = lower(?)', params[:username]).first
end
end
原来还有 gem,原来还有很多东西要考虑,我就是直接在 controller 里写
@studio = Studio.find_by(domain: params[:studio_domain])
是不是图音图森破了?
create_table :users, id: false do |t|
.....
class User < ActiveRecord::Base
self.primary_key = :username
.....
@user = User.find(params[:id])
return render_404 if @user.id.to_s == params[:id]
#2 楼 @libuchao #3 楼 @chairy11 谢谢,这是个办法,但改动太大,用 friendly_id 可以不改任何原来的代码
#4 楼 @mimosa 这有更详细的说明: http://ruby-journal.com/how-to-override-default-primary-key-id-in-rails/ 不但改动大,而且处理 association 的时候会有问题
#5 楼 @xmonkeycn 谢谢,你一句话点醒梦中人,你的办法真是太太太棒了!!! 建议给 friendly_id 的 README.rdoc 发 pull request,他们根本没有说明这个问题,难道用这个 Gem 的人只是考虑漂亮和 SEO,没有考虑过隐藏主键的事?
定义一个方法不就好了。
def find_by_friendly_id(id)
first_name, last_name = id.split('-')
find_by! first_name: first_name, last_name: last_name
end
谢谢,我不是真的找用户,是“比如”。
定义方法太复杂了,还要改 view 和 route,如果用 friendly_id,所有原来的代码都不用改,而且可以自动自成漂亮的 Url。
#5 楼 的方法已经足够好了。
Rails 里面正确用法应该用 to_param
http://api.rubyonrails.org/classes/ActiveRecord/Integration.html#method-i-to_param
#9 楼 @rei 你一直是论坛正能量,也愿意花时间帮助大家,先给你点个赞。
一般情况下不要改 view 和 route,Product.find(params[:id])
和 edit_product_url(@product)
之类的都不用改,我 #8 楼 说错了。
基于我对你的了解,你可能不太喜欢依赖过多的 Gem,但在这个问题上,用 to_param
和 定义一个方法不太适合我的情况,我的情况会更复杂。主帖的 user 只是一个例子而已。
比如说现在做一个产品的 CRUD,把产品名称而不是产品 id 放在 url,url 中可能还有除 id 之外的其它参数,产品名称可能涉及英文和字母外的特殊字符,有可能还会重名,可能还会因为 SEO 的原因改名 (要考虑改名后会有坏链),这时写一个复杂的 to_param
已经不能解决问题,应该添加一个 unique 的 slug
字段存储转换后的产品名称以及“历史名称” ,如果重名还要做一些处理。更麻烦的是不只是产品要这样处理,比如 用户,产地,厂商等 controller 都要这样处理。
如果只是 to_param
这个链接对此方法有更多说明:
https://gist.github.com/cdmwebs/1209732
文章最后也推荐用 friendly_id
gem,因为“历史名称”不是一两句话就可以搞定。
PS: 关于中文等特殊字符处理: http://waynechu.logdown.com/posts/205700-rails-web-site-no-longer-displays-only-id
如果只要通过用 friendly id 来查找,用
User.find_by_friendly_id(params[:id])
不要用
User.friendly.find(params[:id])
#15 楼 @quakewang
谢谢!想问一下,你是怎么找到这个方法的,我 find_by_friendly_id
只搜索到这个页面:
http://www.rubydoc.info/github/norman/friendly_id/FriendlyId/FinderMethods:find_by_friendly_id