2014-06-26 34 views
1

我這樣做紅寶石附加的方法來不斷動態 - 需要更好的方式來做到這一點

@orders = Order.unscoped.dated 
    @orders = @orders.search_for(params["search"]) if params["search"].present? 
    @orders = @orders.where(:items_received_status => true) if params[:air].present? && params[:air] == 't' 
    @orders = @orders.tagged_with(params[:tags])   if params[:tags].present? 

有沒有更好的方式來寫相同的代碼

@orders = Order do 
    self.where(some condition) 
    self.joins(some table) 
end 

有應該是避免重複賦值運算符的一種方法

+1

你不喜歡那個代碼?看起來對我來說很好。 –

回答

0

您可以做類似於秒。它本質上是相同的代碼,但它更整潔,因爲邏輯不混淆正在做什麼:

@orders = build_orders 

... 

# In pure ruby, this is fine as a private method. 
# In rails, it would be better to have this method in the `Order` model, 
# perhaps split up as separate methods as Sergey Moiseev mentions. 

private 

def build_orders 
    orders = Order.unscoped.dated 
    orders = orders.search_for(params["search"])   if params["search"].present? 
    orders = orders.where(:items_received_status => true) if params[:air].present? && params[:air] == 't' 
    orders = orders.tagged_with(params[:tags])   if params[:tags].present? 

    orders 
end 
1

我認爲這樣做最簡單的方法是創建這個模型方法:

class Order 
    def self.air(air) 
    return self.where(items_received_status: true) if air == 't' 
    self 
    end 

    def search(search... 

這樣你就可以在控制器鏈中這樣說:

Order.unscoped.dated.air(params[:air]).seach(... 
0

可以委託查詢到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。用於自己的危險。正如一些評論者所說,你可能只是爲了方便而犧牲可讀性。

相關問題