Rails 3:自定义Restful Routes:更改Edit-Action行为

时间:2012-02-24 17:40:44

标签: ruby-on-rails rest routing

对于我的项目,我需要有自定义网址,这不应该很容易猜到,因为它会增加对象的整数ID。为了解决这个问题,我为我的对象提供了一个unique_id属性,该属性是一个字符串,并编写了由resources :objects自己生成的七个动作,如下所示:

  get '/objects' => 'objects#index', as: :objects 
  post '/objects' => 'objects#create'
  get '/objects/new' => 'objects#new', as: :new_object
  get '/:unique_id/edit' => 'objects#edit', as: :edit_object
  get '/:unique_id' => 'objects#show', as: :object
  put '/:unique_id' => 'objects#update'
  delete '/:unique_id' => 'objects#destroy'

一切都很好,我只需告诉控制器通过Object.find_by_unique_id(params[:unique_id])而不是Object.find(params[:id])找到对象 我可以创建,阅读和删除完美,但我无法更新。

当我打开edit_object_path时,它会正确呈现表单,但是当我点击“更新对象”时,它就会搞砸了。 从WEBrick输出我可以看到它创建了一个PUT请求,但它请求对象的id而不是unique_id。例如,不是请求PUT /osefushe7398hr9,而是PUT /26。甚至没有调用update方法,而是要求创建一个unique_id为26的新对象。

我真的不知道在哪里更改该行为或如何传递unique_id而不是id。

3 个答案:

答案 0 :(得分:3)

Rails模型有一个您可能想要覆盖的方法来实现此目的,称为to_param方法。此方法的默认行为是返回模型实例的ID(我相信您正在尝试更改)。

根据您当前的布局,我会抛弃您所有的路线更改。在模型中,添加:

def to_param
  "#{unique_id.parameterize}"
end

现在,通过正常路由,/ objects /:变量的请求将按您的意愿运行。

使用参数化方法,您可以安全地不遇到不友好的URL。

覆盖to_param方法的一个小缺点是,现在在控制器中使用Model.find方法的其他操作(:edit,:update和:destroy)都需要更改为Model.find_by_unique_id [if你保持RESTful]。

答案 1 :(得分:1)

在表单中,您可以明确地告诉它要发布到哪个URL以及与其一起使用的参数。例如(使用HAML和form_tag)

= form_tag object_path(@object.unique_id), :method => :put do

您还可以更明确地使用:

= form_tag object_path(:id => @object.unique_id), :method => :put do

答案 2 :(得分:0)

好的解决方案是添加

def to_param
  unique_id
end

到没有参数化的对象模型或#{}语法。 我实际上发现事故是试图将unique_id传递给第二个解决方案中提到的表单。事实证明,我没有像解决方案二中建议的那样更改form_for标记。参数化是将unique_id设为小写的原因。

现在一切都按预期工作(并且仍然很安静)