Ruby on Rails Отменить где пункт - PullRequest
0 голосов
/ 07 марта 2019

Это мой route.rb:

get 'people',         to: 'people#index'
get 'people/:person', to: 'people#person'

Это мой контроллер:

def index
  @result = People.complicated_stuff
                  .sum(:amount)

  # more queries without .where(person: p)
  # more code
end

def person
  p = params[:person]

  @result = People.complicated_stuff
                  .where(person: p)
                  .sum(:amount)

  # more queries with .where(person: p)
  # more code
end

Я бы хотел, чтобы этот код был более СУХИМ, потому что код тот же,кроме клаузулы.Так что я подумал о том, чтобы объединить два вместе в отдельный метод.Как я могу отменить все предложения where с помощью (Person: p)?Единственное, что я придумал, было:

def my_method(person: nil, select_all: true)
  if select_all
    p = People.distinct.pluck[:person]
  else
    p = person
  end

  @result = People.complicated_stuff
                  .where(person: p)
                  .sum(:amount)
end

Но это очень уродливый запрос.

Редактировать

Я только что обнаружил и эту работу, и я думаю, что этодостаточно хорошо для меня: я изменил мой route.rb, чтобы оба перешли к «people # index».И в моем контроллере:

def index
  @p = params[:person]
  person = @p.nil? ? "" : "people.person = ?"

  @result = People.complicated_stuff
                  .where(person, @p)
                  .sum(:amount)
end

Я никогда не знал, что это сработало.

1 Ответ

0 голосов
/ 07 марта 2019

Вы можете разбить область запроса на частный метод на вашем контроллере.Вот пример того, как это может выглядеть:

# frozen_string_literal: true

class PeopleController < ApplicationController

  def index 
    result
  end

  def people
    result
  end

  private

  def people_scope
    @people_scope ||= People.complicated_stuff
  end

  def person_scope
    # Depending on your use-case, it may make sense to memoize this
    person_id = params[:person]
    people_scope.where(person: person_id)
  end

  def result
    # If you want a one-liner, you could do this:
    # @result ||= params[:person] ? person_scope.sum(:amount) : people_scope.sum(:amount)
    # Personally, I like the readability and ease of debugging of the if/else statement
    @result ||= if params[:person]
                  person_scope.sum(:amount)
                else
                  people_scope.sum(:amount)
                end
  end
end

Это всего лишь один способ немного высушить контроллер.Вы могли бы пойти так далеко, чтобы позвонить result в before_action.Однако я бы предостерег от этого.ИМО, читаемый код с низкими когнитивными издержками лучше, чем 100% СУХОЙ код.

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