Problem with form_for Helper - ruby-on-rails

I have the following form_for declaration in a Rails site I am building:
form_for(form_question, :url => { :controller => "form_questions", :action => "edit", :id => form_question.id }) do |f|
but the site renders;
<form action="/form_questions/1/edit">
why is it putting the '/1/' before the "edit" in the action url?

Simple Answer. RESTful routes.
Basically you have defined resources :form_questions in config/routes.rb and that is transforming, automagically, your URL to make it RESTful.

I would recommend using the RESTful helpers provided to you, like:
<% form_for(#form_question) do %>
<%= f.text_field :question %>
...
<% end %>
Which will generate a URL to either create or update depending on if the #form_question response to new_record? is true or false respectively. It'll also do other things, like give the form tag a different id attribute based also off what new_record? returns.

Related

Rails Form_tag syntax error

I get an error when I run this code. I want to make a button that redirects to an action from pages_controller.
Submultimi.html.erb
<%= form_tag({:controller => '/pages_controller', :action => 'calculeaza'}, :method => "post") do %>
<%= text_field_tag :field1 %>
<%= submit_tag "Button" %>
<% end %>
pages_controller.rb
def Submultimi
end
def Combinari
end
def Permutari
end
def calculeaza
puts "YAY"
redirect_to '/combinari'
end
Error message: No route matches {:action=>"calculeaza", :controller=>"pages_controller"}
routes.rb
Rails.application.routes.draw do
get '/submultimi' => 'pages#Submultimi'
get '/combinari' => 'pages#Combinari'
get '/permutari' => 'pages#Permutari'
end
If you get an error you must include the error message in the question. Anyway the controller name is obviously wrong so this must be the problem. The controller should not include the "/" nor the "_controller".
<%= form_tag( { :controller => 'pages', :action => 'calculeaza' }, :method => "post") do %>
<%= text_field_tag :field1 %>
<%= submit_tag "Button" %>
<% end %>
Your routes are also wrong:
there's no calculeaza method in routes
methods should be lowercase in routes and controller
Thanks to Phlip for the correction about the controller name :)
As Pablo said, remove the / from your controller name.
Your error message says there is no route defined. That means you haven't correctly told rails what to do with your form's post request; it's trying a route that doesn't exist.
You've got a few things going wrong. Your action names are capitalized in routes.rb, but your method names (at least the one you've linked) is not. They're case sensitive, convention is all lowercase. Also, you don't have a route defined for calculeaza. You need one, in routes.rb add (something like, I haven't tested any of this):
post '/calculeaza/' to 'pages#calculeaza'
If you want to see your currently defined routes, run rails routes in a terminal, and to use it in code append _path to the prefix verb. You end up with something like:
form_tag calculeaza_path do
You may want to read the rails routing guide, especially the parts about resourceful routes.

No route matches error

I'm building a Rails app and am making a form with form_for. I keep getting the error that there are no route matches for what I've specified, but when I run rake routes, I see the route I'm specifying (or at least I think I do). Can anyone help out?
My form_for tag is:
<%=form_for #party, :url => { :action => "update", :controller=>"parties", :method=>"patch" } do |f| %>
And in my parties controller I have:
def update
#party.find(params[:id])
#party.update_attributes
if #party.save
redirect_to '/login'
end
end
Also, my routes for the party model are seen below:
If you leave out the options, rails will figure out if it is a create/update form. Otherwise you will need to have separate forms for create/update if you specify options.
<%= form_for #parties do |f| %>
...
<% end %>

Rails Routing and link_to

It's a little late here so maybe this a trivial question where I'm missing something simple. But when I click a button (with link_to) I created the following gets appended to my URL:
%23<ActionView::Helpers::FormBuilder:0x3ef1fd8>
Why is this, and how can I prevent this? Again, I apologize if this is a shallow question. I can post more information regarding routes and whatnot if that is needed.
Thanks!
Edit: More information as requested.
View:
<%= link_to "Index", welcome_path(f), :class => 'button' %>
with f being part of a form_for loop. I think I'm passing the wrong parameter but I'm unsure.
Relevant Route:
get "index" => 'welcome#show', :as => 'index'
Update:
Thanks for the help everyone. I ended up getting it working by pluralizing my controller (I don't know why I didn't have that before) and utilizing welcome_url instead. That seemed to do the trick.
Check out the very first example and paragraph in the Rails API docs for ActionView::Helpers::FormBuilder:
<%= form_for #person do |f| %>
Name: <%= f.text_field :name %>
Admin: <%= f.check_box :admin %>
<% end %>
What this is saying is that f represents an instantiated FormBuilder object that you are passing to the welcome_path method in your link_to helper.
Typically, you would not mix #index and #show in your routes. Depending on what you want to use the WelcomesController for, you might actually want to route your root_path to welcome_index:
get "welcome/show" => 'welcome#show', :as => 'welcome'
root 'welcome#index'
You should run: $ rake routes in the terminal to get an idea of path view helpers that you can use in your app.
Maybe you're trying to send users to a personalized welcome page. You could have something like this for your corresponding link_to helpers would look best like this:
<%= link_to "Show", welcome_path(#user.id), :class => 'button %>
<%= link_to "Index", root_path, :class => 'button' %>

Route a form to new controller action in Ruby on Rails

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
Two places to revise:
Route. Better to use static route for POST without parameter, and specify POST
match 'projects/queue' => 'projects#queue', via: :post
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 %>
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!
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)

How to set the action with form_for?

I created a new page on an existing controller.
I added 2 action methods on the controller: prompt_user and process_feedback.
So I get to the page via
redirect_to :controller => :users, :action => :prompt_user
And the form_for code looks like
<% form_for :user, #user do |f| %>
Which generates the following html
<form action="users/prompt_user" method="post">
Notice the action is prompt_user, where as I want to set it to process_feedback. I thought I could change the action with a button
<%= submit_tag "Process feedback" %>
But that didn't work.
So my question is how can I change the action to process_feedback?
Also, as you can probably tell, I'm very new to rails, so if I'm doing something especially obtuse, I'd love to find out what it is.
This is from memory, but I think you can do something like this:
form_for :user, #user, :url => { :action => :prompt_user } do |f|
Alternatively the same can be reached using form_tag with the syntax:
See my answer on this question: here https://stackoverflow.com/a/37145293/1248725

Resources