両方の関連付けられたテーブルに多くのフィールドを含む has_many アソシエーションの accepts_nested_attributes_for のパラメータを処理する方法
概要
建物モデルと has_many の関連付けを持つユーザー モデルがあります。最初は user.create と user.buildings.create を使用してユーザーと建物を別々に作成していました。テーブルにそのフィールドが true の場合にのみ建物を作成するようなフィールドがあり、建物には次の条件もありました。建物内の条件付きフィールドが true の場合、より多くのフィールド データが建物に追加されます。ユーザーが単一の建物を作成するまでは、すべてがスムーズに実行されていました。しかし、ユーザーがさらに建物を作成し始めると、コードがバーストしてしまいます。 以下は users_controller のコードです
def create
role = Role.find_by(id: params[:user][:role_id])
if role.nil?
render json: { error: 'invalid role' }, status: :unprocessable_entity
else
user = User.new(user_params)
user.role_id = role.id
ActiveRecord::Base.transaction do
if user.save
# If the user is a technician, handle equipment_params
if role.name.downcase == 'technician'
equipment_ids = params[:user][:equipment_id]
handle_technician_params(user, equipment_ids)
end
# If the user is a customer, handle customer_params
if role.name.downcase == 'customer'
handle_customer_params(user)
end
# Generate a new authentication token for the user
token, refresh_token = generate_tokens(user.id)
render json: { message: 'User created successfully', authentication_token: token, user: user, meta: {photos: UserSerializer.new(user) }}, status: :ok
else
render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
end
end
end
end
def handle_customer_params(user)
if user_params[:is_customer_direct_point_of_contact] == 'true'
handle_building_params(user)
else
handle_service_params(user)
end
end
def handle_building_params(user)
building_params = params.require(:building).permit(:service_address_line1, :service_address_line2, :service_zip_code, service_images: [])
building = user.buildings.create(building_params)
end
def handle_service_params(user)
service_params = params.require(:building).permit(:service_address_line1, :service_address_line2, :service_zip_code, :name, :phone_number, :email, :tax_id, service_images: [])
building = user.buildings.create(service_params)
end
ユーザーを直接作成してビルドするために accepts_nested_attributes_for を使用するように変更しようとしましたが、その方法がわかりませんでした。 それを行う他の方法もありますか?
解決策
ここでクリーンアップできる非常に基本的なものがたくさんあります。これらには、コントローラー (user.technician?) ではなくモデル内で実行する必要がある値のテストなどが含まれます。モデルメソッドである必要があります。しかし、あなたの特定の質問に答えるために:
アプリの機能を実験しないでください。テストを書くことでより優れたコーダーになり、コード ベースがより良くなり、反復してより速く学習できるようになります。
https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers
そして、高頻度の反復テストにはガードを使用することをお勧めします。 https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://github.com/guard/guard