2015-12-15 49 views
0

我有一個方法select_active_buildings有三個參數,默認爲nil來使用提供的信息過濾我的數據庫。重構可選參數刪除`if`語句的方法

def select_active_buildings(category:nil, upgrader:nil, upgrade_resource:nil) 
    my_active_buildings = self.buildings.active(self.townhall_level) 
    if category && upgrader && upgrade_resource 
    return my_active_buildings.where(category:category, upgrader:upgrader, upgrade_resource:upgrade_resource) 
    elsif category && upgrader 
    return my_active_buildings.where(category:category, upgrader:upgrader) 
    elsif category && upgrade_resource 
    return my_active_buildings.where(category:category, upgrade_resource:upgrade_resource) 
    elsif upgrader && upgrade_resource 
    return my_active_buildings.where(upgrader:upgrader, upgrade_resource:upgrade_resource) 
    elsif category 
    return my_active_buildings.where(category:category) 
    elsif upgrader 
    return my_active_buildings.where(upgrader:upgrader) 
    elsif upgrade_resource 
    return my_active_buildings.where(upgrade_resource:upgrade_resource) 
    else 
    return my_active_buildings 
    end 
end 

我需要幫助重構此方法。

+0

這個問題將在http://codereview.stackexchange.com/ –

+0

更好這個問題可能是適用於[代碼審查(http://codereview.stackexchange.com/help)只要(a)您的代碼按預期工作,(b)您的代碼是真實的代碼,而不是示例代碼,並且(c)您的代碼包含在問題的正文中。如果您希望通過同行評審來改進代碼的各個方面,請將其發佈在代碼評審中。 – Phrancis

+0

謝謝,你是對的。 – thedanotto

回答

2

假設你用ActiveRecord,Mongoid,或用可鏈接where做別的事情,你可以採取的事實,即這樣的:

o.where(:a => b, :c => d) 

是一樣的:

o.where(:a => b).where(:c => d) 

這可以讓你做到這一點:

def select_active_buildings(category: nil, upgrader: nil, upgrade_resource: nil) 
    buildings = self.buildings.active(self.townhall_level) 
    buildings = buildings.where(category: category) if(category) 
    buildings = buildings.where(upgrader: upgrader) if(upgrader) 
    buildings = buildings.where(upgrade_resource: upgrade_resource) if(upgrade_resource) 
    buildings 
end 

甚至:

def select_active_buildings(conditions) 
    buildings = self.buildings.active(self.townhall_level) 
    %i[category upgrader upgrade_resource] 
    .select { |f| conditions.has_key?(f) } 
    .inject(buildings) { |q, f| q.where(f => conditions[f]) } 
end 
+0

我和你的第一個選擇一起去了。非常感謝。 – thedanotto

3

我應該這樣做:

def select_active_buildings(category: nil, upgrader: nil, upgrade_resource: nil) 
    my_active_buildings = self.buildings.active(self.townhall_level) 
    cond = { 
    category: category, 
    upgrader: upgrader, 
    upgrade_resource: upgrade_resource 
    }.select { |k, v| v } 
    my_active_buildings.where(cond) 
end 

或者,

def select_active_buildings(category: nil, upgrader: nil, upgrade_resource: nil) 
    my_active_buildings = self.buildings.active(self.townhall_level) 
    cond = {} 
    cond[:category] = category if category 
    cond[:upgrader] = upgrader if upgrader 
    cond[:upgrade_resource] = upgrade_resource if upgrade_resource 
    my_active_buildings.where(cond) 
end 

或者,如果我真的不關心語法在select_active_function水平檢查,

def select_active_buildings(cond) 
    my_active_buildings = self.buildings.active(self.townhall_level) 
    my_active_buildings.where(cond) 
end 

如果你真的不想要.where({})的情況下,你可以把它放在return my_active_buildings if cond.empty?之前。

+0

最後一個變體是'where(cond.slice(:category,...))'。 –

-1
def select_active_buildings(category: nil, upgrader: nil, upgrade_resource: nil) 
    buildings.active(self.townhall_level).where(
    **({category: category} if category).to_h, 
    **({upgrader: upgrader} if upgrader).to_h, 
    **({upgrade_resource: upgrade_resource} if upgrade_resource).to_h, 
) 
end