No route matches error - ruby-on-rails

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

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.

undefined method `posts_path' for #<#<Class:0x007fe3547d97d8>:0x007fe3546d58f0>

I'm new to rails and I'm getting this error:
undefined method `posts_path' for #<#<Class:0x007fe3547d97d8>:0x007fe3546d58f0>
I've posted my files below, please keep in mind I'm new to rails so simple explanations would be really appreciated!
Route.rb:
Rails.application.routes.draw do
get '/post' => 'post#index'
get '/post/new' => 'post#new'
post 'post' => 'post#create'
end
post_controller.rb:
class PostController < ApplicationController
def index
#post = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to '/post'
else
render 'new'
end
end
private
def post_params
params.require(:post).permit(:content).permit(:title)
end
end
new.html.erb:
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.label :post %><br>
<%= f.text_area :title %>
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit "Create" %>
</div>
<% end %>
I'm guessing form_for(#post) expects there to be a method called posts_path and one doesn't exist because it hasn't been defined in your routes file. Try replacing:
Rails.application.routes.draw do
get '/post' => 'post#index'
get '/post/new' => 'post#new'
post 'post' => 'post#create'
end
with
Rails.application.routes.draw do
resources :posts, only: [:new, :create, :index]
end
Edit: more info:
Read the full page on form helpers at http://guides.rubyonrails.org/form_helpers.html, and inparticular, read the section on "2.2 Binding a Form to an Object" and the part that says:
When dealing with RESTful resources, calls to form_for can get
significantly easier if you rely on record identification. In short,
you can just pass the model instance and have Rails figure out model
name and the rest:
## Creating a new article
# long-style:
form_for(#article, url: articles_path)
# same thing, short-style (record identification gets used):
form_for(#article)
## Editing an existing article
# long-style:
form_for(#article, url: article_path(#article), html: {method: "patch"})
# short-style:
form_for(#article)
Notice how the short-style form_for invocation is conveniently the
same, regardless of the record being new or existing. Record
identification is smart enough to figure out if the record is new by
asking record.new_record?. It also selects the correct path to submit
to and the name based on the class of the object.
So, knowingly or not, when you say form_for(#post), you're asking rails to guess the route that your form should be submitted to, based on the name of your #post variable. The routes that you had defined didn't match what rails expected them to be.
For more on routing in rails read the entire page at http://guides.rubyonrails.org/routing.html, and inparticular pay attention to the section "2 Resource Routing: the Rails Default". Your form_for(#post) will assume that you're using "resource routing", which is what I switched to.
As for why your getting a new error? There's somewhere else in your app where you were expecting to use your previous custom defined routes, and now you're using rails "resource routes" so your path names will be different. No route matches [GET] "/post/new" because now the route instead matches No route matches [GET] "/posts/new" (note the plural posts).
Here the form is try to find a route to a post_method through a path "posts_path"
So you need to define in your routes.rb file.
Rails.application.routes.draw do
get '/post' => 'post#index'
get '/post/new' => 'post#new'
post '/posts' => 'post#create'
end
The problem arises from the views. Rails cannot recognize the path that will run when the form is submitted.
You can manually change your form_for tag to point to the appropriate url.
<%= form_for #post, :url => "enter_your_path_here" do |f| %>
This solved my similar problem
you need to rename the post controller and the corresponding files to plural. that's posts not post. and then the route too needs to be resources :posts.
don't forget to change the class name of your post controller to be plural.

Using form_for with Nested Resources

I am building a To Do application in an attempt to get fluent with Rails. There are four levels of hierarchy in my app.
User
Goals (multiple goals per user)
Tasks (multiple tasks per goal)
Subtasks (multiple subtasks per task)
I have a working front end form for each of these that utilizes nested resources. My routes.rb has something like this
resources :goal do
resources :task do
resources :subtask
end
end
What I would like to do now is that have all these forms right in one of the views of the user controller.
This the form that I have attempted to create :
<%= form_for #task, url: {controller: 'task', action: 'create'} do |f| %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.submit "Add Goal", class: "btn" %>
<% end %>
But I end up getting this error
No route matches {:action=>"create", :controller=>"task", :id=>"1"}
The :id=>1 corresponds to the user page I am on (http://localhost:3000/user/1)
What I understand is that there is that nowhere have I provided the goal_id for which this step is intended. No idea how to implement this.
Another thing that I have noticed is that a response to rake routes shows a lot of URI paths but nothing for POST method. It does not allow me to use a path from there in the url: in form_for because it does not match the POST method.
So my questions are :
How to route a form_for that when you have nested resources?
How to provide the ID of the parent resource while using form_for so that my create action is correctly routed?
It is typically bad practice to nest routes beyond two levels deep. I would change your routes to:
resources :goal do
resources :task
end
and
resources :task do
resources :subtask
end
Now if you run "bundle exec rake routes" in the command line you will see all of the nested routes and their corresponding helpers. Your current issue lies with the form_for method. You need to add the resource its nested with which in this case should be:
<%= form_for [#goal,#task] do |f| %>
blah blah
<% end %>
Lastly, #goal is also still undefined so you'll need to define it in your 'new' action in the tasks controller. This is normally done by passing the id of the goal your task will be associated with via the params hash and the "link_to" used to get to the 'new' form. Then in the new action in your tasks controller:
#goal = Goal.find(params[:goal_id]) #The parameter can be named anything
#task = Task.new
Then in your 'create' action you should have the association made:
#task = Goal.tasks.new(task_params)
if #task.save
flash[:success] = "Woot"
redirect_to somewhere_awesome_path
else
whatever
end

Rails 4 action routes with simple_form and shallow nested resources

resources :users, shallow: true do
resources :shoes
end
This gives me two different routes for create and edit
user_shoes_path
shoes_path
In my shoes _form.html.erb if I leave the form tag :url as default I get a missing routes error when I submit a new or updated shoe.
If I supply the url in the form I can get it to work for either the new or the edit update, but I can't get it to work for both.
This works for the new:
<%= simple_form_for :shoe, url: user_shoes_path do |f| %>
This works for the edit, but will fail once it tries the actual update since it redirects to /:param_id:
<%= simple_form_for :shoe, url: shoes_path(#shoe) do |f| %>
How can I make it work for both? Thanks.
You should use
<% = simple_form_for [#user, #shoe] do |f| %>
and let do simple_form do the work...
This case, if there is a #user, simple form will use it (as for a new), if there isn't (like for an edit), simple form won't use it...

Problem with form_for Helper

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.

Resources