如何列出所有父对象的所有子对象?

How to list all child objects for all 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

我想列出所有父对象的所有子对象。

我想,我将不得不如下修改路线

routes.rb

Rails.application.routes.draw do
  root 'customers#index'

  resources :customers do
    resources :bookings
  end
  resources :bookings
end

我还需要修改bookings_controller.rb

  1. 注释掉before_action :set_customer行,否则我会得到类似Couldn't find Customer without an ID

  2. 的错误
  3. 我必须为除 index 之外的所有方法添加 @customer = Customer.find(params[:customer_id])。这意味着我不会遵循 DRY 概念...

还有其他更好的方法来解决这个问题吗?

我认为你的方法已经是最好的了,只需要正确使用 Rails 助手来保持你的代码干燥。

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...

不,您不必这样做。

如果 customers/bookings_controllerindex 操作未在其他任何地方使用,则只需从控制器文件中删除该操作并在路由文件中指定相同的操作:

resources :customers do
  resources :bookings, except: :index
end

如果 index 动作仍在其他地方使用,那么 Rails 回调可以使用 except 选项声明如下,以指定 set_customer 将被调用除 index.

之外的所有操作
before_action :set_customer, except: :index

有关 Rails 控制器回调选项的更多信息 here

您可能需要检查的其他要点:

  1. dependent: :delete_all。有了这个,当你删除 customer 时,你的数据库中将有孤立的 active_storage_attachments 记录。因为当保留这些预订的 attached images 不变时,它会触发仅删除关联的 bookings 的回调。 Reference
  2. resources :bookings (last line of your route file)。如果控制器中只有 index 操作,则应在此处声明与 resources :bookings, only: :index
  3. 相同的操作