我有卡车和乘员组模型,卡车has_many :crews
。在复选框的前端,我选择卡车ID并将其发送到我的控制器。我只需要销毁没有人员的卡车。我现在所拥有的:
# app/models/truck.rb
belongs_to :company
has_many :crews
# app/models/crew.rb
belongs_to :truck, optional: true
# trucks_controller.rb
def bulk_destroy
trucks_with_crews = []
current_company.trucks.where(id: params[:ids]).find_each do |truck|
if truck.crews.exists?
trucks_with_crews << truck
next
end
truck.destroy
end
if trucks_with_crews.empty?
head :no_content
else
message = []
trucks_with_crews.each_with_object([]) { |x| message << x.name }
render json: { message: "Trucks: '#{message.join(', ')}' can't be deleted because used by crews." }, status: :unprocessable_entity
end
end
但是它非常复杂,我想在查询中使其更好。有人可以帮助我吗?
我认为应该是这样的
我不知道该怎么做:
a = current_company.trucks.where(id: params[:ids])
b = current_company.trucks.includes(:crews).where(truck.crews.map(&:id))
a = a - b
希望您能理解我的意思。谢谢:)
答案 0 :(得分:1)
首先,您可以为“卡车”型号添加限制,以免意外删除有工作人员的卡车
has_many :crews, dependent: :restrict_with_exception
让我们重构您的控制器代码:
def bulk_destroy
# let find truck which should be deleted
trucks_wo_crew = current_company.trucks.includes(:crews)
.where(id: params[:ids]).where(crews: { id: nil })
# and delete them
trucks_wo_crew.destroy_all
# if we search by id after deletion we'll get trucks with crew,
# because we already deleted other.
# We can get only names, since we don't need other info
trucks_with_crew = current_company.trucks.where(id: params[:ids]).pluck(:name)
return head :no_content if trucks_with_crew.empty?
render json: { message: "Trucks: '#{trucks_with_crew.join(', ')}' can't be deleted because used by crews." }, status: :unprocessable_entity
end