有一个表单对象允许创建具有关联的对象。
这个主要问题是关联更新。我真的不知道如何在没有大量each
和条件的情况下扩展它。
扩展此类以更新对象的最方便方法是什么?
module Company
class JobForm
include ActiveModel::Model
attr_accessor :title, :body, :city, :start_date, :attachments,
:requirements, :company
attr_reader :object
validates :title, :body, :start_date, :city, presence: true
def save
persist! if valid?
end
private
def persist!
ActiveRecord::Base.transaction do
save_job
save_attachments
save_requirements
end
object
end
def save_job
@object = company.jobs.create(
# attributes.. ..)
end
def save_attachments
return unless attachments&.present?
attachments.each do |attacment_attributes|
object.attachments.create(attacment_attributes)
end
end
def save_requirements
return unless requirements&.present?
object.requirements.destroy_all
requirements.each do |requirement_attributes|
object.requirements.create(requirement_attributes)
end
end
end
end
答案 0 :(得分:1)
您询问了在自定义表单对象中实现更新的最便捷方式...但是自定义表单对象不是在Rails中使用表单的便捷方式。
有一些方便的宝石有助于构建复杂的形式。其中一个是reform
。查看Populator部分http://trailblazer.to/gems/reform/populator.html。
如果您使用收藏,通常您必须按正确的顺序手动匹配incomming params和相关对象,请查看以下示例
collection :songs,
populator: ->(fragment:, **) {
# find out if incoming song is already added.
item = songs.find { |song| song.id == fragment["id"].to_i }
item ? item : songs.append(Song.new)
}
如果您已经有关联模型 - 您从populator返回它,它将使用incomming参数进行更新。如果你没有它 - 你建立一个新模型,它将使用incomming参数创建...
答案 1 :(得分:1)
您可以利用质量赋值的功能,如果具有一对多关联的对象使用params哈希实例化,并且该哈希具有关联键,则Rails将调用<association_name>_attributes=
因此,您可以在表单对象类上定义该方法:
def attachments_attributes=(attributes)
@attachments ||= []
attributes.each do |_, attachment_params|
attachment = @attachments.find {|a| a.id.to_s == attachment_params[:id]}
attachment ? attachment.assign_attributes(document_params) : @attachments.push(Attachment.new(attachment_params))
end
end