【问题标题】:Route a form to new controller action in Ruby on Rails将表单路由到 Ruby on Rails 中的新控制器操作
【发布时间】:2013-04-29 16:31:03
【问题描述】:

我对 Ruby on Rails 比较陌生,正在尝试在现有控制器上设置一个带有新操作的表单。

我现有的模型和控制器称为“项目”,我在控制器中创建了一个名为“队列”的新操作。目标是用户可以使用“/queue/username”过滤不同用户的项目。

routes.rb

match 'queue/:username' => 'projects#queue'

projects_controller.rb

  def queue
    if (params[:user_id].blank? && params[:user_id].nil?)
      @projects = Project.find_all_by_user_id(User.where(:username => params[:username]).pluck(:id))
    else
      @projects = Project.find_all_by_user_id(params[:user_id])
    end
  end

queue.html.erb

<%= form_tag("queue", :id => "select_user", :method => "post") do %>
    <%= hidden_field_tag('user_id', '') %>
    <%= text_field_tag('user', nil, :placeholder => 'Enter a user...', class: "users",
                       data: {autocomplete_source: User.order(:lastname, :firstname).map { |u| {:label => u.firstname + " " + u.lastname, :id => u.id} }}) %>
<% end %>

当我提交此表单时,它会以“队列/队列”的形式提交,为了直接链接到此操作,我需要执行以下操作:

<%= link_to "Queue", queue_path + "/" + current_user.username.to_s %>

我知道这是不正确的。

我的问题是如何让表单作为“队列/用户名”提交?这应该在一个新的“队列”控制器中单独处理路由吗?任何帮助表示赞赏。

Rails 版本 3.2.13

Ruby 版本 1.9.3

【问题讨论】:

  • 你使用的是什么版本的 rails 和 ruby​​?
  • 更新了我的问题:Rails:3.2.13,Ruby:1.9.3。

标签: ruby-on-rails routing


【解决方案1】:

两处修改:

  1. 路线。不带参数的POST最好使用静态路由,并指定POST

    match 'projects/queue' => 'projects#queue', via: :post
    
  2. 表单标签。你需要指定路径

    <%= form_tag "projects/queue", method: :post do %>
    

    最好不要使用div id,如果必须这样使用它

    <%= form_tag "projects/queue", method: :post, html: {id: "select_user"} do %>
    

【讨论】:

  • 感谢您的回复。当我添加这些更改时,'projects_queue(current_user)' 给了我未定义的方法错误,'projects_queue_path(current_user)' 给了我'/projects/queue.1'。 1 是记录的 ID。有没有办法在链接和表单操作中将其更改为路由到“队列/用户名”而不是 id?
  • 我没有回答。顺便说一句,您为什么要拥有该动态ID?您的表单可以发布所有数据。
  • 我正在使用 jquery ui 自动完成,当他们选择一个选项时,我正在存储要提交的选择的用户 ID。如果有更好的方法来做到这一点,我愿意改变任何/全部。
  • 您可以在表单中有一个隐藏字段并使用 jQuery 来操作它的值。然后将发送此数据。
【解决方案2】:

Josh 和 Billy 的回答可以很好地完成这一点,我建议将其作为基于 projects 的路线。假设您的路线是宁静的,并且包含resources projects 的项目:

resources :projects do 
   post "queue", :on => :collection
end

这样做是将路由 projects/queue 添加到您的路由中,因为它基于集合而不是成员。请参阅:http://guides.rubyonrails.org/routing.html#adding-more-restful-actions 了解更多信息。

值得注意的是为什么会发生这种情况。这是因为您最初发布的路线只有queue,而您想要的是queue/:id,因为id是通过url参数指定的,您应该使用get请求。但是由于看起来您是通过发布请求发布 id,所以这有点令人困惑。选择只使用发布请求,您不需要像比利建议的 url 参数,我也同意,因为这将使您保持更简洁。

希望这会有所帮助!

编辑用户名使用

将表单更改为:

<%= form_tag("queue", :id => "select_user", :method => "post") do %>
    <%= hidden_field_tag(:username) %>
    <%= text_field_tag('user', nil, :placeholder => 'Enter a user...', class: "users",
                       data: {autocomplete_source: User.order(:lastname, :firstname).map { |u| {:label => u.firstname + " " + u.lastname, :username => u.username} }}) %>
<% end %>

假设 JS 正常工作,您只需使用 :username 值而不是 :id 填充隐藏字段。然后在控制器方面:

  def queue
    @projects = Project.find_all_by_username(params[:username])
  end

希望这是有道理的!

【讨论】:

  • 感谢所有有用的建议,杰森。使用这种方法我可以提交表单,但是传入的所有参数都是文本框的值,我仍然认为我需要隐藏字段来传递id。
  • @Drew 你是完全正确的,很抱歉我显然有一个严重的大脑放屁,出于某种原因,读起来好像你正在使用一个选择字段。我更新了答案以删除该部分,但之前的原则保持不变。因此,如果通过自动完成 JS 正确设置,您之前的表单应该可以正常工作。
  • 有道理,谢谢。我仍然想传入用户名而不是 id,但这是我将来必须尝试的。
  • @Drew 您可以提交用户名,如果您愿意将其限制为 user_id 的唯一原因是因为您在隐藏字段中使用了该用户名。就个人而言,我会这样保留它,因为它允许控制器端的查询更简单一些。我将对答案添加一个编辑,以允许将用户名传递给控制器​​。
  • 再次感谢您的帮助!
【解决方案3】:

您可以将路线更改为类似

match 'queue/:username' => 'projects#queue', :as => 'projects_queue'

然后有目的地是

projects_queue(current_user)

【讨论】:

  • @Drew 可能需要是 projects_queue_path(current_user)
  • 这在传递 'queue/id' 时有效,但不是用户名。
  • 等等,你在说它有效吗?一定要current_user.id吗?
  • 如果我传入projects_queue(current_user),就会传id。
猜你喜欢
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多