Form submit doesn't update database - ruby-on-rails

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.

Related

How to get Rails form_for to point towards different controller

I have a form for creating new comments. This code exists in a page that is under a different controller (let's say it's app/views/posts/show.html.erb).
<%= form_for Comment.new do |f| %>
<%= f.label :content %>
<%= f.text_field :content %><br/>
<%= f.submit %>
<% end %>
The form works if I have Comment.new like above, but I want to use an instance variable like form_for #comment, similar to the first code snippet in this link: https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/FormHelper.html
In order to do so, I thought I need to define a new function like this and assign an empty comment. I tried putting this code in both the posts_controller and comments_controller.
def new
#comment = Comment.new
end
But when I replace Comment.new with #comment, I get this error: ActionView::Template::Error (First argument in form cannot contain nil or be empty):
This leads me to believe that neither of the new methods are being called. What am I doing wrong here?
My routes.rb looks like this:
Rails.application.routes.draw do
root to: 'posts#show'
resources :messages
end
if you are using show page (app/views/posts/show.html.erb) to display form
add this line in the show action of posts controller
# posts_controller
def show
#comment = Comment.new
end
and if you also want to submit your form other than the comment's create action mention the url in form_for tag
<%= form_for #comment, url: posts_path do |f| %>
<%= f.label :content %>
<%= f.text_field :content %><br/>
<%= f.submit %>
<% end %>

Pass a variable from view to controller from form submit

I am trying to access a variable sent through a submit form. However it does not appear to be present once the form is submitted.
see the hidden field on line: 2
<%= form_for #import, html: { multipart: true } do |f| %>
<%= f.hidden_field :tree_id, :value => #tree.id %>
<%= f.label :new_branch_data %>
<div class="help-text">Locate a file for import. (.xls, .xlsx file type)</div>
<%= f.file_field :attachment %>
<%= f.submit "Import", class: "btn btn-primary" %>
<% end %>
After hitting submit the action called in my controller:
def index
#tree = Tree.find(params[:tree_id])
...
...
end
Hangs up on #tree = Tree.find(params[:tree_id]) and returns a
"ActiveRecord::RecordNotFound"
at /imports
Couldn't find Tree without an ID
How can I correct this so that the #tree variable referenced in the form can be passed to the controller?
You can inspect the params that you're getting but I guess you have tree_id on params[:import] so ...
def index
#tree = Tree.find(params[:import][:tree_id])
...
...
end
I realized I wasn't calling the index action directly.
When looking at my controller I was actually calling the create action which was later redirecting to the index.
def create
#import = Import.new(import_params)
if #import.save
redirect_to imports_path, notice: "Data imported successfully."
else
render "new"
end
end
I changed the redirect to pass the param,
redirect_to imports_path(tree_id: params[:import][:tree_id]), notice: "Data imported successfully."
and then accessed the passed param in the index view by adding
#tree = Tree.find(params[:tree_id])
to the top of my index action.

Does rails automatically pass '#variables' into partial?

I have a simple setup:
class EventsController < ApplicationController
def edit
#user = User.find(params[:user_id])
#event = Event.find(params[:id])
end
end
events\edit.html.erb:
<h1>Edit <%= #user.name %>'s event</h1>
<%= render 'form' %>
events\_form.html.erb:
<%= form_for [#user, #event] do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.submit %>
<% end %>
To my biggest surprise this code is working and I am not getting any errors. Form partial knows about #user and #event!
I always thought I have to pass parameters as locals in order to access them in the partial, so the render from the view have to be:
<%= render 'form', user: #user, event: #event %>
And form_for line should be changed to:
<%= form_for [user, event] do |f| %>
Am I missing something here? Is it one of those days when I confused my self so much that I should probably get some sleep?
I am running this on Rails 4.1.4 and events are nested resources of user if that changes anything.
Your parameter is an instance variable. As such it is available to any partials rendered in the view.
You can check out more about rendering on the rails guides: http://guides.rubyonrails.org/getting_started.html#rendering-a-partial-form
It's good practice to pass in variables to partials as locals, as its easier to reuse the partial in other actions:
http://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables
Also if you try to access a local variable you didn't pass into the partial, your view with explode, while an instance variable will just be nil. Having the view explode is, in my opinion, easier to debug.

form_for route error [RoR]

I have a method called "createpost" in "topics_controller" which I am trying access from the show inside "topics_controller" but I keep getting a route error.
The Form:
<%= form_for #community_post, :url => { :action => "createpost", :controller=> "community_topics" } do |f| %>
<%= render 'error_messages' %>
<%= f.label :text %>
<%= f.text_area :text %>
<%= hidden_field_tag :community_topic_id, #community_topic.id %>
<br>
<%= f.submit "Submit reply" %>
The Controller Action:
def createpost
#community_post = CommunityPost.new(community_post_params)
#community_post.user_id = current_user.id
#community_post.community_topic_id = params[:community_topic_id]
if #community_post.save
redirect_to "/community_topics/#{#community_post.community_topic_id}", notice: 'Community post was successfully created.'
else
render action: 'new'
end
end
What am I doing wrong so I can correct it? Thanks a bunch.
You should have in your routes something like:
resources :comunity_topics do
post 'createpost', action: 'createpost'
end
and the form route should be something like:
createpost_comunity_topics_path
Either rename the method createpost in controller to create and remove the url option for form_for in view. Or define the route, if you really want use the createpost action like this:
resources :community_posts do
collection do
post :createpost
end
end
But I suspect that you are following some old tutorial from the times when Rails had routes that contained the name of controller and action to be executed. This approach was abandoned in favor of RESTful routes.
Read the current docs here:
http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

The action 'update' could not be found for InfosController

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.

Resources