Ruby on Rails撤消where子句

时间:2019-03-07 15:02:26

标签: ruby-on-rails

这是我的路线。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

我想让此代码更DRY,因为除了在哪里,代码是一样的。因此,我想到了将te结合在一起成为一种单独的方法。如何使用(Person:p)撤消所有where子句? 我想到的唯一一件事是:

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

但这给出了一个非常丑陋的查询。

编辑

我刚刚发现这也可行,我认为这对我已经足够了: 我更改了routes.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 :(得分:0)

您可以将查询范围划分为控制器上的私有方法。这是一个可能看起来像的例子:

# 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。但是,我对此表示警告。 IMO,具有较低认知开销的可读代码优于100%DRY代码。