可以委託查詢到BasicObject
該代理ActiveRecord::Relation
。
class QueryDelegator < BasicObject
def initialize(target)
@target = target
end
def method_missing(*args, &block)
result = target.send(*args, &block)
@target = result if result.kind_of? @target.class
result
end
end
這裏發生的事情是,你是進行代理的方法調用你的委託方與該調用返回範圍ActiveRecord的::關係。然後,如果您的代理正在返回ActiveRecord :: Relations或其子類的方法,則會將該結果分配給委託目標。
然後,你會怎麼做:
@orders = QueryDelegator.new(Order.unscoped.dated)
@orders.search_for(params["search"]) if params["search"].present?
@orders.where(:items_received_status => true) if params[:air].present? && params[:air] == 't'
@orders.tagged_with(params[:tags]) if params[:tags].present?
或者你可以進一步重構,並做到:
class Order < ActiveRecord::Base
# ...
def self.search(params)
orders = query_builder(unscoped.dated)
orders.search_for(params["search"]) if params["search"].present?
orders.where(:items_received_status => true) if params[:air].present? && params[:air] == 't'
orders.tagged_with(params[:tags]) if params[:tags].present?
end
def self.query_builder(scope = nil)
scope ||= scoped
QueryDelegator.new(scope)
end
end
然後打電話給你的搜索結果在您的控制器像這樣:
Order.search(params)
瑞恩貝茨在這個模式上做了一個RailsCast。用於自己的危險。正如一些評論者所說,你可能只是爲了方便而犧牲可讀性。
你不喜歡那個代碼?看起來對我來說很好。 –