Rails 5.1 API - индексный метод с фильтрами, нумерацией страниц и областями действия - как упростить - PullRequest
0 голосов
/ 24 марта 2019

У меня есть метод индексации в контроллере Rails API, который довольно ужасен, как вы можете видеть ниже.

Я уверен, что есть более Ruby или Rails способ написать это.

Действие поддерживает разбиение по страницам и фильтрацию (по параметру filter = query), а также может предоставить идентификатор клиента для ограничения того, что возвращается только предложениям, относящимся к предоставленному клиенту.

Интересно, может быть, мне следует отделитьфункциональность клиента для отдельной конечной точки?(например, клиенты /: идентификатор / предложения).Конечно, эта конечная точка также должна поддерживать пейджинг и фильтрацию, поэтому я думаю, что у меня может не получиться DRY-код.Есть ли способ (как в случае с проблемами), чтобы я мог упростить этот индексный код (т. Е. Без всех if...then...else)?

  def index
    if params[:page].present?
      page = params[:page]
      if params[:filter].present?
        if params[:customer_id].present?
          @proposals = current_user.retailer.proposals.customer(params[:customer_id]).search(params.slice(:filter)).page(page)
        else
          @proposals = current_user.retailer.proposals.search(params.slice(:filter)).page(page)
        end
      else
        if params[:customer_id].present?
          @proposals = current_user.retailer.proposals.customer(params[:customer_id]).page(page)
        else
          @proposals = current_user.retailer.proposals.page(page)
        end
      end
      render json: @proposals, root: 'proposals', meta: pagination_dict(@proposals)
    else
      render status: :bad_request, json: { message: "Please supply page parameter" }
    end
  end

Вот области действия модели Proposal:

  default_scope { order("updated_at DESC") }
  scope :filter, -> (term) { where("lower(first_name) || ' ' || lower(last_name) || ' ' || lower(email) LIKE ? OR qd_number::text LIKE ?", "%#{term.downcase}%", "%#{term}%") }  
  scope :customer, -> (customer_id) { where customer_id: customer_id }

1 Ответ

1 голос
/ 24 марта 2019

Я бы начал с чего-то вроде этого:

def index
  if params[:page].present?
    @proposals = current_user.retailer.proposals.page(params[:page])

    @proposals = @proposals.customer(params[:customer_id]) if params[:customer_id].present?
    @proposals = @proposals.search(params.slice(:filter))  if params[:filter].present?

    render json: @proposals, root: 'proposals', meta: pagination_dict(@proposals)
  else
    render status: :bad_request, json: { message: "Please supply page parameter" }
  end
end

Более того, вы можете обработать ошибку в before_action:

before_action :check_required_parameters, only: :index

def index
  @proposals = current_user.retailer.proposals.page(params[:page])

  @proposals = @proposals.customer(params[:customer_id]) if params[:customer_id].present?
  @proposals = @proposals.search(params.slice(:filter))  if params[:filter].present?

  render json: @proposals, root: 'proposals', meta: pagination_dict(@proposals)
end

private

def check_required_parameters
  return if params[:page].present?

  render status: :bad_request, json: { message: "Please supply page parameter" }
end

Или вы можете изменить свойОбласти для обработки пустых значений:

# in the model
scope :filter, -> (term) { where("lower(first_name) || ' ' || lower(last_name) || ' ' || lower(email) LIKE ? OR qd_number::text LIKE ?", "%#{term.downcase}%", "%#{term}%") if term.present? }  
scope :customer, -> (customer_id) { where(customer_id: customer_id) if customer_id.present? }

# in the controller
def index
  if params[:page].present?
    @proposals = current_user.retailer.proposals
      .customer(params[:customer_id])
      .search(params.slice(:filter))
      .page(params[:page])

    render json: @proposals, root: 'proposals', meta: pagination_dict(@proposals)
  else
    render status: :bad_request, json: { message: "Please supply page parameter" }
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...