2012-07-19 39 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