Rails Instance Variables - ruby-on-rails

I'm working on creating a survey app where surveys can have many questions and questions can have many surveys. What I'd like to do is on the survey show page display a button "Add new question" that allows a user to add a new question to that survey. So in my code I send the survey id like this:
<%= link_to "Add Question", new_question_path(:survey_id => #survey.id)%>
Then I can set #survey using the params I'm sending in my question controller. This is working fine in my :new method, but is throwing a nil error when I try to call in the :create method. I believe this is because a new instance of the controller is getting created which no longer has access to the :survey_id param I sent initially.
So I'm wondering if there is anyway to pass along the params to the next instance of the controller? Or is there a better way to send which survey should be set for that question? Is this something I could "save" in a hidden field? I thought about trying to save something in my model, but to save a question earlier would require me to remove the validations I have.
Here's my question_controller:
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
before_action :set_survey, only: [:new, :create]
# GET /questions
# GET /questions.json
def index
#questions = Question.all
end
# GET /questions/1
# GET /questions/1.json
def show
#answers = #question.answers
end
# GET /questions/new
def new
#question = Question.new
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
def create
#question = Question.new(question_params)
respond_to do |format|
if #question.save
#survey.questions << #question
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
format.html { redirect_to questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
def set_survey
#survey = Survey.find(params[:survey_id])
flash[:alert] = "Survey is " + #survey.to_s
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :single_response, :surveys, :surveytizations)
end
end
And the form I'm creating the question with:
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :single_response %><br>
<%= f.check_box :single_response %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Thanks! Any help is very much appreciated!
UPDATE:
I was able to work using Rails.cache.write/Rails.cache.read - How to pass values between controller methods
Is there anything wrong with doing it that way or is that the best route?

I think you need to store the survey_id in a hidden field. Then you can access it from the questions controller. In your view:
<%= form_for(#question) do |f| %>
<%= f.hidden_field :survey_id %>
#rest of form
You also might have to change your new action to something like this:
#question = Question.new(:survey_id => params[:survey_id])
If the questions always belongs to a survey it could be a good idea to nest the routes so that you always can check which survey you are working on.

Related

Rails: undefined method `each' for nil:NilClass

I want to build a for loop but I an this error.
undefined method `each' for nil:NilClass
That is the part of the view, which gives me the error:
<% #deadlines.each do |deadline| %>
<% if Time.now < deadline.deadline %>
<%= form_for(current_user) do |f| %>
<%= f.hidden_field :enrolled, :value => true %>
<%= f.submit "Anmeldung bestätigen", class: "btn btn-primary" %>
<% end %>
<% end %>
<% end %>
Seems like #deadlines is not recognized, even though I already used the same loop in the Index view of the deadlines folder. How can I use the same variable in my homepage view?
Thanks a lot!
Here is the Controller, maybe it also gives you some information:
class DeadlinesController < ApplicationController
before_action :set_deadline, only: [:show, :edit, :update, :destroy]
# GET /deadlines
# GET /deadlines.json
def index
#deadlines = Deadline.all
end
# GET /deadlines/1
# GET /deadlines/1.json
def show
end
# GET /deadlines/new
def new
#deadline = Deadline.new
end
# GET /deadlines/1/edit
def edit
end
# POST /deadlines
# POST /deadlines.json
def create
#deadline = Deadline.new(deadline_params)
respond_to do |format|
if #deadline.save
format.html { redirect_to #deadline, notice: 'Deadline was successfully created.' }
format.json { render :show, status: :created, location: #deadline }
else
format.html { render :new }
format.json { render json: #deadline.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /deadlines/1
# PATCH/PUT /deadlines/1.json
def update
if #deadline.update(deadline_params)
flash[:success] = "Die Deadline wurde erfolgreich aktualisiert."
redirect_to deadlines_path
else
flash[:error] = "Die Deadline wurde nicht aktualisiert."
end
end
# DELETE /deadlines/1
# DELETE /deadlines/1.json
def destroy
#deadline.destroy
respond_to do |format|
format.html { redirect_to deadlines_url, notice: 'Deadline was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_deadline
#deadline = Deadline.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def deadline_params
params.require(:deadline).permit(:deadline)
end
end
Your #deadlines is empty now, use this #deadlines = Deadline.all to your homepage controller action and each block modify like this
<% if #deadlines.present? %>
<% #deadlines.each do |deadline| %>
<% if Time.now < deadline.deadline %>
<%= form_for(current_user) do |f| %>
<%= f.hidden_field :enrolled, :value => true %>
<%= f.submit "Anmeldung bestätigen", class: "btn btn-primary" %>
<% end %>
<% end %>
<% end %>
<% else %>
Deadline is empty
<% end %>
When #deadlines is empty then it will show Deadline is empty

Find record in table and save id to another table in Rails

I'm developing an app in which users can have a personal food diary.
It's pretty simple: a user can search for a nutrient on a Nutrients table (let's say milk) - currently through a pretty simple search form - and then should be able to save the amount he consumed of this nutrient (together with the nutrient_id) on a second table, which is called Diaries (that holds the nutrient_id as foreign key and an integer field called "amount").
My search works. I can also create new records in Diaries but I have to type in the nutrient_id manually.
My question is now how I can make this easily work? Ideally a user finds a nutrient clicks on it and will be redirected to a page that shows this nutrient together with a field for "amount" and a save button to save both information (nutrient_id and amount) on the Diaries table.
At the end of the day I think the user will be directed to the new action of my diary controller - the question is how my app sets the nutrient_id for this action for the nutrient the user selected before?
Sorry if this is a too simple question but I just started coding few weeks ago.
Thanks a lot for help!
My code looks like as follows:
nutrient.rb
class Nutrient < ActiveRecord::Base
has_many :diaries
def self.search(search)
where("name LIKE ?", "%#{search}%")
end
end
diary.rb
class Diary < ActiveRecord::Base
belongs_to :nutrient
end
nutrients_controller.rb
class NutrientsController < ApplicationController
before_action :set_nutrient, only: [:show, :edit, :update, :destroy]
# GET /nutrients
# GET /nutrients.json
def index
#nutrients = Nutrient.all
end
def search
if params[:search]
#nutrients = Nutrient.search(params[:search]).order("created_at DESC")
if #nutrients.present?
#nutrients
else
flash[:notice] = "Nutrient not found in database"
end
end
end
# GET /nutrients/1
# GET /nutrients/1.json
def show
end
# GET /nutrients/new
def new
#nutrient = Nutrient.new
end
# GET /nutrients/1/edit
def edit
end
# POST /nutrients
# POST /nutrients.json
def create
#nutrient = Nutrient.new(nutrient_params)
respond_to do |format|
if #nutrient.save
format.html { redirect_to #nutrient, notice: 'Nutrient was successfully created.' }
format.json { render :show, status: :created, location: #nutrient }
else
format.html { render :new }
format.json { render json: #nutrient.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /nutrients/1
# PATCH/PUT /nutrients/1.json
def update
respond_to do |format|
if #nutrient.update(nutrient_params)
format.html { redirect_to #nutrient, notice: 'Nutrient was successfully updated.' }
format.json { render :show, status: :ok, location: #nutrient }
else
format.html { render :edit }
format.json { render json: #nutrient.errors, status: :unprocessable_entity }
end
end
end
# DELETE /nutrients/1
# DELETE /nutrients/1.json
def destroy
#nutrient.destroy
respond_to do |format|
format.html { redirect_to nutrients_url, notice: 'Nutrient was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_nutrient
#nutrient = Nutrient.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def nutrient_params
params.require(:nutrient).permit(:name)
end
end
diaries_controller.rb
class DiariesController < ApplicationController
before_action :set_diary, only: [:show, :edit, :update, :destroy]
# GET /diaries
# GET /diaries.json
def index
#diaries = Diary.all
end
# GET /diaries/1
# GET /diaries/1.json
def show
end
# GET /diaries/new
def new
#diary = Diary.new
end
# GET /diaries/1/edit
def edit
end
# POST /diaries
# POST /diaries.json
def create
#diary = Diary.new(diary_params)
respond_to do |format|
if #diary.save
format.html { redirect_to #diary, notice: 'Diary was successfully created.' }
format.json { render :show, status: :created, location: #diary }
else
format.html { render :new }
format.json { render json: #diary.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /diaries/1
# PATCH/PUT /diaries/1.json
def update
respond_to do |format|
if #diary.update(diary_params)
format.html { redirect_to #diary, notice: 'Diary was successfully updated.' }
format.json { render :show, status: :ok, location: #diary }
else
format.html { render :edit }
format.json { render json: #diary.errors, status: :unprocessable_entity }
end
end
end
# DELETE /diaries/1
# DELETE /diaries/1.json
def destroy
#diary.destroy
respond_to do |format|
format.html { redirect_to diaries_url, notice: 'Diary was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_diary
#diary = Diary.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def diary_params
params.require(:diary).permit(:nutrient_id, :amount)
end
end
routes.rb
Rails.application.routes.draw do
resources :diaries
resources :nutrients do
collection do
get :search
end
end
_form.html.erb (for a new diary record)
<%= form_for(#diary) do |f| %>
<% if #diary.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#diary.errors.count, "error") %> prohibited this diary from being saved:</h2>
<ul>
<% #diary.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :nutrient_id %><br>
<%= f.number_field :nutrient_id %>
</div>
<div class="field">
<%= f.label :amount %><br>
<%= f.number_field :amount %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There are several ways to resolve this, one the quickest and most likely the best approach to me would be to nest the diaries under nutrients, since diaries belongs_to :nutrients
resources :nutrients do
resources :diaries
collection do
get :search
end
end
This way your all your diaries path method would accept a #nutrient argument and your route would be like: /nutrients/4/diaries/1
So in your diaries_controller, you could have:
class DiariesController < ApplicationController
before_action :set_nutrient
def new
#diary = #nutrient.diaries.new
end
def create
#diary = #nutrient.diaries.new(diary_params) # you can safely remove the nutrient_id from the strong params
... remaining logic here
end
...
private
def set_nutrient
#nutrient ||= Nutrient.find(params[:nutrient_id])
end
# You cans skip/ignore this method, if you don't want to be too strict
def set_diary
#diary ||= #nutrient.diaries.find(params[:id])
end
end
Then in your view, you could then have:
<%= form_for([#nutrient, #diary]) do |f| %>
<% if #diary.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#diary.errors.count, "error") %> prohibited this diary from being saved:</h2>
<ul>
<% #diary.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :amount %><br>
<%= f.number_field :amount %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
As I mentioned, there are still other ways of doing this, as you could also use hidden_fields however, this seem to be the cleanest way to me.
If you don't always want your diaries routes to be nested, you could expect: [the list of actions that should not be nested, eg show], both on your before_action and your routes' resources :diaries. Hope I'm able to help or let me know other confusions you may encounter.

Nested resources in rails not saving

Ive setup some nested resources in Rails using the following:
resources :notes do
resources :comments
end
But even though /notes/1/comments/new will take me to a new comments page, it does not make the association of the note for the comment. I have included an note_id field in the comment but this does not get populate. Any tips?
Comments controller:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to #comment, notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: #comment }
else
format.html { render :edit }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:note_id, :comment)
end
end
Form code:
<%= form_for(#comment) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :note_id %><br>
<%= f.text_field :note_id %>
</div>
<div class="field">
<%= f.label :comment %><br>
<%= f.text_area :comment %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should create your Comment like this in your controller:
class CommentsController < ApplicationController
before_action :set_comment, :set_note, only: [:show, :edit, :update, :destroy]
# Build your comment from your #note
# this sets all the association values correct (like ids)
def create
#comment = #note.comments.build(comment_params)
# etc...
end
def set_note
#note = Note.find(params[:note_id])
end
#...
end
So, using the #note.commments.build will help you on your issue. But of course, you need to query the #note using the note_id in the params hash.

Nested Form in Rails 4 not being rendered in view

Apologies if this has already been answered but I can't find anything that can help me. I am a newbie with Rails so please be gentle :D
I have been pulling my hair out trying to get nested forms working, I am sure I got nested forms working using Rails 3 and the railscasts demo last year, but Rails 4 is beating me.
Looking at the log, the query is being run to pull the data for the associated table, but nothing is rendered in the form.
I have read many web sites, but none have helped so far and I don't know where to start. The latest article I have followed is this http://www.createdbypete.com/articles/working-with-nested-forms-and-a-many-to-many-association-in-rails-4/
Still nothing being rendered in the view.
Where do I start debugging this, maybe my Rails install is broken?? But I am probably missing something crucial.
Thanks,
Royce
Edit - I have added some of the controllers and the view in question
surveys_controller.rb
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy, :answers]
# GET /surveys
# GET /surveys.json
def index
#surveys = Survey.all
end
# GET /surveys/1
# GET /surveys/1.json
def show
end
# GET /surveys/new
def new
#survey = Survey.new
end
# GET /surveys/1/edit
def edit
end
# POST /surveys
# POST /surveys.json
def create
#survey = Survey.new(survey_params)
respond_to do |format|
if #survey.save
format.html { redirect_to #survey, notice: 'Survey was successfully created.' }
format.json { render :show, status: :created, location: #survey }
else
format.html { render :new }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /surveys/1
# PATCH/PUT /surveys/1.json
def update
respond_to do |format|
if #survey.update(survey_params)
format.html { redirect_to #survey, notice: 'Survey was successfully updated.' }
format.json { render :show, status: :ok, location: #survey }
else
format.html { render :edit }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
# DELETE /surveys/1
# DELETE /surveys/1.json
def destroy
#survey.destroy
respond_to do |format|
format.html { redirect_to surveys_url, notice: 'Survey was successfully destroyed.' }
format.json { head :no_content }
end
end
def answers
#participants = Participant.all
#questions = #survey.questions
end
private
# Use callbacks to share common setup or constraints between actions.
def set_survey
#survey = Survey.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit(:name,
:questions_attributes => [:id, :content,
:answers_attributes => [:id, :content, :participant_id]
])
end
end
participents_controller.rb
class ParticipantsController < ApplicationController
before_action :set_participant, only: [:show, :edit, :update, :destroy]
# GET /participants
# GET /participants.json
def index
#participants = Participant.all
end
# GET /participants/1
# GET /participants/1.json
def show
end
# GET /participants/new
def new
#participant = Participant.new
end
# GET /participants/1/edit
def edit
end
# POST /participants
# POST /participants.json
def create
#participant = Participant.new(participant_params)
respond_to do |format|
if #participant.save
format.html { redirect_to #participant, notice: 'Participant was successfully created.' }
format.json { render :show, status: :created, location: #participant }
else
format.html { render :new }
format.json { render json: #participant.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /participants/1
# PATCH/PUT /participants/1.json
def update
respond_to do |format|
if #participant.update(participant_params)
format.html { redirect_to #participant, notice: 'Participant was successfully updated.' }
format.json { render :show, status: :ok, location: #participant }
else
format.html { render :edit }
format.json { render json: #participant.errors, status: :unprocessable_entity }
end
end
end
# DELETE /participants/1
# DELETE /participants/1.json
def destroy
#participant.destroy
respond_to do |format|
format.html { redirect_to participants_url, notice: 'Participant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_participant
#participant = Participant.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def participant_params
params.require(:participant).permit(:name)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
answers.html.erb
<h1><%= #survey.name %> Answers</h1>
<%= form_for(#survey) do |f| %>
<% #participants.each do |participant| -%>
<h3><%= participant.name %></h3>
<table>
<thead>
<tr>
<td>Questions</td>
<td>Answer</td>
</tr>
</thead>
<tbody>
<% #questions.each do |question| -%>
<tr>
<td><%= question.content %></td>
<td>
<%= f.fields_for :questions, question do |q| -%>
<%= q.fields_for :answers, question.answers.find_or_initialize_by(participant: participant) do |a| -%>
<%= a.text_area :content %>
<%= a.hidden_field :participant_id, participant.id %>
<% end -%>
<% end -%>
</td>
</tr>
<% end -%>
</tbody>
</table>
<% end -%>
<div class="actions">
<%= f.submit %>
</div>
<% end -%>
As you're new with Rails, let me explain how nested forms work for you!
--
Nested
Nested forms are not actually nested at all - they are associative forms.
You must remember that Rails (by virtue of being built on Ruby) is an object orientated framework. OOP (object orientated programming) is not just a buzzword - it's a fundamental core construction for your application & how it hands input / execution.
The problem many people have is they don't realize the true nature of Rails, and consequently become confused about how its many features work. If you appreciate that everything you do in Rails should be constructed around objects, life gets much simpler!
--
Form
With this in mind, you can begin to appreciate the role of objects throughout Rails, to the degree that you need to build / invoke objects for every element of your Rails application, including your form:
#app/models/survey.rb
Class Survey < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions
end
#app/controllers/surveys_controller.rb
Class SurveysController < ApplicationController
def new
#survey = Survey.new
#survey.questions.build #-> very important
end
end
#app/views/surveys/new.html.erb
<%= form_for #survey do |f| %>
...
<%= f.fields_for :questions do |q| %>
<%= q.text_field :title %>
<% end %>
<%= f.submit %>
<% end %>
This should create a form which allows you to pass associative data through to your child model. There are several important elements to consider:
You need to include accepts_nested_attributes_for in your "parent" model
You need to build your associative objects
You need to populate your form with the relative objects
By following this simple pattern, you'll be able to populate the nested form that you wish to show in the view
Try to use the following code:
<%= f.fields_for :questions do |q| -%>
<%= q.fields_for :answers, q.object.answers.find_or_initialize_by(participant: f.object.participant) do |a| -%>
<%= a.text_area :content %>
<%= a.hidden_field :participant_id, participant.id %>
<% end -%>
<% end -%>
and make sure that you render to answers.html.erb, you have accepts_nested_attributes_for :questions in survey.rb file, and accepts_nested_attributes_for :answers in question.rb file
Have you got accepts_nested_attributes_for :question in your survey model? And the same for the answer model?

Ruby on Rails form_for reference class id and pass to child comment

I have a class called "questions", which is similar to an article, and each of them can have comments. Now the problem is, that I want to show multiple questions on the index page and all displaying the comments of the specific question as well as a small little form to leave a comment, which should be added to its question. Basically I have added the form and done everything, apart from figuring out how to get the question id and pass it to the comment.
I have made a little screenshot as well: http://prntscr.com/2pjk0i
questions_controller.rb
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
# GET /questions
# GET /questions.json
def index
#current_user ||= User.find_by_id(session[:user_id])
#questions = Question.all
end
# GET /questions/1
# GET /questions/1.json
def show
end
# GET /questions/new
def new
#question = Question.new
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
def create
#question = Question.new(question_params)
#current_user ||= User.find_by_id(session[:user_id])
#question.update(:user_id => #current_user.id)
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
format.html { redirect_to questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :body)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#current_user ||= User.find_by_id(session[:user_id])
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
#current_user ||= User.find_by_id(session[:user_id])
#comment.update(:user_id => #current_user.id, :question_id => ?) # What to add here to get the specific question id?
respond_to do |format|
if #comment.save
format.html { redirect_to '/', notice: 'comment was successfully created.' }
format.json { render action: 'show', status: :created, location: #comment }
else
format.html { render action: 'new' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to '', notice: 'comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to '' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:title, :body)
end
end
index.html.erb
<h1>Listing questions</h1>
<%= link_to 'New Question', new_question_path %>
<hr>
<% #questions.each do |question| %>
<!-- Author -->
<%= question.user.name %> <br>
<!-- Date -->
<%= question.created_at %> <br>
<!-- Title -->
<%= question.title %> <br>
<!-- Body -->
<%= question.body %> <br>
<%= question.id %> <br>
<!-- Comment count -->
<%= question.comments.size %> Comment <br>
<!-- Comments -->
<% question.comments.each do |comment| %>
<!-- Comment Author -->
<%= comment.user.name %> <br>
<!-- Comment Date -->
<%= comment.created_at %> <br>
<!-- Comment Body -->
<%= comment.body %> <br>
<% end %>
<%= form_for(question.comments.new) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<hr>
<% end %>
Thank you in advance for your help! :)
The form_for will need to submit the question_id somehow - either by a route or through the form. I recommend a route.
If you don't interact with comments independently - if there is always a question, then change your routes to something like this:
resources :questions do
resources :comments
end
Then - in your form for, you will do this
<%= form_for [question, question.comments.new] do |f| %>
This will cause the form to submit (POST) to /question/:question_id/comments and you can handle it from there.
In the comments controller - you'll get the question from the params[:question_id] and return the result via an ajax response (respond to json).
This part is still tricky if you haven't done it before. If you need help with that part, you can probably find good examples or ask a separate question...
you can add hidden field inside your form
<%= f.hidden_field :question_id, value: question.id %>
or you can change your form
<%= form_for :comment, :url => comments_path(question_id:question.id) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
when u submit this form u will have url like /comments?question_id=id

Resources