Rails 6中匹配现有address记录后创建新delivery的实现问题
现有代码核心问题
- 控制器
confirm_address回调仅查询了地址,查询失败时没有终止请求返回错误,查询成功后也没有将找到的地址关联到待创建的delivery实例 - 模型层无法直接访问控制器层的
params对象,before_validation回调逻辑完全无法生效,且查询字段street和请求参数的street_name不匹配 delivery关联address默认必填,创建时没有传入address_id必然会触发校验失败,且模型上额外添加的地址类属性完全冗余,不需要在delivery表存储地址字段
修正后的实现代码
1. 控制器代码
class DeliveriesController < ApplicationController before_action :confirm_address, only: %i[ create edit update ] protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? } def index render json: Delivery.all end def create # 直接用查到的地址创建关联的delivery,自动填充address_id delivery = @confirmed_address.deliveries.new(delivery_params) if delivery.save render json: {status: 'Awesome!', data: delivery}, status: :ok else render json: {status: 'Boo!', data: delivery.errors}, status: :unprocessable_entity end end private def delivery_params # 地址参数仅用于匹配地址,不需要存入delivery,只允许业务字段company即可 params.permit(:company) end def confirm_address @confirmed_address = Address.find_by( numeric: params[:numeric], street_name: params[:street_name], city: params[:city], state: params[:state], zip: params[:zip] ) unless @confirmed_address.present? # 地址匹配失败直接返回错误,终止后续请求流程 render json: {status: 'error', message: '匹配地址失败'}, status: :unprocessable_entity end end end
2. 模型代码
class Delivery < ApplicationRecord belongs_to :address # 删除所有冗余的地址属性和before_validation回调即可 end
逻辑说明
请求触发create动作前会先执行confirm_address校验:
- 地址匹配失败:直接返回错误响应,不会执行后续创建逻辑
- 地址匹配成功:用匹配到的
@confirmed_address关联创建delivery,自动填充关联的address_id,满足belongs_to必填校验,正常走保存流程即可
内容的提问来源于stack exchange,提问作者PSCampbell
相关产品推荐
相关产品推荐

