гибкая система уничтожения каждой записи в партии - PullRequest
0 голосов
/ 22 февраля 2019

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 голосов
/ 22 февраля 2019

Вместо зацикливания на params и нахождения каждой записи по одной вы также можете рассмотреть возможность использования нескольких #where запросов, объединяющих их вместе с использованием #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

ссылки:

0 голосов
/ 22 февраля 2019

Вам нужно перебрать свой массив вместо того, чтобы просто брать из него первое значение.Я не понимаю, какие параметры у вас есть, поэтому я предполагаю, что вы хотите сделать свои find_by, используя хэш client_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

Это вызовет ошибку 422 для клиента, если он не предоставит ключ client_skipped_days.

Если это невозможно, вам нужно добавить if к check_on_exist, чтобы убедиться, что client_skipped_days_params не равно нулю (потому что они используют client_skipped_day).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...