问题描述
tldr:如何通过嵌套关联查找和更新或创建记录?
我有一个属于 Lead 模型的注册模型。当用户提交注册表时,通过嵌套属性创建潜在客户。这工作正常,但现在我需要更新注册,以便它创建一个新的潜在客户,或者如果该电子邮件中已经存在潜在客户,则查找并更新潜在客户。
注册.rb:
class Registration < ApplicationRecord
belongs_to :showing
belongs_to :lead
accepts_nested_attributes_for :lead
validates_associated :lead
end
lead.rb
class Lead < ApplicationRecord
belongs_to :account
has_many :registrations,dependent: :destroy
has_many :showings,through: :registrations
validates :name,:email,:phone,presence: true
end
registrations_controller.rb
class RegistrationsController < ApplicationController
before_action :set_account
def index
redirect_to new_showing_registration_path
end
def new
@registration = @showing.registrations.build
@lead = Lead.new
end
def create
@showing = Showing.find(params[:showing_id])
@registration = @showing.registrations.build(registration_params)
if @registration.save
redirect_to new_showing_registration_path,notice: 'Thank you for registering.'
else
render :new,status: :unprocessable_entity
end
end
def show
redirect_to new_showing_registration_path
end
def edit
@showing = Showing.find(params[:showing_id])
@registration = Registration.find(params[:id])
@account_id = @showing.listing.account.id.to_i
end
def update
@registration = Registration.find(params[:id])
if @registration.update(registration_params)
redirect_to new_showing_registration_path,notice: 'Thank you for registering.'
else
render :edit,status: :unprocessable_entity
end
end
private
def registration_params
params.require(:registration).permit(lead_attributes: [:account_id,:id,:name,:agent,:mortgage,:source])
end
def set_account
@showing = Showing.find(params[:showing_id])
@account_id = @showing.listing.account.id.to_i
end
end
解决方法
也许这个会有所帮助
https://stackoverflow.com/a/3580267/11544219
或者这个
https://dev.to/katkelly/why-yes-i-ll-accept-those-nested-attributes-18f7
class Registration < ApplicationRecord
belongs_to :showing
belongs_to :lead
accepts_nested_attributes_for :lead
validates_associated :lead
def autosave_associated_records_for_lead
existed_lead = Lead.find_by(registration: self)
if existed_lead.present?
existed_lead.update!(lead.attributes)
else
lead.save!
end
end
end
,
对于正在研究类似功能的其他人,这是我解决它的方法(如下)。最终,我选择使用回调而不是覆盖自动保存方法。在覆盖自动保存方法时,我在连接表中的父对象上设置嵌套对象 ID 时遇到了问题。所以,我采用了以下回调过程:
- 检查该电子邮件是否存在潜在客户
- 如果存在,则使用新的潜在客户属性更新现有潜在客户
- 将新潜在客户设置为更新后的现有潜在客户
- 如果线索不存在,则将新线索传回控制器进行创建
class Registration < ApplicationRecord
belongs_to :showing
belongs_to :lead
accepts_nested_attributes_for :lead,:reject_if => :all_blank,allow_destroy: true
before_validation :update_or_create_lead
private
def update_or_create_lead
existing = Lead.find_by(email: self.lead.email)
if existing
existing.update(
name: lead.name,phone: lead.phone,agent: lead.agent,mortgage: lead.mortgage,source: lead.source
)
self.lead = existing
else
self.lead
end
end
end