In my app I have User, Post and Comment models.
When a User wants to comment on Post the new action from the Comments controller takes over. The Post (to be commented on) is shown and the User enters his Comment.
However, when the User submits, I want to pass the Post.id and the Comments.content to the create action. How do I do that?
Here is the comments/new.html.erb
<%= form_for #comment do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit "Done" %>
</div>
<% end %>
Thanks to all of you. I did the nested routing and my new.html.erb now has
<%= form_for [#post,#comment] do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<% f.hidden_field :post %>
<div class="field">
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit "Done" %>
</div>
<% end %>
However I get: undefined method `comment' and I cant figure that bugger out.
My guess is that each Comment must belong to a Post If that's the case then this seems like the perfect candidate for nested routes. http://guides.rubyonrails.org/routing.html#nested-resources
resources :posts do
resources :comments
end
So in your case both the post id and the comment id would be part of the URL:
# Will submit to a URL like /posts/1/comments
# or /posts/1/comments/1
<%= form_for [#post,#comment] do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit "Done" %>
</div>
<% end %>
You would need to handle the post_id in your comments controller actions.
First of all you have to pass Post.id to the comments new action. Something like
link_to "Add comment", new_comment_path( params[ :id ] )
I assume that you're following conventions so params[ :id ] is Post.id. Later in your Comment#create instantiate new comment with
#comment = Comment.new( :post_id => params[ :id ] )
which will create comment related to the post. Finally form for new comment
<%= form_for #comment do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= f.hidden_field :post_id %>
<div class="field">
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit "Done" %>
</div>
<% end %>
In the view (using HAML)
=form_for( #comment, :as => :comment) do |f|
=f.hidden_field :post_id
=f.hidden_field :user_id
=f.text_area :comment
=f.submit "Submit"
and in the Comment#new controller:
#comment = Comment.new(:user_id => #user.id, :post_id => #post.id)
Related
I am trying to save parent as well as child object at the same time using accepts_nested_attributes_for
Code in controller's new method:
def new
#project = Project.new
#project.instances.build
end
and form looks like this:
<%= simple_form_for(#project) do |f| %>
<%= f.input :name %>
<%= link_to "Add New Instance", new_project_instance_path(#project), id: "new_link", remote: true %>
<% end %>
The route entry for this is:
resources :projects do
resources :instances
end
And the fields that need to be displayed instances/_form.html.erb:
<%= form.simple_fields_for :instances do |i| %>
<%= i.input :user_id %>
<%= i.input :password %>
<%= i.input :service_url %>
<% end %>
The issue here project_id being :nil, it is giving error:
No route matches {:action=>"new", :controller=>"instances", :project_id=>nil} missing required keys: [:project_id]
I need to somehow call <%= render 'cdd_instances/form', form: f %>, so that the fields get rendered below the Project details, how should I implement this?
I think your #project is null you have to pass like:
new_project_instance_path(project_id: (#project || ''))
In this case you are not able to pass non-persisted #project to create this link_to url.
I believe you are looking for something like: cocoon.
<%= simple_form_for #project do |f| %>
<%= f.input :name %>
<h3>Instances</h3>
<div id="instances">
<%= f.simple_fields_for :instances do |instance| %>
<%= render 'instance_fields', f: instance %>
<% end %>
<div class="links">
<%= link_to_add_association 'add instance', f, :instances %>
</div>
</div>
<%= f.submit %>
<% end %>
Cheers!
When updating an object, we should :method => :put to override the post in the form as the following:
<%= simple_form_for #task, :url => update_task_url, :method => :put do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :description %>
</div>
<div class="form-actions">
<%= f.submit 'Update Task'%>
</div>
<% end %>
<%= link_to 'Back', tasks_path %>
In the controller before making the request, I tried to render the params to check everything is correct as follow:
render text: tasks_params
uri = URI.parse("http://localhost/tasks/public/api/tasks/"+params[:id])
response = Net::HTTP.post_form(uri, task_params)
render text: response.body
but I get the following without the _method attribute:
{"name"=>"Task#1", "description"=>"lorem ipsum"}
and as a result the request is not successful on the server side.
What am I missing here exactly?
You should post to the desired controller action like so
<%= simple_form_for #task, :url => update_task_url, :method => :post do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :description %>
</div>
<div class="form-actions">
<%= f.submit 'Update Task'%>
</div>
<% end %>
I would add a debugger break point in the update action in your TasksController just to make sure you are hitting the right route.
I'm having troubles handling objects that not respect the validation.
I'm building an app in which an user can create a "Trip" model and then add steps to his trip, that I called "Traces". Each added trace prints a new part of a map present in the trip#show action.
The association between models is user has_many trips and trip has_many traces
In the users#show I put a "CREATE NEW TRIP" button linking to the trips#new and here I have the form_for with the field corresponding to the Trip attributes.
When I fill the form correctly everything is ok. When something is missing or wrong (for the validations) I get this error:
NoMethodError in Trips#create
undefined method `model_name' for Array:Class
------ in the trips_controller.rb
def create
#trip = current_user.trips.build(params[:trip])
if #trip.save
# handle a successful save
flash[:success] = 'Trip created!'
redirect_to user_trip_path(#trip, user_id: current_user.id)
else
#trip = []
#feed_items = []
render 'new'
end
end
------ in app/views/trip, in the new.html.erb
h1>Create a trip</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3 general-input">
<%= form_for ([current_user, #trip]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name,'Give a name to your trip ;)' %>
<%= f.text_field :name %>
<%= f.label :trip_start, 'Choose your starting point!' %>
<%= f.text_field :trip_start %>
<%= f.label :departure, 'When are you leaving?' %>
<%= f.date_select :departure, :start_year => Date.current.year %>
<%= f.label :arrive, 'And coming back home?' %>
<%= f.date_select :arrive, :start_year => Date.current.year %>
<%= f.submit 'Create a new trip', class: 'btn btn-primary btn-lg' %>
<% end %>
EDIT 1: problem solving removing #trace=[ ] from trips_controller.rb
EDIT 2:
I also have a similar problem with the creation of a new Trace:
The form for adding a new trace is in the trip#show page.
When I try to create a trace that not respects the validation (e.g. if I leave blank the "destination" field) I get this error:
NoMethodError in Posts#create
undefined method `any?' for nil:NilClass
When I'm on the Trip page where the form for the Traces is placed, the URL is like:
http://localhost:3000/users/2/trips/8
but when I create a not valide Trace it switchs to a path like:
http://localhost:3000/trips/8/posts
I suppose I'm doing something wrong handling the error messages. I probably misunderstood something, even because I'm new to Rails and web programming in general.
Here you are some code parts, hoping it helps to understand my mistake:
------ in the traces_controller.rb
def create
#trip= Trip.find(params[:trip_id])
#trace = #trip.traces.create(params[:trace])
if #trace.save
flash[:success] = 'Trace created!'
redirect_to user_trip_path(#trip, user_id: current_user.id)
else
#trace=[]
render 'trips/show'
end
end
------ in app/views/shared, in the add_trace_form.html.erb
<p>Complete your trip adding a route!</p>
<%= form_for ([#trip, #trip.traces.build]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="block post-form">
<div class="field ">
<%= f.text_field :end, placeholder: 'Where are you going next?' %>
<%= f.label :arr_day, 'When?' %>
<%= f.date_select :arr_day, :start_year => Date.current.year %>
<%= f.submit 'Add route', class: 'btn btn-primary btn-landing' %>
</div>
</div>
<% end %>
------ in app/views/shared, in the error_messages.html.erb
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |message| %>
<li>* <%= message %></li>
<% end %>
</ul>
</div>
<% end %>
------ in the routes.rb
resources :users do
resources :trips
end
resources :trips do
resources :traces
end
resources :traces
Thanks a lot
i think when you are passing the f.object in locales in render its is passing array not the active record object ,<%= render 'shared/error_messages', object: f.object %>.
Can u check inspecting object in your partial and what class it has.
Try inspecting object.errors.inspect
Try refering http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
My Artist conroller, edit method looks like this
def edit
#user = User.find(params[:id])
end
In the view (artists/edit.html.erb), I have:
<%= form_for(#artist) do |f| %>
<ul>
<li class="clearfix">
<%= f.label :name %>
<%= f.text_field :name %>
</li>
...
</ul>
<%= image_submit_tag('update.png', :class => 'submit') %>
<% end %>
However, when rendered. The form element submits to the user controller, update method (i.e. ).
How do I make it submit to the artist controller, update method instead?
I think you want to change the form_for parameters :
<%= form_for(#artist, :url => edit_user_path(#artist)) do |f| %>
<ul>
<li class="clearfix">
<%= f.label :name %>
<%= f.text_field :name %>
</li>
...
</ul>
<%= image_submit_tag('update.png', :class => 'submit') %>
<% end %>
Cf http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
Also, are you sure your #artist points to #user ? I think you meant, in your controller :
#artist = User.find....
Ok, I am new to rails so I hope I explain this well. I seem to have a problem with a form collecting the proper information. Work in one spot and not another. Here is the situation.
I have created a blog with three tables, posts, comments, and votes. I have comments working correctly and votes working partially. Here is what I mean.
The /posts/show.html.erb file basically shows the post, the associated comments and it shows how many votes that post has. I am working the votes but using a form with a hidden field that delivers a value of '1' along with the post_id to the table. I am then using AJAX to return the #post.votes.count. This all works great.
I am trying to use this same vote/return mentioned above but on the /posts/index.html.erb page. In the index page I have the <% #post.each do |post| %> doing two things. First render :partial => post %> and then I have the same code that I am using on the show.html.erb page. The error that I am getting from the terminal is
ActiveRecord::RecordNotFound (Couldn't find Post without an ID):
app/controllers/votes_controller.rb:4:in `create'
I am guessing this has to do with it being part of the index record set which doesn't have a unique post param associated with the page. I am hoping there is a simple fix. Here is the code:
This is the /posts/show.html.erb code that is working correctly:
<div id="backto"<%= link_to 'Back to all BattleCries', posts_path %>
</div>
<%= render :partial => #post %>
<div id="beltcomments">
<div id="beltcommenttext">
<div id="vote">
<div id="votes">
<%= #post.votes.count %> People liked this BattleCry.
</div>
</div>
<div id="votebutton">
<% remote_form_for [#post, Vote.new] do |f| %>
<%= f.hidden_field :vote, :value => '1' %>
<%= f.submit "Like" %>
<% end %>
</div>
</div>
</div>
<div id="beltcommentsbottom">
</div><br/><br/>
<div id="belt">
<div id="belttext">
<p5>Add a Comment</p5>
<% remote_form_for [#post, Comment.new] do |f| %>
<p>
<%= f.text_area ( :body, :class => "commentarea") %>
</p>
<%= f.submit "Add Comment"%>
<% end %>
</div>
<div id="beltbottom">
</div>
</div><br/>
<div id="comments">
<%= render :partial => #post.comments %>
</div>
<br/>
<div id="commenttime">
Copyright 2009, My Life BattleCry, LLC.
</div>
<br/>
<br/>
<br/>
Here is where it is in the index page:
<% #posts.each do |post| %>
<%= render :partial => post %>
<%= render :partial => #post %>
<div id="beltcomments">
<div id="beltcommenttext">
<div id="vote">
<div id="votes">
<%= post.votes.count %> People liked this BattleCry.
</div>
<%= link_to "Comments (#{post.comments.count})", post %>
</div>
<div id="votebutton">
<% remote_form_for [#post, Vote.new] do |f| %>
<%= f.hidden_field :vote, :value => '1' %>
<%= f.submit "Like" %>
<% end %>
</div>
</div>
</div>
<br/>
<br/>
<br/>
<% end %>
<div id="commenttime">
Copyright 2009, My Life BattleCry, LLC.
</div>
<br/>
<br/>
<br/>
Here is the votes_controller.rb
class VotesController < ApplicationController
def create
#post = Post.find(params[:post_id])
#vote = #post.votes.create!(params[:vote])
respond_to do |format|
format.html { redirect_to #post}
format.js
end
end
end
Here is the /votes/create.js
page.replace_html :votes, :partial => #vote
page[#vote].visual_effect :highlight
Lastly, here is the partial, /_vote.html.erb:
page.replace_html :votes, :partial => #vote
page[#vote].visual_effect :highlight
I hope this makes sense. Let me know if I need to clarify anything.
I imagine this is causing problems. You didn't post your posts controller, but does the index action set #post?:
<%= render :partial => #post %>
Looks like I just needed to change the following in the <% #posts.each do |post| %> section of the index.html.erb file.
<% remote_form_for [#post, Vote.new] do |f| %>
<%= f.hidden_field :vote, :value => '1' %>
<%= f.submit "Like" %>
to
<% remote_form_for [post, Vote.new] do |f| %>
<%= f.hidden_field :vote, :value => '1' %>
<%= f.submit "Like" %>