原始代码:
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方法中遇到错误&#34; page&#34;不被承认。
答案 0 :(得分:1)
在Ruby中,方法不是闭包。即,他们不能使用周围范围内的局部变量,例如array_builder
。
如果你想为page
的每个元素评估ADMIN_PAGES
,你应该使用一个块参数(这基本上只是将proc作为参数传递的一些语法)。否则,它只会在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#select
和Enumerable#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