【问题标题】:Rails 3.0: error with routes when overriding to_param in modelRails 3.0:在模型中覆盖 to_param 时出现路由错误
【发布时间】:2011-02-11 22:11:40
【问题描述】:

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

这是错误:

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

这是我设置代码的方式。

models/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

config/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"}

【问题讨论】:

  • 请显示链接,这会导致此错误。您所有的代码都是正确的,因此您的链接中存在错误
  • 问题在于显示、编辑、更新和销毁路径。所以要么尝试导航到浏览器中的路径(/users/test@test.com,要么在视图中调用link_to,如, or

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


【解决方案1】:

问题是电子邮件添加了“。” (点)在 url 中,这会使 rails 感到困惑,因为它会尝试查找“com”格式(如果电子邮件以 .com 结尾)

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

文件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,所以这真的有助于我理解它是如何工作的 :)。

【讨论】:

  • 谢谢,奥古斯托!这篇博文帮助我更好地理解了 to_param 的情况。不过,我认为这里还有更多事情要做。在我的控制器中,我使用 find_by_email 从参数中查找用户,而不是 User.find。似乎只有在路由中使用电子邮件才有问题。我在用户模型中添加了一个“名称”字段只是为了对其进行测试,使用 :name 属性覆盖 to_param 可以正常工作,但电子邮件仍然失败,包括如果我按照您的建议添加 id。任何想法为什么电子邮件特别失败?
  • 我发现了问题。请重新检查答案
  • 啊,是的,我在错误输出中看到它显示将“.com”部分解析为此格式参数的参数。感谢您帮助解决这个问题!
【解决方案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

【讨论】:

    【解决方案3】:

    我在通过 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*')
    

    【讨论】:

      【解决方案4】:

      为避免通过 URL 传递 '.' (dot) 时出现问题,您可以在路由定义中添加:

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

      感谢:https://stackoverflow.com/a/8943634/333061

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-18
        • 1970-01-01
        相关资源
        最近更新 更多