2012-07-19 37 views
0

原始代碼:我將如何重構此代碼使用特效?

def self.user_admin_links 
    ADMIN_PAGES.inject([]) do |result, page| 
     result << Page.new(controller: page[:name]) if page[:menu] && (page[:group_admin] || page[:company_admin]) 
     result 
    end 
    end 

    def self.super_admin_links 
    ADMIN_PAGES.inject([]) do |result, page| 
     result << Page.new(controller: page[:name]) if page[:super_admin] 
     result 
    end 
    end 

我試圖重構是這樣的:

array_builder = Proc.new do |conditional| 
    ADMIN_PAGES.inject([]) do |result, page| 
     result << Page.new(controller: page[:name]) if conditional 
     result 
    end 
    end 

    def self.user_admin_links 
    array_builder.call(page[:menu] && (page[:group_admin] || page[:company_admin])) 
    end 

    def self.super_admin_links 
    array_builder.call(page[:super_admin]) 
    end 

但我得到這個錯誤:

Error: undefined local variable or method `array_builder' for Page:Class. 

當我打開array_builder成一個類的方法,如這個:

def self.array_builder 
    Proc.new do |conditional| 
     ADMIN_PAGES.inject([]) do |result, hsh| 
     result << Page.new(controller: hsh[:name]) if conditional 
     result 
     end 
    end 
    end 

我收到了self.user_admin_links方法中「頁面」無法識別的錯誤。

+0

這似乎是Ruby的濫用:)。必須有一個更優雅的方法。你最終想要完成什麼? – 2012-07-19 16:03:26

+0

你正在嘗試抽象,這很好,但你做錯了。你所做的注入事實上是模擬列表理解,這就是你必須要抽象的東西。在Ruby中搜索有關列表理解的問題。 – tokland 2012-07-19 18:10:49

回答

1

在Ruby中,方法不是閉包。即,它們不能使用周圍範圍的局部變量,如array_builder

如果你想爲ADMIN_PAGES的每個元素評估page,你應該使用一個塊參數(基本上只是一些傳遞特定參數的語法)。否則,只在links方法中評估一次,其中page未定義。

def array_builder &conditional 
    ADMIN_PAGES.inject([]) do |result, page| 
    result << Page.new(controller: page[:name]) if conditional[page] 
    result 
    end 
end 

此外,這是一個更好的Ruby工作成語。不用手動推到一個數組並使用注入,使用Enumerable#selectEnumerable#map

def array_builder &conditional 
    ADMIN_PAGES.select(&conditional).map {|page| Page.new(controller: page[:name])} 
end 

其他方法然後傳遞塊:

def self.user_admin_links 
    array_builder {|page| page[:menu] && (page[:group_admin] || page[:company_admin])} 
end 

def self.super_admin_links 
    array_builder {|page| page[:super_admin]} 
end 
+0

我很欣賞你在這裏使用的細節。謝謝。 – 2012-07-19 22:06:36