在我的Rails API中,我的Child模型中包含以下代码:
before_create :delete_error_from_values, :check_errors, :update_child_if_exists
def delete_error_from_values
@new_error = self.values["error"]
@values = self.values.tap { |hs| hs.delete("error") }
end
def update_child_if_exists
conditions = {type: self.type, parent_id: self.parent_id}
if existing_child = Child.find_by(conditions)
new_values = existing_child.values.reverse_merge!(@values)
hash = {:values => new_values}
existing_child.update_attributes(hash)
end
end
def check_errors
if self.type == "error"
conditions = {type: self.type, parent_id: self.parent_id}
if existing_child = Child.find_by(conditions)
bd_errors = existing_child.error_summary
bd_errors[@new_error] = bd_errors[@new_error].to_i + 1
hash = {:error_summary => bd_errors}
existing_child.update_attributes(hash)
else
self.error_summary = {@new_error => 1}
end
end
end
除了一个小细节之外,它的工作方式与预期相同:如果类型和parent_id的记录已经存在,则会更新子级,但也会创建它。我怎样才能重构这个以阻止创作呢?
我已尝试加入return false
,但如果我这样做,则更新失败。
我希望有find_or_create_by
之类的内容,但我不确定如何在这种情况下使用它。
答案 0 :(得分:1)
您可以按照以下方法重构代码:
def create
@parent = Parent.find(params[:parent_id])
existing_child = Child.where(type: child_params[:type], parent_id:
child_params[:parent_id]).first
if existing_child.present?
existing_child.update_attributes(attribute: value_1)
else
@child = @parent.child.build(child_params)
end
#other saving related code goes here.
end
这只是一个基本的例子。 尝试创建单独的实例方法以保持Contrller DRY。 :)