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.
Related
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.
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 %>
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
I'm pretty new to rails so sorry if this is poorly worded... for a course, I'm creating an app that lets you add (post) new instances of classes called Planets and Moons. Moon is supposed to be a child of Planet. Right now I can create both in separate database tables, using three route requests:
get "planets" => "planets#index"
get "planets/new" => "planets#new"
post "/planets" => "planets#create"
(This create a form page to register new planets. Substitute "moons" and the moon class works the same, including create, from it's own form page.)
I have a fourth route for a planets show-by-id page
get "planets/:id" => "planets#show"
On this planets id show page, I want to create an "Add a moon" form that takes the param ID for the planet, lets the user enter a moon name, and sends the post request to create the new instance.
I don't think I know enough about forms and routing.
My form for the new moons is
<%= form_for #moon, url: "/planets/:id" do |f| %>
<p><strong>New Moon Name:</strong></p>
<p>Name: <%= f.text_field :name %></p>
<% Planet.find(params[:id]: :planet_id %>
<p><%= f.submit "Create!" %></p>
<% end %>
The three "moon" routes I have:
1) get "moons" => "moons#index"
2) get "moons/new" => "moons#new" (goes to a form I was using to test, I don't know if I need this)
3) post "/planets/:id" => "moons#create" (where I think the problem is)
I think I may need to use interpolation to get the planet ID from the params into the moon posting form so help there is great, but I'm more concerned with getting past the line:
<%= form_for #moon, url: "/planets/:id" do |f| %>
I get error: "First argument in form cannot contain nil or be empty"
This is what I have defined in the moons controller...
def new
#moon = Moon.new
end
def create
moon_attributes = params[:moon]
Moon.create({
name: moon_attributes[:name],
planet_id: moon_attributes[:planet_id]
})
end
I hope this question makes sense. Thanks in advance!
To give you some perspective, here's what you need to do:
#config/routes.rb
resources :planets, only: [:index, :new, :create, :show] do
resources :moons, only: [:create] #-> planets/:id/moons
end
This uses the resourceful routing structure in Rails, giving you the paths you have already anyway.
In terms of your form, you'd be best doing this:
#app/views/planets/show.html.erb
<%= form_for #moon do |f| #-> should route to moons_controller#create %>
<p><strong>New Moon Name:</strong></p>
<p>Name: <%= f.text_field :name %></p>
<p><%= f.submit "Create!" %></p>
<% end %>
#app/controllers/moons_controller.rb
class MoonsController < ActiveRecord::Base
def create
moon = Moon.new(moon_params)
moon.save
redirect_to planets_show_path(planet)
end
private
def moon_params
params.require(:moon).permit(:name).merge(planet_id: params[:planet_id])
end
end
So a user has many colleges (that they have attended), and a college belongs to a user. I call these colleges, college_profile as they are the college attribute of a user's profile.
I am running into the problem when trying to generate a new college. My controller for the college at the moment is very simple:
def new
#user = User.find(params[:id])
#college = current_user.college_profile.build if signed_in?
end
And the view equally as simple: (views/college_profiles/new.html.erb)
<%= form_for [#user, #college] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<% end %>
And yet, for some reason I get the following error:
NoMethodError in College_profiles#new
Showing .../app/views/college_profiles/new.html.erb where line #4 raised:
undefined method `user_college_profiles_path' for #<#<Class:0x5bf1b68>:0x673aef8>
As I am still learning Rails, I really don't even understand what this error is exactly referring to. A fair amount of Google-ing has given me no luck, or if the answer is out there I simply don't know enough to realize I was looking at it. Any help would be greatly appreciated!
If it is relevant, seeing as we're talking about paths, here's an excerpt from my routes file:
resources :users, :only => [:index, :new, :create, :destroy, :update, :edit] do
resources :college_profiles, :only => [:new, :create]
end
If any more info is needed, just let me know. Thanks!
The thing about form_for is that its URL is based on the model that you passed in. In your case, it's:
<%= form_for [#user, #college] do |f| %>
Rails automatically looks for user_college_profiles_path because you assigned User to #user, and current_user.college_profile to #college.
Fortunately, Rails provides a way to override the default URL the form will go to on submit:
<%= form_for([#user, #college], :url => your_custom_route_path) do |f| %>
All you need to do is create your_custom_route in your routes.rb
Source: Ruby on Rails Guides: Rails Form Helpers
Rails is trying to create a path that will be used to post data from the form to your controller. The action that it's looking for is create, but you only have new defined in your routes. If your controller is called CollegeProfiles, then you will need to change your nested route to:
resources :college_profiles, :only => [:new, :create]