Rails 3.0:在模型中覆盖to_param时路由错误

时间:2011-02-11 22:11:41

标签: ruby-on-rails ruby-on-rails-3 routing

当我尝试在我的用户模型中覆盖to_param以使用电子邮件地址作为ID时,我的路由出错了。它似乎试图在尝试匹配路由时匹配id的整个对象。任何人都可以帮我弄清楚我错过了什么吗?

这是错误:

No route matches {:controller=>"users", :action=>"show", :id=>#<User id: 1, email: ....>}

以下是我如何设置代码。

模型/ user.rb:

attr_accessible :email    

def to_param 
  email
end

控制器/ users_controller.rb:

before_filter :get_user, :only=>[:show,:update,:edit,:destroy]

...

def get_user
  @user = User.find_by_email params[:id]
end

配置/ routes.rb中

resources :users

这是rake路线的输出:

     user GET    /users(.:format)          {:controller=>"users", :action=>"index"}
          POST   /users(.:format)          {:controller=>"users", :action=>"create"}
 new_user GET    /users/new(.:format)      {:controller=>"users", :action=>"new"}
edit_user GET    /users/:id/edit(.:format) {:controller=>"users", :action=>"edit"}
     user GET    /users/:id(.:format)      {:controller=>"users", :action=>"show"}
          PUT    /users/:id(.:format)      {:controller=>"users", :action=>"update"}
          DELETE /users/:id(.:format)      {:controller=>"users", :action=>"destroy"}

4 个答案:

答案 0 :(得分:5)

问题是电子邮件添加了'。' (点)在网址中,这会混淆rails,因为它试图找到“com”格式(如果电子邮件以.com结尾)

我已将此代码添加到我的某个应用程序(我有人而不是用户)并且它正常工作,所以诀窍是用其他东西替换点。我选择将其替换为“@”,因为其他符号(如 - 或+)在电子邮件地址中有效。

档案 person.rb

def to_param
  email.sub ".", "@"
end

def self.param_to_email(param) 
  segments = param.split '@'
  host = segments[1..-1].join('.')
  segments[0] + '@' + host
end

文件 people_controller.rb

def get_person
  email = Person.param_to_email params[:id]
  @person = Person.find_by_email email
end

http://jroller.com/obie/entry/seo_optimization_of_urls_in中有更多关于其工作原理的提示。

感谢您提出这个问题,我刚开始使用rails,所以这真的帮助我了解它是如何工作的:)。

答案 1 :(得分:2)

你可以加点'。'如果为路径中的“id”参数指定自定义正则表达式,则在to_param返回值中,例如:

match '/images/:id',
  :via => :get,
  :constraints => { :id => /[^\/]+/ },
  :format => false,
  :to => 'images#show',
  :as => :image

有关详细信息,请参阅http://edgeguides.rubyonrails.org/routing.html#specifying-constraints

答案 2 :(得分:0)

我在通过GET发送电子邮件地址时遇到了问题。

#this url will cause the following problem
/resend-validation/abcd@abcd.com 
params[:email] = abcd@abcd

# I had to encode the email:
<%= link_to('Resend Code', resend_activation_path(:email => user.email.unpack('H*'))) %>

# than decode it in controller:
email = params[:email].split.pack('H*')

答案 3 :(得分:0)

为了避免通过URL传递'.' (dot)的问题,您可以在路线定义中添加:

resources :users, :id => /.*/

信用到:https://stackoverflow.com/a/8943634/333061