I am new to RoR and I am having trouble with a simple_form with nested resources.
I have 2 models: Interview & Practice. The Interview has_many practices and practices belong_to Interview.
I am having Action Controller error (undefined method `practices_path' for #<#Class:0x00007fda24ed79d8:0x00007fda24ed5fe8>) when trying to create new practices within the interview_id using simple_form ie. at this route: /interviews/:interview_id/practices/new)
Can anyone help identify what I am doing wrong? Thank you so much in advance.
Controllers
class PracticesController < ApplicationController
def index
@practices = Practice.all
end
def new
@practice = Practice.new
end
def create
@interview = Interview.find(params[:interview_id])
@practice = Practice.new(practice_params)
@practice.interview = @interview
if @practice.save
redirect_to new_interview_practice_path(@interview)
else
render 'new'
end
end
# def destroy
# @interview = Interview.find(params[:id])
# @question.interview = @interview
# @question.destroy
# redirect_to interview_questions_path(@interview)
private
def practice_params
params.require(:practice).permit(:question, :type, :title)
end
end
class InterviewsController < ApplicationController
def index
@interviews = Interview.all
end
def new
@interview = Interview.new
end
def create
@interview = Interview.new(interview_params)
@interview.user = current_user
if @interview.save
redirect_to interview_path(@interview)
end
end
def show
@interview = Interview.find(params[:id])
@question = Question.new
end
def destroy
@interview = Interview.find(params[:id])
@interview.destroy
redirect_to interviews_path
end
private
def interview_params
params.require(:interview).permit(:company, :industry, :photo)
end
end
Models
class Interview < ApplicationRecord
belongs_to :user
has_many :videos, dependent: :destroy
has_many :questions, dependent: :destroy
has_many :practices, dependent: :destroy
validates :company, :industry, presence: true
has_one_attached :photo
def days_remaining
-(Date.today - self.final_date.to_date).to_i if self.final_date
end
include PgSearch::Model
pg_search_scope :search_by_name_and_date,
against: [:name, :open_date, :final_date, :company],
using: {
tsearch: { prefix: true }
}
end
class Practice < ApplicationRecord
belongs_to :interview
has_many :questions, through: :interviews
end
View
<br>
<div class="text-center">
<h3>Lets create a new practice interview!</h3>
</div>
<div class="form-container">
<%= simple_form_for [@interview, @practice] do |f| %>
<div class="flex-container2">
<div class="form-style-5">
<legend><span class="number">1</span> Job Info</legend>
<%= f.input :title, placeholder: "give it a name"%>
<%= f.input :type, placeholder: "Competency"%>
<%= f.input :question, placeholder: "add here" %>
</div>
</div>
<div class="row d-flex justify-content-center mb-5">
<div class="col-md-7">
<%= f.submit class: "btn btn-primary"%>
</div>
</div>
<% end %>
</div>
Routes
Rails.application.routes.draw do
devise_for :users
root to: 'pages#home'
get 'dashboard', to: 'users#dashboard'
get 'calendar', to: 'pages#calendar'
get 'video', to: 'pages#video'
get 'settings', to: 'pages#settings'
post 'sendsms', to: 'videos#send_sms'
resources :interviews, only: [:index, :new, :create, :show, :destroy] do
resources :questions, only: [:index, :new, :create, :show]
resources :practices, only: [:index, :new, :create, :show, :destroy]
resources :videos, only: [:index, :new, :create, :show] do
resources :reviews, only: [:new, :create]
end
end
resources :candidates, only: [:create, :new, :show]
resources :searches
get 'thank_you', to: 'videos#thank_you'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
Schema
create_table "interviews", force: :cascade do |t|
t.datetime "open_date"
t.datetime "final_date"
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "name"
t.string "company"
t.string "industry"
t.index ["user_id"], name: "index_interviews_on_user_id"
end
create_table "practices", force: :cascade do |t|
t.string "title"
t.string "type"
t.text "question"
t.bigint "interview_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["interview_id"], name: "index_practices_on_interview_id"
end
The strange
Action Controller error (undefined method `practices_path' for #<#Class:0x00007fda24ed79d8:0x00007fda24ed5fe8>)
error just means that Rails is trying to get the path for [@interview, @practice]
(that you're using in your view) but @interview is empty or nil, so the default path for creating a record (in this case @practice) would be practices_path
(the form would be a post to /practices).
What you want is simple_form_for
to use interviews_practices_path
which will convert to /interviews/:interview_id/practices.
In your PracticesController
action new
you also need to initialize a new @interview
variable, since you're using that in the view.
Since your Practice model is nested, this means that when you go to /interviews/:interview_id/practices/new
your ID will be coming from the URL, and is available in params[:interview_id]
.
So, a simple solution would be to add:
def new
@interview = Interview.find(params[:interview_id]
@practice = Practice.new
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.