I'm trying to create a basic survey app. I'm attempting to create a choice with whatever answer the user creates, but for some reason my question isn't getting set in my choice controller.
Here's my routes:
resources :questions do
resources :choices, only: [:create, :destroy]
end
My view:
<h3>Questions:</h3>
<ul><% #survey.questions.each do |question| %>
<li><p><%= question.title %></p></li>
<% choice = question.choices.build %>
<% if question.single_response == true %>
<%= form_for [question, choice] do |f| %>
<% question.answers.each do |answer| %>
<%= f.radio_button :answer_id, answer.id %> <%= answer.title %><br>
<% end %>
<%= f.hidden_field :survey_id, value: #survey.id %>
<%= f.submit %>
My set_question method in my choice controller:
def set_question
#question = Question.find(params[:question_id])
end
And then my create method:
def create
#choice = #question.choices.build(choice_params)
respond_to do |format|
if #choice.save
format.html { redirect_to surveys_path, notice: 'Choice was successfully created.' }
format.json { render action: 'show', status: :created, location: #choice }
else
format.html { render action: 'new' }
format.json { render json: #choice.errors, status: :unprocessable_entity }
end
end
end
Which is netting a nil class error.
undefined method `choices' for nil:NilClass
Rails.root: /Users/thomashammond89/SurveyMe
Application Trace | Framework Trace | Full Trace
app/controllers/choices_controller.rb:27:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"XjNNShH6jvTAcz1NQqSBU+a+2exP2STPFnja+yfbinY=",
"choice"=>{"answer_id"=>"19",
"survey_id"=>"1",
"question_id"=>"13"},
"commit"=>"Create Choice",
"question_id"=>"13"}
Which looks to me that the question_id is there in the params. Any idea why it's not getting set?
You aren't defining the instance variable #question in your create action. Try:
#question = Question.find(params[:choice][:question_id])
Related
I would like to create a booking from bookings#new and rooms#show. When I try to create it from bookings#new it works, but when try to create it from rooms#show it shows me the error:
1 error prohibited this booking from being saved, room must exist.
Here is the code I'm using:
BookingsController:
def create
if #room
#room = Room.find(params[:room_id])
#booking = #room.bookings.create(booking_params)
if #booking.save
redirect_to room_path(#room)
else
render :new
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: #booking }
else
format.html { render :new }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
end
views/rooms/show.html.erb
<h2>book this room:</h2>
<%= form_with(model: [ #room, #room.bookings.build ], local: true) do |form| %>
<p>
<%= form.label :traveller %>
<%= form.text_field :traveller %>
</p>
<p>
<%= form.label :startfrom %>
<%= form.datetime_select :startfrom %>
</p>
<p>
<%= form.label :endsat %>
<%= form.datetime_select :endsat %>
</p>
<p>
<%= form.label :bookingref %>
<%= form.text_field :bookingref %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Your mistake is inside if-else in the controller. You're checking #room before you define it, so it is always nil. It should be:
def create
# use find_by here, otherwise you get RecordNotFound error
#room = Room.find_by(id: params[:room_id])
if #room
# use build, because create saves the instance
#booking = #room.bookings.build(booking_params)
if #booking.save
redirect_to room_path(#room)
else
# I suppose you don't want render bookings/new view here
render 'books/show'
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
# redirect and render logic goes here. BTW, do you really need json response format?
end
end
end
end
Also, define in rooms#show action
#booking = #room.bookings.build
and use the instance in the form to correctly display validation errors
form_with(model: [#room, #booking], local: true) do |form|
I'm trying to use an if else statement in show.html.erb in the Assignment to check if a record in Bid exists. But I encountered a syntax error "SyntaxError in AssignmentsController#show" that occurs on the first line of the code below:
<%= if Bid.exists?(user_id: current_user.id, assignment_id: #assignment.id) %>
<p>it exists</p>
<%= else %>
<p>it doesn't exists</p>
The following is the entire file Assignment/show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<strong>Assignment:</strong>
<%= #assignment.assignment %>
</p>
<p>
<strong>Education:</strong>
<%= #assignment.education.education %>
</p>
<p>
<strong>Subject:</strong>
<%= #assignment.subject.subject %>
</p>
<p>
<strong>Gender prefer:</strong>
<%= #assignment.gender_prefer %>
</p>
<p>
<strong>Timeslot:</strong>
<%= #assignment.timeslot %>
</p>
<p>
<strong>Duration:</strong>
<%= #assignment.duration %>
</p>
<p>
<strong>Budget:</strong>
<%= #assignment.budget %>
</p>
<p>
<strong>Budget unit:</strong>
<%= #assignment.budget_unit %>
</p>
<p>
<strong>Assignment info:</strong>
<%= #assignment.assignment_info %>
</p>
<p>
<strong>Assignment id:</strong>
<%= #assignment.id %>
</p>
<%= if Bid.exists?(user_id: current_user.id, assignment_id: #assignment.id) %>
<p>it exists</p>
<%= else %>
<p>it doesn't exists</p>
<%= end %>
<%= link_to "Create Bid", bids_path(:status => "Pending", :assignment_id => #assignment.id, :user_id => current_user.id), :method => :post %> |
<%= link_to 'Bid', {controller: "bids", action: "new", id: #assignment.id} %> |
<%= link_to 'Bid', bid_path, method: :post %> |
<%= link_to 'Bid', edit_bid_path %> |
<%= link_to 'Edit', edit_assignment_path(#assignment) %> |
<%= link_to 'Back', assignments_path %>
The following is the entire file assignments_controller.rb:
class AssignmentsController < ApplicationController
before_action :authenticate_user!
before_action :set_assignment, only: [:show, :edit, :update, :destroy]
# GET /assignments
# GET /assignments.json
def index
#assignments = Assignment.all
end
# GET /assignments/1
# GET /assignments/1.json
def show
end
# GET /assignments/new
def new
#assignment = Assignment.new
end
# GET /assignments/1/edit
def edit
end
# POST /assignments
# POST /assignments.json
def create
#assignment = Assignment.new(assignment_params)
respond_to do |format|
if #assignment.save
format.html { redirect_to #assignment, notice: 'Assignment was successfully created.' }
format.json { render :show, status: :created, location: #assignment }
else
format.html { render :new }
format.json { render json: #assignment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /assignments/1
# PATCH/PUT /assignments/1.json
def update
respond_to do |format|
if #assignment.update(assignment_params)
format.html { redirect_to #assignment, notice: 'Assignment was successfully updated.' }
format.json { render :show, status: :ok, location: #assignment }
else
format.html { render :edit }
format.json { render json: #assignment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /assignments/1
# DELETE /assignments/1.json
def destroy
#assignment.destroy
respond_to do |format|
format.html { redirect_to assignments_url, notice: 'Assignment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_assignment
#assignment = Assignment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def assignment_params
params.require(:assignment).permit(:assignment, :education_id, :subject_id, :gender_prefer, :timeslot, :duration, :budget, :budget_unit, :assignment_info)
end
end
I've tried simple if else statements which stills returns an error:
<%= if 1 > 0 %>
<p>it exists</p>
<%= else %>
<p>it doesn't exists</p>
<%= end %>
You must not put the = sign in your erb tags with if, else or end. Try something like this :
<% if 1 > 0 %>
<p>it exists</p>
<% else %>
<p>it doesn't exists</p>
<% end %>
<%= %> will print the result of your line into the generated html. So for all the lines that you don't want to print (like the if , else or for statements, and the end too), use <% %> instead.
If you want more details on erb tags, there is this this SO answer : What is the difference between <%, <%=, <%# and -%> in ERB in Rails?
you are not allowed to add = with if.
Use if like this
<% if 1 > 0 %>
<p>it exists</p>
<% end %>
This my first ruby on rails application.
Model Location and Post, Location has many post.I create location as tree structure with ancestry gem.
class Post < ActiveRecord::Base
belongs_to :location, :counter_cache => true
end
class Location < ActiveRecord::Base
include Tree
has_ancestry :cache_depth => true
has_many :posts
end
This my Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
private
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name, :location_id)
end
end
Creating Post with location in Post _form.html.erb
<%= simple_form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.input :name %>
<%= f.select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My question are
First question- f.select :location_id , how display location name, not location id, i am using with simple form
Second question- Post index got error in <%= post.location.name %>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.location.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %> </td>
</tr>
<% end %>
First question:
Check the simple_form syntax for a dropdown. It is mentioned in the docs and you should be able to get this working by yourself.
Second question:
Does the offending post really have a related location? If it does not have one, it can not display the name of course. To counter these nil errors, use try:
<%= post.location.try(:name) %>
try will call the method name on location only if location is not nil.
For your first question :
Maybe you should read about "options_for_select"
http://guides.rubyonrails.org/form_helpers.html#option-tags-from-a-collection-of-arbitrary-objects
<% cities_array = City.all.map { |city| [city.name, city.id] } %>
<%= options_for_select(cities_array) %>
For your second question:
What is your error ?
Maybe one of your "post.location" is nil.
If so, try:
post.location.name unless post.location.nil?
Hope this can help
I'm trying to add answers to questions. Each questions has_one answer. I'm showing them on the comment page through partials except I keep getting this error:
undefined local variable or method `answer'
Here is part of my answers_controller.rb
class AnswersController < ApplicationController
before_action :set_answer, only: [:show, :edit, :update, :destroy]
def index
#question = Question.find params[:question_id]
#question.answers
end
def show
end
def new
#question = Question.find params[:question_id]
end
def edit
end
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(answer_params)
respond_to do |format|
if #answer.save
format.html { redirect_to #comment, notice: 'Answer was successfully created.' }
format.json { render action: 'show', status: :created, location: #answer }
else
format.html { render action: 'new' }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
Here is my _question.html.erb partial where the answer partial is called:
<%=div_for(question) do %>
<div class="questioncontainer">
<p>
<%= question.body %>
<%= render :partial => #question.answers %>
<% if current_user == #comment.user %>
<div class="answercontainer">
<%= link_to 'Answer', new_question_answer_path(question)%>
</div>
</div>
</p>
<% end %>
<% end %>
Last, here is my _answer.html.erb partial:
<%=div_for(answer) do %>
<div class="questioncontainer">
<p>
<%= answer.body %>
</p>
</div>
<% end %>
Thanks for the help :)
Pass answer as local, via locals: {answer: #answer}
Use
<%= render question.answers %>
instead of
<%= render :partial => #question.answers %>
More info here: http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
I have two models, Recipe and Tag, with a has_and_belongs_to_many relation. For this relation I have a simple join table, RecipesTags.
Recipe:
has_and_belongs_to_many :tags
Tag:
has_and_belongs_to_many :recipes
Now upon creating a new recipe, the user gets to fill in which category the recipe belongs to in forms of checkboxes, like "Meat", "Fish", and so on. These categories are in fact just tags in the database.
Problem: the recipes doesn't get any tags saved to it.
Recipe new and create controller methods:
def new
#recipe = Recipe.new
#ingredients = Ingredient.all
#tags = Tag.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: #recipe }
end
end
# POST /recipes
# POST /recipes.json
def create
#recipe = Recipe.new(params[:recipe])
if (params[:tags])
#recipe.tags << params[:tags]
end
respond_to do |format|
if #recipe.save
format.html { redirect_to #recipe, notice: 'Recipe was successfully created.' }
format.json { render json: #recipe, status: :created, location: #recipe }
else
format.html { render action: "new" }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
end
The view:
<%= form_for(#recipe, :html => {:multipart => true}) do |f| %>
<% if #recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
# [ fields that get's saved for the recipe and works fine ]
<% #tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box :tags, t.name %>
<br />
<% end %>
<%= f.submit 'Submit recipe', :class => 'btn btn-primary' %>
<% end %>
At the moment, I get an error message saying:
undefined method `merge' for "Meat":String
"Meat" is the tag name.
So, what am I doing wrong here?
I think the issue is this line #recipe.tags << params[:tags].
The association method you're calling with << takes an object (in this case expecting a tag object), but in this case it seems you might be passing it a string.
For more info this link may be helpful http://guides.rubyonrails.org/association_basics.html#has_and_belongs_to_many-association-reference, in particular where it refers to collection<<(object, …).
In your controller you'll want to do something like #recipe.tags << tag where tag is a specific tag object.
So, try this:
In your controller
params[:tags].each do |k,v|
#recipe.tags << Tag.find(k)
end
In your view
<% #tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box "tags[#{t.id}]" %>
<br />
<% end %>
Try this:
def create
#recipe = Recipe.new(params[:recipe])
params[:tags].each do |tag|
#recipe.tags << Tag.find_by_name(tag)
end
respond_to do |format|
if #recipe.save
format.html { redirect_to #recipe, notice: 'Recipe was successfully created.' }
format.json { render json: #recipe, status: :created, location: #recipe }
else
format.html { render action: "new" }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
end
In view:
<% #tags.each do |t| %>
<%= label_tag t.name %>
<%= check_box_tag "tags[#{t.name}]", t.name %>
<br />
<% end %>