I have created a simple form of nested resources. I can't get the child form todo_item to save correctly. When I click the "create todo item" button, an empty record will be created and saved no matter what I put in the title field.
The code is really simple and the parent record is saving fine. the child records are displaying so I can't figure out what could be wrong. Please help.
My models:
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
end
class TodoList < ActiveRecord::Base
has_many :todo_items, dependent: :destroy
end
My controllers:
class TodoItemsController < ApplicationController
before_action :set_todo_list
before_action :set_todo_item, only: [:show, :edit, :update, :destroy]
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
private
def set_todo_item
#todo_item = #todo_list.todo_items.find(params[:id])
end
def set_todo_list
#todo_list = TodoList.find(params[:todo_list_id])
end
def todo_item_params
params.require(:todo_item).permit(:title, :due_date, :description, :text, :completed)
end
end
View.html.erb:
<h1>New Todo Item</h1>
<%= render 'form' %>
<%= link_to 'Back', #todo_list %>
_form.html.erb:
<%= form_for([#todo_list, #todo_item]) do |f| %>
...
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You initialize the #todo_item here:
def create
#todo_item = #todo_list.todo_items.new # <===== INITIALIZED HERE
respond_to do |format|
if #todo_list.save # <===== SAVED HERE WITHOUT EVER ASSIGNING VALUES.
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
But, don't provide any arguments to new. So, the new record has no values.
Instead, do something more like:
#todo_item = #todo_list.todo_items.new(todo_item_params)
Perhaps you should also add some validations so you could avoid this situation.
You need to modify the create method:
def create
#todo_item = #todo_list.todo_items.create(todo_item_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
Related
sorry for this question but I'm struggling with this issue for hours now and can't find the answer anywhere.
Here is the thing, I have a rails app with "Reservation" and "Space" models with the following relations:
class Reservation < ActiveRecord::Base
belongs_to :space
belongs_to :user
end
class Space < ActiveRecord::Base
belongs_to :condo
has_many :reservations
end
When the user creates a new Reservation, in the form he gets to choose from a dropdown (f.select) the spaces available for him. The f.select in the form look like this:
<div class="field">
<%= #user_spaces = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user_spaces, :id, :name), :prompt => "Select space"
%>
</div>
That select it supose to assign a value to the key "space_id" in the Reservation that is being created (column's table is created). But when I check the last reservation in Rails console, space_id value is "nil". What am I doing wrong?
Thank you very much for your help
Reservation controller file:
class ReservationsController < ApplicationController
before_action :set_reservation, only: [:show, :edit, :update, :destroy]
# GET /reservations
# GET /reservations.json
def index
#reservations = Reservation.all
end
# GET /reservations/1
# GET /reservations/1.json
def show
end
# GET /reservations/new
def new
#reservation = Reservation.new
end
# GET /reservations/1/edit
def edit
end
# POST /reservations
# POST /reservations.json
def create
#reservation = Reservation.new(reservation_params)
#user = current_user.id
#reservation.user_id = #user
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reservations/1
# PATCH/PUT /reservations/1.json
def update
respond_to do |format|
if #reservation.update(reservation_params)
format.html { redirect_to #reservation, notice: 'Reservation was successfully updated.' }
format.json { render :show, status: :ok, location: #reservation }
else
format.html { render :edit }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reservations/1
# DELETE /reservations/1.json
def destroy
#reservation.destroy
respond_to do |format|
format.html { redirect_to reservations_url, notice: 'Reservation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reservation
#reservation = Reservation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:eventdate)
end
end
Space controller file:
class SpacesController < ApplicationController
before_action :set_space, only: [:show, :edit, :update, :destroy]
# GET /spaces
# GET /spaces.json
def index
#spaces = Space.all
end
# GET /spaces/1
# GET /spaces/1.json
def show
end
# GET /spaces/new
def new
#space = Space.new
end
# GET /spaces/1/edit
def edit
end
# POST /spaces
# POST /spaces.json
def create
#space = Space.new(space_params)
respond_to do |format|
if #space.save
format.html { redirect_to #space, notice: 'Space was successfully created.' }
format.json { render :show, status: :created, location: #space }
else
format.html { render :new }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /spaces/1
# PATCH/PUT /spaces/1.json
def update
respond_to do |format|
if #space.update(space_params)
format.html { redirect_to #space, notice: 'Space was successfully updated.' }
format.json { render :show, status: :ok, location: #space }
else
format.html { render :edit }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# DELETE /spaces/1
# DELETE /spaces/1.json
def destroy
#space.destroy
respond_to do |format|
format.html { redirect_to spaces_url, notice: 'Space was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_space
#space = Space.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def space_params
params.require(:space).permit(:name)
end
end
And full Reservation Form:
<%= form_for(#reservation) do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :eventdate %><br>
<%= f.date_select :eventdate %>
</div>
<div class="field">
<%= #user = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user, :id, :name), :prompt => "Select space"
%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pretty sure you need to permit the space_id attribute in your strong params.
def reservation_params
params.require(:reservation).permit(:eventdate, :space_id)
end
whats happening is that when you go to create a reservation, youre passing in set of params, that is the output of reservation_params
#reservation = Reservation.new(reservation_params)
if space_id is not being permitted in your strong params, then it will be nil when created.
if this is not the issue, can you post what params are getting to the server, and what the output of reservation_params are.
Im creating a garden app that has trays and plants.
tray has_many plants, plant belongs_to tray etc.
Im getting the above error and Im not sure how to assign the tray_id to the new plant being created.
Here is the add plant button in my tray's show view
<%= link_to 'ADD PLANT', new_plant_path(#tray.id), class: "btn btn-raised btn-success hoverable" %>
Here is my plants_controller:
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
# GET /plants
# GET /plants.json
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my trays controller
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my form for creating new plants
<%= form_for(#plant) do |f| %>
<%= f.label 'NAME' %>
<%= f.text_field :title, class: 'form-control', id: 'focusedInput1', placeholder: 'ENTER NAME' %>
etc, etc
<% end %>
What am I doing wrong? Thanks for the help :)
The params[:tray_id] is nil on this line tray = Tray.find(params[:tray_id]) in your Posts controller.
You're also not passing tray_id anywhere in your params. You'll need to properly pass it as a param to your new action:
<%= link_to 'ADD PLANT', new_plant_path(tray_id: #tray.id), class: "btn btn-raised btn-success hoverable" %>
Then add a hidden field to pass :tray_id in your form:
<%= f.hidden_field :tray_id, value: params[:tray_id] %>
Now, you can find tray in your create action using tray = Tray.find(params[:plant][:tray_id]).
I ran into a very strange bug in my Rails app: Whenever I try to submit a form I get the error No route matches [PATCH] "/business_cases" (in this case). But after clicking the "Back"-Button in my Browser and filling out + submitting again, it works fine. As this error appears not only in this specific model but almost every other I'm quite lost.. Here is the example.
routes:
business_cases GET /business_cases(.:format) business_cases#index
POST /business_cases(.:format) business_cases#create
new_business_case GET /business_cases/new(.:format) business_cases#new
edit_business_case GET /business_cases/:id/edit(.:format) business_cases#edit
business_case GET /business_cases/:id(.:format) business_cases#show
PATCH /business_cases/:id(.:format) business_cases#update
PUT /business_cases/:id(.:format) business_cases#update
DELETE /business_cases/:id(.:format) business_cases#destroy
routes.rb:
root 'dashboards#index'
get "index" => "pages#index"
resources :users, :orders, :sales, :business_cases
controller (FYI: I use cancancan):
class BusinessCasesController < ApplicationController
load_and_authorize_resource
before_action :authenticate_user!
def index
end
def show
end
def new
end
def edit
end
def create
respond_to do |format|
if #business_case.save
format.html { redirect_to business_cases_url, notice: 'Business case was successfully created.' }
format.json { render :show, status: :created, location: #business_case }
else
format.html { render :new }
format.json { render json: #business_case.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #business_case.update(business_case_params)
format.html { redirect_to business_cases_url, notice: 'Business case was successfully updated.' }
format.json { render :show, status: :ok, location: #business_case }
else
format.html { render :edit }
format.json { render json: #business_case.errors, status: :unprocessable_entity }
end
end
end
def destroy
#business_case.destroy
respond_to do |format|
format.html { redirect_to business_cases_url, notice: 'Business case was successfully destroyed.' }
format.json { head :no_content }
end
end
model:
class BusinessCase < ActiveRecord::Base
validates :name, :description, :presence => true
end
form (shorten):
<%= form_for #business_case, html: { multipart: true } do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control", placeholder: "X-Sell" %>
</div>
<% end %>
I have a problem with simple form it doesn’t highlight field where error is raised.
search_controller.rb
class SearchesController < ApplicationController
before_action :set_search, only: [:show, :edit, :update, :destroy]
layout 'admin'
def index
#searches = Search.includes(:brand, :search_index, :price_ranges)
end
def show
end
def new
#search = Search.new
end
def edit
end
def create
#search = Search.new(search_params)
respond_to do |format|
if #search.save
format.html { redirect_to #search, notice: 'Search was successfully created.' }
format.json { render :show, status: :created, location: #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #search.update(search_params)
format.html { redirect_to searches_url, notice: 'Search was successfully updated.' }
format.json { render :show, status: :ok, location: #search }
else
format.html { render :edit }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def destroy
#search.destroy
respond_to do |format|
format.html { redirect_to searches_url, notice: 'Search was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_search
#search = Search.find(params[:id])
end
def search_params
params.require(:search).permit(:brand_id)
end
end
search.rb
class Search < ActiveRecord::Base
validates_presence_of :brand
_form.html.erb
<%= simple_form_for(#search) do |f| %>
<%= f.error_notification %>
<%= f.input :brand_id, collection: Brand.all.order(:name), prompt: 'Select brand' %>
<% end %>
I want brand field be hihlighted the same way keywords field is.
I've checked if validates_presence_of brand raise the error and it dose, but doesn’t highlight the field.
I'm new to rails and am having a bit of trouble. I am getting an
undefined local variable or method `answer'
error in my _answer.html.erb partial.
Here is 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
def update
respond_to do |format|
if #answer.update(answer_params)
format.html { redirect_to #answer, notice: 'Answer was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
def destroy
#answer.destroy
respond_to do |format|
format.html { redirect_to answers_url }
format.json { head :no_content }
end
end
and my _answer.html.erb file:
<%=div_for(answer) do %>
<div class="questioncontainer">
<p>
<%= answer.body %>
</p>
</div>
<% end %>
If it matters, my resources :answers is nested in resources :questions.
I appreciate any help!
Try using div_for(#answer) instead of answer. When you're communicating between controllers and views, you always do so with #variables. Maybe you should take some time and read this: http://guides.rubyonrails.org/layouts_and_rendering.html