Reputation: 5854
What I have at the moment is pretty standard set of code, where all child objects can be list under only their parent objects.
customer.rb
class Customer < ApplicationRecord
has_many :bookings, dependent: :delete_all
end
booking.rb
class Booking < ApplicationRecord
belongs_to :customer
has_many_attached :images
end
routes.rb
Rails.application.routes.draw do
resources :customers do
resources :bookings
end
end
bookings_controller.rb
This has been automatically generated. I only removed comments and json related lines.
class BookingsController < ApplicationController
before_action :set_customer
before_action :set_booking, only: %i[show edit update destroy]
def index
@bookings = Booking.all.with_attached_images
end
def show; end
def new
@booking = @customer.bookings.build
end
def edit; end
def create
@booking = @customer.bookings.build(booking_params)
respond_to do |format|
if @booking.save
format.html { redirect_to @customer, notice: 'Booking was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if @booking.update(booking_params)
format.html { redirect_to [@customer, @booking], notice: 'Booking was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
@booking.destroy
respond_to do |format|
format.html { redirect_to customer_bookings_url, notice: 'Booking was successfully destroyed.' }
end
end
private
def set_customer
@customer = Customer.find(params[:customer_id])
end
def set_booking
@booking = @customer.bookings.find(params[:id])
end
def booking_params
params.require(:booking).permit(:name, :category, :rooms, :wifi, :phone, :address, :description, :available, :check_in, :check_out, :customer_id, images: [])
end
end
I want to list all child objects for all parent objects.
I guess, I will have to modify routes as follows
routes.rb
Rails.application.routes.draw do
root 'customers#index'
resources :customers do
resources :bookings
end
resources :bookings
end
I will also need to modify bookings_controller.rb
By commenting out the line before_action :set_customer
, otherwise I will get an error like Couldn't find Customer without an ID
And I will have to put @customer = Customer.find(params[:customer_id])
for all methods except index
. Which means I won't be following DRY concept...
Any other better approach to solve this?
Upvotes: 0
Views: 694
Reputation: 841
Your approach is the best already in my opinion, just need to utilize Rails helpers correctly to keep your code DRY.
By commenting out the line before_action :set_customer, otherwise I will get an error like Couldn't find Customer without an ID
And I will have to put @customer = Customer.find(params[:customer_id]) for all methods except index. Which means I won't be following DRY concept...
NO you don't have to.
If the index
action of customers/bookings_controller
is not used anywhere else then just remove that action from the controller file and specify the same in the route file as:
resources :customers do
resources :bookings, except: :index
end
If the index
action is still being used in other places then Rails callbacks can be declared with except
option as below to specify that the set_customer
will be called for all actions except the index
.
before_action :set_customer, except: :index
More about Rails Controller Callback options here
Other points that you may want to check:
dependent: :delete_all
. With this, there will be orphan active_storage_attachments
records in your db when you delete a customer
. Because it triggers the callback that deletes only the associated bookings
when leave the attached images
of those bookings untouched. Referenceresources :bookings (last line of your route file)
. If you only have the index
action in the controller, you should declare the same here also as resources :bookings, only: :index
Upvotes: 1