I have two models: RegisterHour and Employee
This is my model RegisterHour:
class RegisterHour < ApplicationRecord
belongs_to :employee, class_name: 'Employee', foreign_key: 'employee_id'
end
And this my model: Employee
class Employee < ApplicationRecord
has_many :register_hours, dependent: :destroy
end
The mapping of my routes for this case
resources :employees do
resources :register_hours
end
This my controller:
class RegisterHoursController < ApplicationController
before_action :set_employee
before_action :set_hour, :set_employee_hour
def index
json_response(@employee.register_hours)
end
private
def set_hour
@register_hour = RegisterHour.find(params[:id])
end
def set_employee
@employee = Employee.find(params[:employee_id])
end
def set_employee_hour
@register_hour = @employee.register_hours.find_by(id: params[:id]) if @employee
end
def hour_params
params.permit(:status)
end
end
So, when I run the route: http://my_url_in_local/employees/1/register_hours I got this error:
{
"message": "Couldn't find RegisterHour without an ID"
}
I'm sooo confused because I have another controller with the same structure to manage admins and employees, and it works, but this controller don't.
I'm newbie with rails that's my confusion, if anyone can help me to understand what I'm doing wrong I gonna be super happy :)
Thank you!!
Looking to how your routes are defined, you have something like this:
employee_register_hours GET /employees/:employee_id/register_hours(.:format) register_hours#index
POST /employees/:employee_id/register_hours(.:format) register_hours#create
employee_register_hour GET /employees/:employee_id/register_hours/:id(.:format) register_hours#show
PATCH /employees/:employee_id/register_hours/:id(.:format) register_hours#update
PUT /employees/:employee_id/register_hours/:id(.:format) register_hours#update
DELETE /employees/:employee_id/register_hours/:id(.:format) register_hours#destroy
employees GET /employees(.:format) employees#index
POST /employees(.:format) employees#create
employee GET /employees/:id(.:format) employees#show
PATCH /employees/:id(.:format) employees#update
PUT /employees/:id(.:format) employees#update
DELETE /employees/:id(.:format) employees#destroy
If you see there, the URI routing the index action in RegisterHoursController only states that an employee_id
in the params is expected. But in your private set_hour
method, you're expecting that the params contain an id
corresponding to an existing RecordHour record in your database:
RegisterHour.find(params[:id])
There's where your error is happening. As you're not sending that id, find is raising a ActiveRecord::RecordNotFound
error.
You have a simple solution, that's to remove that method and everything related to it. So, your RegisterHoursController would end up in something much more simple:
class RegisterHoursController < ApplicationController
def index
@employee = Employee.find(params[:employee_id])
json_response(@employee.register_hours)
end
private
def hour_params
params.permit(:status)
end
end
Why? As you don't receive a RegisterHour id, then set_hour
isn't necessary, this way set_employee_hour
also becomes unnecessary, because @employee.register_hours.find_by(id: params[:id])
is always going to return nil
.
Removing that, you end up with set_employee, which can be just moved to the action where it belongs, allowing you to remove the before_action
callback.
Notice, if you're using only the index action in RegisterHoursController, then you can avoid generating all other unneeded routes:
resources :employees do
resources :register_hours, only: :index
end