灵活的系统可以批量销毁每条记录

时间:2019-02-22 13:46:47

标签: ruby-on-rails ruby

client_skipped_day_controller.rb

class ClientSkippedDaysController < ApplicationController
  before_action :check_client_on_exist, only: [:create]

  def index
    @client_skipped_days = ClientSkippedDay.order_by(params[:sort_by], params[:direction])

    if params[:date].present?
      @client_skipped_days = @client_skipped_days.where('skipped_at = ?', Date.parse(params[:date]))
    end

    render json: @client_skipped_days, status: :ok
  end

  def create
    @client_skipped_days = ClientSkippedDay.create!(client_skipped_days_params)

    render json: @client_skipped_days, status: :created
  end

  def destroy

  end

  private

  def client_skipped_days_params
    params.permit(client_skipped_days: %i[client_id skipped_at])[:client_skipped_days]
  end

  def check_client_on_exist
    client_skipped_days_params.each do |day|
      ClientSkippedDay.find_by(day)&.destroy
    end
  end
end

如果我尝试仅删除一条记录(例如:

),我的代码将起作用
Parameters: {"client_skipped_days"=>[{"client_id"=>533, "skipped_at"=>"2019-02-24"}], "client_skipped_day"=>{}}

但是,如果我尝试删除数组中的每个哈希,那是行不通的:(

Parameters: {"client_skipped_days"=>[{"client_id"=>533, "skipped_at"=>"2019-02-24"}, {"client_id"=>512, "skipped_at"=>"2019-02-24"}], "client_skipped_day"=>{}}

将仅删除一条记录,但是如何添加删除所有记录的功能?与控制器的参数一致?

它必须是一个灵活的系统,可以删除数组中是否包含1个哈希,并立即删除数组中的哈希集合。告诉我怎么做。

2 个答案:

答案 0 :(得分:1)

您需要遍历数组,而不仅仅是从数组中取出第一个值。我不了解您拥有的参数,因此假设您要使用find_byclient_id的哈希值来完成skipped_at

此外,Ruby 2.3.0引入了安全导航运算符,如果您不习惯&.的话,这就是它。 http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

由于find_by返回ActiveRecord对象或返回nil,因此现在是使用安全导航运算符缩短时间的绝佳时机。

  def client_skipped_days_params
    params.permit(client_skipped_days: %i[client_id skipped_at])[:client_skipped_days]
  end

  def check_client_on_exist
    client_skipped_days_params.each do |day|
      ClientSkippedDay.find_by(day)&.destroy
    end
  end

注意,我不确定您的client_skipped_day哈希是多少。我认为您可以删除一天或批量删除。我警告不要让它做两件事。只需使客户端始终为此操作发送一个数组,事情对您来说将变得更容易。如果可以这样做,则可以使client_skipped_days为必需。

  def client_skipped_days_params
    params.require(:client_skipped_days).permit(%i[client_id skipped_at])
  end

如果客户端不提供client_skipped_days密钥,则会向客户端引发422错误。

如果这不可能,那么您需要向if添加check_on_exist以确保client_skipped_days_params不为空(因为他们使用的是{{1 }}。

答案 1 :(得分:1)

您可以考虑使用多个#where查询,而不是遍历params并逐个查找每条记录,而将它们与#or结合使用,并遍历结果记录

def client_skipped_days_params
  params.permit(client_skipped_days: [:client_id, :skipped_at])
  #                                           removed `.values` ^
end

def check_client_on_exist
  destroyed_records, undestroyed_records =
    client_skipped_days_params
    .fetch(:client_skipped_days, []) # get the array or use an empty array as default
    .map(&ClientSkippedDay.method(:where)) # build individual queries
    .reduce(ClientSkippedDay.none, :or) # stitch the queries together using #or
    .partition(&:destroy) # call #destroy on each item in the collection, separating destroyed once from undestroyed once
end

在上面的示例中,生成的销毁记录存在于destroyed_records变量中,而无法销毁的记录存在于undestroyed_records变量中。如果您不关心结果,则可以将其省略。如果您想在无法销毁记录的情况下引发异常,请改用#destroy!(调用每个收集项)。

或者,您可以通过调用#destroy_all(在集合上调用)销毁所有记录,但是它只会返回一个记录数组,而不会将销毁的记录与未销毁的记录区分开。该方法仍将实例化记录并逐个销毁它们,其优点是仍会触发回调。

更快的选项是调用#delete_all(在集合上调用)。这将用一个查询破坏所有记录。 但是销毁记录时不会实例化,这意味着将不会触发回调。

def check_client_on_exist
  destroyed_record_count = 
    # ...
    .reduce(ClientSkippedDay.none, :or)
    .delete_all # delete all records with a single query (without instantiation)
end

引用: