这是我的路线。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
我从不知道这样有用。
答案 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代码。