Route a form to new controller action in Ruby on Rails

人走茶凉 提交于 2019-12-02 06:37:35

问题


I am relatively new to Ruby on Rails, and am trying to set up a form with a new action on an existing controller.

My existing model and controller is called 'projects', and I created a new action in the controller called 'queue'. The goal is that a user can filter projects by different users using '/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 %>

When I submit this form it submits as 'queue/queue', and in order to have a direct link to this action I need to do:

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

Which I know is not correct.

My question is how do I get the form to submit as 'queue/username'? Should this be in a new 'queue' controller to handle routing separately? Any help is appreciated.

Rails version 3.2.13

Ruby version 1.9.3


回答1:


The answers from Josh and Billy can accomplish this well, to throw another hat into the mix I would suggest making this a route based off of the projects. Assuming your routes are restful and contains projects as resources projects:

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

What this does is add the route projects/queue to your routes since it is based off of the collection instead of a member. See: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions for more info.

It is worth noting why this happens. It is because the the route you are originally posting to is only queue when what you want is queue/:id since the id is specified via a url parameter you should use a get request. But since it looks like you are posting the id via a post request this is a little confusing. Choosing just to use a post request you do not need the url parameter like Billy suggested and I also agree since this will allow you to keep it a but more succinct.

Hope this helps!

Edit For username usage

Changing your form to:

<%= 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 %>

Assuming the JS is working as it should, you just need to populate the hidden field with the :username value instead of :id. Then on the controller side of things:

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

Hope this makes sense!




回答2:


Two places to revise:

  1. Route. Better to use static route for POST without parameter, and specify POST

    match 'projects/queue' => 'projects#queue', via: :post
    
  2. Form tag. You need to specify the path

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

    Better not to use div id, if you have to, use it like this

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



回答3:


You can change your route to something like

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

And then have the destination be

projects_queue(current_user)


来源:https://stackoverflow.com/questions/16283706/route-a-form-to-new-controller-action-in-ruby-on-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!