The action 'update' could not be found for InfosController - ruby-on-rails

So I have a site that I'm trying to make, in which you can enter a title and a price for a object called Info. When I enter in the title and price and press submit, the page that it gets redirected to says "The action 'update' could not be found for InfosController". I want it to flash a message notifying the user that the object was created successfully. Any Help??
controllers/infos_controller.rb
class InfosController < ApplicationController
def index
#info = Info.new
end
def create
#info = Info.new(params[:info])
if #info.save
flash[:notice] = 'Object created successfully, thank you'
render :index
else
flash[:notice] = 'Sorry! Object was not created successfully'
render :new
end
end
def update
#info = Info.find(params[:id])
if #info.update_attributes(params[:info])
# if update is successful
else
# if update is unsuccessful
end
redirect_to infos_path
end
end
views/infos/index.html.erb
<h1>Please enter information about an Info object</h1>
<%= form_for #info, url: {action: "create"} do |f| %>
<%= f.label :title %><br />
<%= f.text_field :title %> <br />
<%= f.label :price %><br />
<%= f.text_field :price %> <br />
<%= f.submit "Submit" %> <br />
<% end %>
models/info.rb
class Info < ActiveRecord::Base
attr_accessible :price, :title
end
New error
ActiveRecord::RecordNotFound in InfosController#update
Couldn't find Info with id=create
Rails.root: C:/Sites/2/information
Application Trace | Framework Trace | Full Trace
app/controllers/infos_controller.rb:18:in `update'
Request
Parameters:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"aXaLYDb5yhl2NXNriOf9gub2JcArrkUOdBogX4kcfKA=",
"info"=>{"title"=>"strawberries",
"price"=>".89"},
"commit"=>"Submit",
"id"=>"create"}
also, here is views\infos\create.html.erb
<h1>Infos#create</h1>
<p>Find me in app/views/infos/create.html.erb</p>
<h2><% if flash[:notice] %> <%= flash[:notice] %></h2>

If you've posted your InfosController in its entirety, you're missing the update action. Add it akin to as follows:
# app/controllers/infos_controller.rb
def update
#info = Info.find(params[:id])
if #info.update_attributes(params[:info])
# if update is successful
else
# if update is unsuccessful
end
redirect_to infos_path
end
UPDATE:
The likely reason why you're not hitting the create action is because your form is submitting to a path that matches the update path, rather than the create path.
First, if you have implemented RESTful routes for your infos resource (as you indicated you have), you shouldn't need to explicitly declare get "infos/create" as you have – the create route is implicitly created in your resourceful route declaration.
Then, if you indeed want a form_for helper to POST to your create action, try passing a hash to the url key in your form_for declaration:
<%= form_for #info, url: {action: "create"} do |f| %>
UPDATE 2:
The reason you are not hitting your update action is that the path you're posting your form to is /infos/create, when according to the canonical Rails guides, you should be posting to /infos. You can resolve this simply be removing the url argument in your form_for declaration:
<%= form_for #info do |f| %>
By default, Rails knows to route a form_for submission for a new object to the corresponding create action of the controller.
The reason why you're hitting the update action is that Rails takes the path you're currently submitting to, e.g. /infos/create, and routes to the update action with a params[:id] of create (rather than a numerical id). To properly invoke the update action, you should pass an existing Info object (for instance, Info.first) to your form_for helper. This will automatically route your submission to the update action:
# app/controllers/infos_controller.rb
def edit
#info = Info.find(params[:id]) # let's assume the id == 42
end
# app/views/infos/edit.html.erb
<%= form_for #info do |f| %>
Because you're passing an existing Info object, this form_for helper will automatically POST the request to the path /infos/42. Because the HTTP request method is POST, the request will automatically be routed to the update action, where params[:id] will equal 42 in the example above.
get "infos/create" should be dropped from routes.rb entirely, since the create route is already implicitly created in your resources :infos declaration.

Related

Rails create a model from form that isn't stored in a database

I have an account model that i want to create from the registration controller and form.
index.html.erb
<div id="registration">
<%= form_for(#account) do |f| %>
<% if #account.errors.any? %>
register_controller.rb
class RegisterController < ApplicationController
def index
#account = Account.new
end
def create
#account = Account.new(parames[:account])
end
end
end
end
routes.rb
Rails.application.routes.draw do
get 'register/index'
get 'register/create'
My current issue is undefined method `accounts_path' for #<#:0x007fd9f2fd8468> from the form_for() method
Am I mixing things up because of the names of the classes?
form_for(#account) will auto-set some of the attributes of the form, such as "action", which is where the form submits to. If you want to change this to something else then use the url option. You can pass this a path helper or just put the url in. eg
<!-- if you have a named path you can use the helper for it -->
<%= form_for #article, url: create_register_path %>
or
<!-- alternatively just pass the url -->
<%= form_for #article, url: "/register/create" %>
or
<!-- or you can pass the url as a hash if you prefer -->
<%= form_for #article, url: {controller: "register", action: "create"} %>
http://guides.rubyonrails.org/form_helpers.html
EDIT: I just noticed in your edit to your post that "register/create" is set as a get route. This means you will need to tell your form to use the get method as well: it defaults to post.
<%= form_for #article, url: "/register/create", :method => :get %>

Rails Form Action

I have a form like this in my html page
<%= form_for '/purchases', html: {class: "form form-horizontal validate-form", novalidate: "novalidate"} do |f| %>
But the form action is like this when i inspect the form
action = '/purchases/new'
I want the action to be just /purchases
and my controller method is like
#purchase = OrderItems.new
If you have your routes configured properly, you just need:
<%= form_for #purchase, html: {class: "form form-horizontal validate-form", novalidate: "novalidate"} do |f| %>
of course, provided you set #purchase in your new action:
#purchase = Purchase.new
I think you're getting confused between form_for and form_tag
--
form_for is for objects -
#app/controllers/purchases_controller.rb
Class PurchasesController < ApplicationController
def new
#purchase = Purchase.new
end
def create
#purchase = Purchase.new(purchase_params)
#purchase.save
end
private
def purchase_params
params.require(:purchase).permit(:purchase, :attributes)
end
end
The important thing to note with form_for is how it will build your form out of the ActiveRecord object you define. This is vitally important, and is at the root of your error:
<%= form_for #purchase do |f| %>
This will build all the different attributes of the form (including the action attribute), from the ActiveRecord object itself. This means if you populate your form_for with anything other than an object, you're going to get into trouble (as exhibited by your error)
--
form_tag is for data -
<%= form_tag your_path do %>
...
<% end %>
This might be better suited to your circumstances, as it allows you to create a "standalone" form - one which gives you the ability to send non-model-centric data to your application
We use form_tag implementations for the likes of search facilities etc
Solution
As Marek pointed out, you need to populate your form_for with an ActiveRecord object. To do this, you need first ensure you have initialized the object in your controller's new action, before passing the value to the form:
#app/controllers/purchases_controller.rb
Class PurchasesController < ActiveRecord::Base
def new
#purchase = Purchase.new
end
...
end
#app/views/purchases/new.html.erb
<%= form_for #purchase do |f| %>
I would just like to elaborate on the answers presented here. The way form_for works is it bases the form input names on the first argument passed to it. You can pass string or symbol as the first argument, and it should work, just like your example.
= form_for :purchase do |f|
= f.text_field :order
will result in a form that will submit to the current url and will contain 1 text field with the name purchase[order].
Marek's answer is correct however it doesn't answer your question. In cases where the object of the form, by convention, doesn't match the controller that will handle the request, you can pass a url option to form_for.
# controller
def new
#purchase = OrderItem.new
end
# view
= form_for #purchase, url: '/purchases' do |f|
= f.text_field :order
This will create a form with action set to /purchases but the name of the text field will be order_item[order].
FINAL NOTE
form_for is not exclusively used for active record objects as stated in the API docs

Rails update method for updating records not working

I have two methods in PersonsController- edit and update and a Person model:
def edit
#person=Person.find(params[:id])
end
def update
#person=Person.find(params[:id])
#person.update_attributes(params[:person])
end
and my edit.html.erb:
<h2> Edit info here!</h2>
<%= #person.name %>
<%= form_for #person, html: {mulitpart: true} do |f| %>
<p><%= f.text_field :location %></p>
<p><%= f.submit :submit , class: "btn btn-large btn-success" %></p>
<% end %>
and routes.rb:
resources :persons
But when I submit the form I get:
AbstractController::ActionNotFound
The action '5231d2491dba7fb057000004' could not be found for PersonsController
The 5231....... is id of a person.
Request Parameters:
{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"3TL7nn4UxhxFoxETeooBMThhkE0VdMoGFpjN9sx4srk=", "person"=>{"location"=>"nagpur"}, "commit"=>"submit", "controller"=>"persons", "action"=>"5231d2491dba7fb057000004"}
What is wrong here? I'm using mongoid and rails 3.2.13.
Your final comment reveals the source of error.
For either #edit or #update, you should not set the params manually in hidden field, which is also unnecessary.
If using conventional RESTful routes as resources :persons, you edit route will look like GET /persons/1/edit where 1 is the param id. You can get this person in #edit as
#person = Person.find(params[:id])
Similarly, you can get the person again in #update whose route is PUT persons/1
#person = Person.find(params[:id])
Then the question is answered.
But there is one more problem in your code, the part you get the attributes for updating. Because the params of person's attributes are sent via form, all attributes are under params[:person]. Thus, to get the photo attribute, you should use
params[:person][:photo] # Not params[:photo]

Form submit doesn't update database

I am trying to create lists and each has 2 attributes name and description.Database does create it and save it when using console but not using the website form.When checking the log file I found that website form does not post instead uses gets and is redirected to itself, How do I make the website form POST instead of GET so it gets stored in database.
Log file:
Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2013-09-18 12:35:14 -0400
Served asset /jquery_ujs.js - 304 Not Modified (0ms)
Here is list controller:
def create
#list = Lists.new(params[:lists])
if #list.save
redirect_to #list
else
render 'new'
end
end
def update
if #list.update_attributes(params[:lists])
flash[:success] = "lists updated"
redirect_to #list
else
render 'edit'
end
end
def new
#list = Lists.new
end
This is the form for users to create list
<%= form_for #list, url: newlist_path(#list), html: { method: :put } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
</br>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.submit "Create the List" %>
<% end %>
Your form_for helper is routing to the incorrect action. Try routing to the create action instead:
<%= form_for #list, url: {action: "create"} do |f| %>
I don't know if your controller's code excerpt you've pasted is complete, but you might missed to initialize list object for update. In your update action you have only
if #list.update_attributes(params[:lists])
but you are not initializing #list variable before. So you probably need something like
#list = Lists.find(params[:id])
You can also inspect your log file and verify what parameters are sent to controller.

Rails 3 View/Controller: Submit or Update changing parameters passed? ("New" works)

Something weird's happening with my Rails app. When I try to send an update command to one of my controllers, for some reason the submit button appears to be changing some of the params.
I'm using nested resources and setting up races which have participants. Pretty simple. For some reason, though, when I try to update a participant, it changes the value of :race_id to the participant's id (:id).
Though it only does that on update. I seem to be able to create new participants perfectly using the very same form, and so the very same submit button.
Here is some of the relevant code:
_form.rb (used by new and update)
<%= form_for ([:race, #participant]) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p><%= f.submit %></p>
<% end %>
participants_controller.rb
class ParticipantsController < ApplicationController
before_filter :authenticate_user!, :only => [:edit, :update, :destroy, :create, :new]
before_filter :set_up_race
...
def create
#participant = #race.participants.new(params[:participant])
if #participant.save
redirect_to setup_race_path(#race), :notice => "Successfully created participant."
else
render :action => 'new'
end
end
...
def update
#participant = Participant.find(params[:id])
if #participant.update_attributes(params[:participant])
redirect_to setup_race_path(#race), :notice => "Successfully updated participant."
else
render :action => 'edit'
end
end
...
def set_up_race
#race = Race.find(params[:race_id])
end
end
Here's why it seems that parameters are being changed:
If I modify the _form.rb file to include <%= params[:race_id] %>
The screen tells me 3
When I click submit I get:
Couldn't find Race with id=25
Request
Parameters:
{"utf8"=>"✓", "_method"=>"put",
"authenticity_token"=>"4VCZP9sI/iv8n454I8AE76n5vLiwGayuXc1NrPYfzGc=",
"participant"=>{"name"=>"hgdjhgf"}, "commit"=>"Update Participant",
"race_id"=>"25", "id"=>"25"}
(As you can see under parameters, "race_id"=>"25" after I click submit, but the page originally had :race_id =>"3" (proven above, and again if I do anything to make the form crash)).
So the question is, after all of that, why is :race_id changing somewhere between the view and the controller?
EDIT: here's a rake routes output, as per Jeff's request:
http://dylancodes.net/personal/ARTk/images/routes.png
What does the url look like that your form is posting to? Based on your routes, I would expect it to look something like /races/3/participants/25. From what I've read, the line
form_for ([:race, #participant]) do |f|
creates a namespaced route (search for "namespaced" on that page) that would look like /races/participants/25.
Does changing that line to this work for you?
form_for [#race, #particpant] do |f|
That should build the form url as /races/:race_id/participants/:id.

Resources