In my tickets.js.coffee:
$.ajax '/comments/add',
type: 'POST',
dataType: 'html'
success: ( data ) ->
alert 'success'
<%= form_for #comment, :url => user_ticket_message_comments_path( #user, #ticket, m ), :html => { :class => "add-comment", :id => "add-comment-" + #ticket.id.to_s } do |f| %>
<%= f.label :body, "Add comment" %>
<%= f.text_area :body %>
<%= f.hidden_field :message_id, :value => m.id %>
<%= f.submit "Add comment" %>
<% end %>
Comments table:
id | message_id | body
----------------------
CommentsController:
def create
#comment = params[:comment]
#comment.save
end
My routes.rb:
resources :messages do
resources :comments
end
I get this error:
undefined method `save' for {"body"=>"awef", "message_id"=>"15"}:ActiveSupport::HashWithIndifferentAccess
Comment belongs to a Message and Message has many comments.
Where should I look to fix this error?
params[:comment] is a Hash, not a Comment object, and thus can't be "saved". You need to create a new Comment object and assign each attribute to it, then save the Comment object:
def create
#comment = Comment.new(params[:comment])
#comment.save
end
Depending on how "new" your app is, config.active_record.whitelist_attributes may be set to true, in which case the above will give you a security error and you should read the Rails Guides on Mass-Assignment for more information about how to properly assign attributes (you should actually read it either way).
Related
I am Rails newbie. I am creating a section that is pulling existing user's details and when the user click on edit, he can save the changes he has made. However, the changes aren't reflecting once the user saves it. Can you tell me what I am missing in here?
Here's the html/ruby form I am using:
<%= form_tag(html: {:id => 'user_profile_form'}, :url => patient_profile_path(#user), :method => :put) do %>
<%= text_field_tag(:inputFieldName, "#{#user.first_name} #{#user.last_name}", {:disabled => true}) %>
<%= submit_tag 'Save', :id=> 'saveButton' %>
<%= end %>
Here's the routes:
put :patient_profile, to: 'users#patient_profile'
post :dashboard, to: 'dashboard#index'
Here are the controller codes:
def patient_profile
if params[:user]
u = params[:user]
#user.first_name = u[:first_name] unless u[:first_name].nil? || u[:first_name].empty?
#user.last_name = u[:last_name] unless u[:last_name].nil? || u[:last_name].empty?
#user.save!
# index
render :index
end
end
It doesn't look like your form is actually updating anything since your form fields don't match your model. Try simplifying your form action:
View
<%= form_for(#user, html: {:id => 'user_profile_form'}, :url => patient_profile_path(#user), :method => :put) do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.submit "Update User" %>
<%= end %>
Controller:
def patient_profile
# TODO: Handle failed validation
#user.update_attributes!(params[:user])
# index
render :index
end
end
def user_params
params.require(:user).permit(:first_name, :last_name)
end
In my Rails app I'm trying to create a form for updating model instance attributes with new info and am running into trouble.
When I hit submit on the edit form, the following error is thrown:
param is missing or the value is empty: product
And here's the code snippet it provides:
# all the attributes that must be submitted for the product to be listed
def product_params
params.require(:product).permit(:name, :price, :description)
end
end
I think the problem is that the model :product isn't getting passed from the edit form to the update action. Here's the form:
<h1>Edit your listing</h1>
<%= form_for edit_item_path(#product), url: {action: "update"} do |f| %>
<div><%= f.label :name %><br />
<%= f.text_field :name, :placeholder => "Name yourself" %>
</div>
<div><%= f.label :price %><br />
<%= f.number_field :price, :placeholder => "Name your price" %>
</div><br />
<div><%= f.label :description %><br />
<%= f.text_area :description, :cols => "50", :rows => "10", :placeholder => "Write a few sentences about the item you're listing. Is it in good condition? Are there any accessories included?"%>
</div>
<br />
<%= f.submit "Update listing" %>
<% end %>
Here are the edit and update actions in my products_controller:
def edit
#product = Product.find(params[:id])
end
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(product_params)
format.html {render :action => "show"}
else
format.html {render :action => "edit"}
end
end
end
Finally, my product routes
get "/products/new(.:format)" => "products#new", :as => "list_item"
post "/products/create(.:format)" => "products#create"
get "/products(.:format)" => "products#index"
get "/products/:id(.:format)" => "products#show"
get "/products/:id/edit(.:format)" => "products#edit", :as => "edit_item"
post "/products/:id/update(.:format)" => "products#update"
So anyone know what the problem is? Am I not passing the right info to the update action? If I'm not, what do I need to do to do it?
form_for
The problem you have is you're using form_for without any object
form_for generates an appropriate form tag and yields a form builder
object that knows the model the form is about. Input fields are
created by calling methods defined on the form builder, which means
they are able to generate the appropriate names and default values
corresponding to the model attributes, as well as convenient IDs, et
form_for helpers are primarily designed to give you a way to manage ActiveRecord objects:
<%= form_for #object do |f| %>
...
<% end %>
--
Fix
Everything inside this form block will have to work with the object in the form_for. As you have only used a path helper in your form_for method, it's not going to work as you hope.
You'll need to do this:
<%= form_for #product, url: {action: "update"} do |f| %>
This will ensure your form_for populates the object correctly. The error you have basically says your strong_params method is expecting this structure:
params => {
"product" => {
"name" => ____,
"price" => _____,
"description" => ______
}
}
As you've not included the #product object in your form_for, your params hash won't have the product key, thus causing your error. The fix is to populate the form_for element correctly
Replace
form_for edit_item_path(#product), url: {action: "update"}
with
form_for #product
which is similar to
form_for #product, as: :product, url: product_path(#product), method: :patch do |f|
I am new to ruby, trying to follow the official documentation and create a basic form for creating a post:
<%= form_for #post, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :entry, :size => "60x12" %>
<%= f.submit "Create" %>
<% end %>
The form is successfully adding an entry to the database, but an empty one, I think I must be missing something in my controller? Do I need to pass the variables somehow?
def create
#post = Main.create
end
A basic create action can look like this. You first initialize a new post. Depending on if it successfully saves you proceed.
# app/controllers/posts_controller.rb
class PostsController < ActionController::Base
def create
#post = Post.new(params[:post])
if #post.save
redirect_to #post, notice: 'Post has been created.'
else
render :new
end
end
end
You can shorten your form.
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.text_area :entry, :size => "60x12" %>
<%= f.submit %>
<% end %>
You can see excellent example code along these lines when you generate a scaffold, so I would encourage you to try $ rails generate scaffold Post title body:text and learn by example.
Submitting a form passes the values entered into that form (along with some other information) to the controller as a hash called "params" - the params will contain a block labelled with the name of the form, in this case "post".
You need to use the post block from params in the creation of the new object.
def create
#post = Main.new(params[:post])
if #post.save
# handles a successful save
else
# handles validation failure
end
end
Try:
#post = Main.new(params[:post])
#post.save
I have a Project that belongs to User. In my user view I have a link to add a new project, with the parameter for the user I want to add the project to.
<%= link_to 'Add new project', :controller => "project", :action => "new", :id => #user %>
Url: /projects/new?id=62
Adding a project to a user works. The problem is when the validation fails while adding a new project and I do a render.
def create
#project = Project.new(params[:project])
if #project.save
redirect_to :action => "show", :id => #project.id
else
render :action => "new"
end
end
view:
<%= form_for #project do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :user_id , :value => params[:id] %>
<%= f.submit "Create project" %>
<% end %>
routes
resources :users do
resources :projects
end
How can I keep the parameter for the user after the render? Or is there some better way to do this? Been looking at a lot of similar questions but can't get it to work.
try
render :action => "new", :id => #project.id
if its not works for you, then try alternate way to pass the parameter to your render action.
This can also help you->
Rails 3 Render => New with Parameter
You shouldn't use params[:id] to assign value to this form field. Instead, add this to your #new action in controller:
def new
#project = Project.new(user_id: params[:id])
end
and then just write this in your form:
<%= f.hidden_field :user_id %>
Because #project was defined in your #new and #create actions and because it already contains a Project instance with a user_id assigned to it, the value would automatically be added to this field.
I've got a pickem object that has one result. I'm having an issue getting the result to save properly to the database.
pickems_controller.rb
def results
#pickem = Pickem.find params[:id]
# #pickem.result = #pickem.build_result if #pickem.result.blank?
#pickem.result = Result.new
end
def update_results
#pickem = Pickem.find params[:id]
#pickem.result = Result.new params[:pickem][:result_attributes]
if #pickem.result.update_attributes params[:pickem][:result_attributes]
redirect_to edit_pickem_results_path(#pickem), :notice => 'The results have been successfully updated.'
else
render "edit"
end
end
results.html.erb
<%= simple_form_for #pickem, :url => edit_pickem_results_path(#pickem), :method => :put, do |f| %>
<%= f.simple_fields_for :result do |r| %>
<%= r.input :first_name %>
...
<% end %>
<%= f.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
pickem.rb
has_one :result, :dependent => :destroy
accepts_nested_attributes_for :result
result.rb
belongs_to :pickem
I was initially using the build_result code that is commented out in the controller but had to back out of that. With build_result a result record was saved to the database the instant somebody clicked into the results form. There are rules in place in the application that don't allow users to make any picks if a result has been entered. So even if a user clicked into the result form but didn't submit, the result was still being created.
How can I build my form and save the result record only when the user clicks save, and not when the form is loaded? The current solution I've pasted above does not work. It saves a result record with the appropriate foreign key but never gets the form data. If I dump #pickem.result the correct form data is in the result object, I just can't get it to save right. Other solutions I've tried save the form data correctly but have a foreign key of 0.
EDIT:
For whatever reason #pickem.result = Result.new was still saving a record to the database so I changed it to #result = Result.new and updated the form as follows:
<%= simple_form_for #result, :url => edit_pickem_results_path(#pickem), :method => :put, do |r| %>
<%= r.input :first_name %>
<%= r.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
Then using the suggestion from Chuck W of #result = #pickem.result.build params[:result], I get undefined methodbuild' for nil:NilClass`.
pickems_controller.rb
def results
#pickem = Pickem.find params[:id]
#pickem.result.blank? ? #result = Result.new : #result = #pickem.result
end
def update_results
#pickem = Pickem.find params[:id]
#result = #pickem.result.build params[:pickem][:result]
if #result.save
redirect_to edit_pickem_results_path(#pickem), :notice => 'The results have been successfully updated.'
else
render "edit"
end
end
Then, your view should look something like this:
<%= simple_form_for #pickem, :url => edit_pickem_results_path(#pickem), :method => :put, do |f| %>
<%= f.simple_fields_for #result do |r| %>
<%= r.input :first_name %>
...
<% end %>
<%= f.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
You might have to play around with how the parameters are being passed back to the update_results action (I'm pretty new to rails), but I think you get the gist of it.