[英]How would I refactor this code to use procs?
The original code: 原始代码:
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
I tried to refactor like this: 我试图像这样重构:
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
But I get this error: 但是我得到这个错误:
Error: undefined local variable or method `array_builder' for Page:Class.
When I turned array_builder into a class method, like this: 当我将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
I got an error that in the self.user_admin_links method that "page" is not recognized. 我收到一个错误,在self.user_admin_links方法中无法识别“页面”。
In Ruby, methods are not closures. 在Ruby中,方法不是闭包。 Ie, they cannot use local variables from the surrounding scope, such as
array_builder
. 即,它们不能使用周围范围的局部变量,例如
array_builder
。
And if you want page
to be evaluated for every element of ADMIN_PAGES
, you should use a block argument (which is basically just some syntax for passing procs as arguments). 而且,如果您希望针对
ADMIN_PAGES
每个元素对page
进行评估,则应使用一个块参数(基本上只是将proc作为参数传递的某种语法)。 Otherwise it is just evaluated once in the links
methods, where page
is not defined. 否则,将仅在未定义
page
的links
方法中对它进行一次评估。
def array_builder &conditional
ADMIN_PAGES.inject([]) do |result, page|
result << Page.new(controller: page[:name]) if conditional[page]
result
end
end
Also, here is a better Ruby idiom for the job. 另外,这是一个更好的Ruby习惯用法。 Instead of manually pushing to an array and using inject, use
Enumerable#select
and Enumerable#map
: 使用
Enumerable#select
和Enumerable#map
而不是手动推送到数组并使用inject:
def array_builder &conditional
ADMIN_PAGES.select(&conditional).map {|page| Page.new(controller: page[:name])}
end
The other methods then pass a block: 然后,其他方法传递一个块:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.