Rails beginner here. I'm having trouble with commenting on posts. I have the comments working when they are on the same page as the post but after trying to set up seperate pages for creating and viewing the comments i get the following error:
No route matches {:action=>"new", :controller=>"comments", :id=>"27"} missing required
keys: [:post_id]
My posts/show.html.erb file: (the second line is the link that's causing the problem)
<h class="eventhead"><%= #post.description %></h>
<%= link_to "Add comment", new_post_comment_path, class: "btn btn-primary btn-medium" %>
And here's my comments/_form.html.erb file:
<%= simple_form_for [#post, Comment.new] do |f| %>
<p>
<%= f.input :title, :subtitle, :body, :label => "New Comment", as: :text, input_html: {
rows: "3" } %>
</p>
<p><%= f.submit "Add Comment", class: "btn btn-primary" %></p>
<% end %>
Thanks for the help!
You are using a nested resource, so this requires that you pass in the post_id to the link_to. Revise your code as:
<%= link_to "Add comment", new_post_comment_path(#post), class: "btn btn-primary btn-medium" %>
Just as #jaycode mentioned you will need to make sure the comment#new action assigns #postin your controller.
# comments_controller.rb
def new
#post = Post.find params[:post_id]
#comment = Comment.new
end
Welcome to Rails :)
Check the content of method new_post_comment_path. Most likely it requires :post_id variable to be passed into it.
Perhaps you should use this instead:
And make sure in comments_controller.rb action new (def new in that file), you have #post_id variable defined.
Related
When I use form_tag as below then I get this error:
AbstractController::ActionNotFound at /quizzes/[whichever_quiz_id]
The action 'whichever_quiz_id' could not be found for QuizzesController
My code is as below:
erb file
<%= form_tag action: :add_questions do %>
<%= collection_select(:quiz, :id, Quiz.where.not(id: params[:id]), :name, :id, prompt: 'Select Quiz') %>
<%= text_field_tag(:input_quiz_questions, 'Question ids') %>
<%= submit_tag "Add" %>
<% end %>
So here I have a method in my QuizController called add_questions which takes a selected question from another Quiz and adds it to the present Quiz.
def add_questions
id = params[:id]
required_quiz_id = params[:quiz][:id].to_i #taken from collection_select
required_questions_ids = params[:input_quiz_questions].split().map { |s| s.to_i } #taken from text_field_tag
# remaining logic here
routes
resources :quizzes, as: 'tests' do
member do
get :add_questions
end
end
So why am I getting the above error here and how can I rectify it?
You should write after form_tag the url, not the name of the action in the option hash
<%= form_tag quizzes_add_questions_path, method: :get do %>
I'm using nested resources, and in order to make a new Round, you need to have the id of its Case, so my routes.rb includes the following:
resources :cases do
resources :rounds
end
So, when a user hits the 'new round' button on the homepage, it first directs them to a page where they can pick a case that the round belongs to, before redirecting to the round form.
For the pick_case view, I have the following:
<%= form_tag new_case_round_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
However, rails forces me to name a case_id in the new_case_round_path, so it gives me this error before it loads the pick_case view:
No route matches {:action=>"new", :controller=>"rounds"} missing required keys: [:case_id]
How can I reference the route that the form needs to submit to when the required information for the route is being entered in the form?
No route matches {:action=>"new", :controller=>"rounds"} missing
required keys: [:case_id]
The error clearly says that case_id is missing. Rails expects case_id to be present which can't be provided in your situation as you are creating a new case instance.
One way to resolve your situation is to use Shallow Nesting which provides the route for new case
resources :cases do
resources :rounds, shallow :true
end
Now, when you run rake routes, you will find a route for new case as below
new_case GET /cases/new(.:format) cases#new
So that in your pick_case view, you can change the form to
<%= form_tag new_case_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
Which creates a case instance first before redirecting to the round form
A bit of a work-around for the answer, I feel like there's probably a more elegant way. I added post 'get_case' => rounds#get_case to routes.rb
I added this to my rounds controller:
def get_case
id = params[:case_id]
if id
redirect_to new_case_round_path(case_id: id)
else
flash[:danger] = "An error occured. Please try again"
redirect_to pick_case_path
end
end
And this is my new pick_case view:
<%= form_tag get_case_path do %>
<%= select_tag :case_id,
options_for_select(map_with_id(Case, :title)),
class: "chosen-select" %><br/>
<%= submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
I am rendering a form in a view in the instance that an user has not verified their email. This form also allows them to put in their email preferences.
Here is the form.
<%= form_tag update_email_and_sports_url, class: "form-signin", method: 'patch' do %>
<h2>Please confirm your email</h2>
<%= email_field_tag :email, nil, class: "input-block-level", placeholder: current_user.email %>
<h2>We'll email you when opportunities arise to play any of the sports you select below:</h2>
<%= check_box_tag :basketball, checked = false %>
<%= check_box_tag :volleyball, checked = false %>
<%= check_box_tag :soccer, checked = false %>
<%= check_box_tag :football, checked = false %>
<%= check_box_tag :hockey, checked = false %>
<%= check_box_tag :kickball, checked = false %>
<%= check_box_tag :softball, checked = false %>
<%= f.hidden_field_tag :user_id, :value => current_user.id %>
<div>
<%= submit_tag "Submit", class:"btn btn-large btn-success" %>
</div>
The view will not even render and I'm getting this error:
No route matches {:controller=>"users", :action=>"update_preferences"} missing required keys: [:id]
It's saying the error is in my form_tag line. Here is my route.
patch '/user/preferences/:id' => 'users#update_preferences', :as => 'update_email_and_sports'
And my controller
def update_preferences
current_user.email = params[:email]
preference = Preference.new(preference_params)
redirect_to root_url
end
def preference_params
params.require(:preference).permit(:user_id, :basketball, :football, :softball, :soccer, :kickball, :volleyball, :hockey)
end
Since you don't need id param to search for user in this action, you should remove it from your route to this action in routes.rb:
patch '/user/preferences' => 'users#update_preferences', :as => 'update_email_and_sports'
The error is raised because route with id included expects :id parameter, which you don't provide calling this route's helper.
Why is this happening?
The form_tag path (or in your case, url) needs to take an id (or an object) of the user you want to update... Something like:
<%= form_tag update_email_and_sports_url(current_user), class: "form-signin", method: 'patch' do %>
This will solve the error of missing required keys: [:id].
Potentially better idea...
However, if you're using current_user always for this update, you may consider dropping :id from your route... Then you'd leave the form_tag in your question as-is.
I have a form in Rails
<div class="page-header">
<h3>Create Blah</h3>
</div>
<%= simple_form_for #blah do |f| %>
<%= f.input :id %>
<%= f.input :name %>
<%= f.input :pho %>
<%= f.input :fun %>
<%= f.submit :class => 'btn btn-primary' %>
<% end %>
<br>
When I click the submit button, where does the code attempt to go? Does it call the create method for blah_controller.rb? Because currently, I get a routing error
Routing Error
uninitialized constant BlahsController
Here is the BlahController#create method:
def create
authorize! :create, :blahs
#blah = Blah.new(params[:blah])
if #blah.save
redirect_to admin_blah_path(#blah), :notice => 'New blah created!'
else
render :new
end
end
In my rake routes, I have
admin_blahs GET /admin/blahs(.:format) admin/blahs#index
POST /admin/blahs(.:format) admin/blahs#create
new_admin_blah GET /admin/blahs/new(.:format) admin/blahs#new
edit_admin_blah GET /admin/blahs/:id/edit(.:format) admin/blahs#edit
admin_blah GET /admin/blahs/:id(.:format) admin/blahs#show
PUT /admin/blahs/:id(.:format) admin/blahs#update
DELETE /admin/blahs/:id(.:format) admin/blahs#destroy
It looks like your BlahsController is a namespaced controller, living under the Admin module (i.e., its fully-qualified name is Admin::BlahsController). If so, when constructing forms you must also provide the :admin namespace, using something like the following:
<%= simple_form_for [:admin, #blah] do |f| %>
See the Rails Guide to Form Helpers, under the "Dealing with Namespaces" section.
<%= text_area_tag :body_html, "", :class =>"required mceEditor", :id=>"txaEditableContent" %>
This is my code. I want this text_area_tag to be assigned to an object(object is note in my case) just like we use "form_for object" so that the :body_html goes straight into params[:note] on submit. How can I do this?
You have got to set first an instance of Note in the controller corresponding action:
#note = Note.new
Then, in your view put this form:
<%= form_for #note do |f| %>
<%= f.text_area :body_html, :class => "required mceEditor", :id => "txaEditableContent" %>
<%= f.submit "Submit" %>
<% end %>
Now when you click the submit button you should get the right post request as you needed.