是否需要物质是必要的吗?

3
我希望有一个 Ruby 文件,可以使用 require 导入所有常见的依赖项,这样其他文件就可以在这个共享文件上只有一个 require。例如:我有 foo.rbbar.rb 以及 allrequires.rb。我想在 foo.rbbar.rb 中都有一行 require "allrequires.rb",但是 bar.rb 不需要所有的 requires。
如果我在不需要该文件的 .rb 文件中使用 require,是否会有影响?可能会影响性能吗?
我目前使用的是 ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32] 更新:
看起来在两个 .rb 文件中“共享”或使用所有 requires 不是最好的主意。那么解决方案是什么呢?
现在我能想到的是使用文件名作为条件。

2
第一句话是什么意思?分享的含义是什么? - Andrew Grimm
4个回答

3

主要有两个性能问题:

  1. require 本身所花费的时间。在 Ruby 1.9.1 和 Ruby 1.9.2 中,所有 require 所需时间的可扩展性不如线性 - 如果你将 require 的数量翻倍,所需时间将超过两倍 - 我认为需要四倍的时间。
  2. 执行被 require 的文件中代码所需的时间。如果你的代码类似于以下内容,则执行代码将需要相当长的时间。
class MyClass
  MY_CONSTANT = File.read("data.txt")
end

我更新了我的问题...你能给我提供任何解决方案吗? - Radek
@Radek 你试过查找“非微不足道的数量”是什么意思吗? - Andrew Grimm
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Radek
为了其他阅读此内容的人的利益:我现在放弃了。 - Andrew Grimm
2
@Radek 一旦你完成了所有的要求,通常就没有什么缺点了。 - Andrew Grimm
显示剩余6条评论

1
另一种条件要求的方法是,以下脚本在JSON解析器上不会出错,因为它被命名为require1.rb,在没有名称的脚本(如require1.rb或script2.rb)中,gem不需要。
require 'json' if "require1.rb, script2.rb"[File.basename(__FILE__)]

p File.basename(__FILE__)

text = '[{ "name" : "car", "status": "good"}, { "name" : "bus", "status": "bad"},{ "name" : "taxi", "status": "soso"},
  {"noname":"", "status" : "worse"}
]' 
data = JSON.parse(text) 

p data.collect { |item| item['name'] } 

编辑:这里有一个使用数组的版本

["require1.rb","script1.rb"].find{|script|require 'json' if script===File.basename(__FILE__)}

我想我正在寻找的是“有条件的要求”。你能向我解释一下if语句的语法吗?if "require1.rb, script2.rb"[File.basename(__FILE__)] - Radek
1
当然,“require1.rb,script2.rb”是您希望此要求操作的脚本名称字符串,[]在字符串后面检查括号内的字符串是否存在(简化的正则表达式),这里是常量__FILE__,我从中获取基本名称。因此,我检查脚本名称是否出现在字符串中。您可以使用数组并使用扫描或映射函数进行检查,也可以与我在这里的其他答案结合使用。 - peter
文件名为什么用逗号分隔?这是一个字符串还是两个字符串? - Radek
一个字符串,逗号只是分隔符。 - peter
1
我编辑了我的答案,加入了一个数组版本,这比字符串方法更清晰、更安全。 - peter

0

是的,会有速度惩罚,您可以进行基准测试以考虑实际影响。 对于多个require,我将它们放在代码中,以便不占用太多屏幕空间。

['green_shoes','Hpricot'].each(&method(:require))

你也可以使用条件式的 require,但这样会让你的代码变得丑陋。
begin
  data = JSON.parse(text)
rescue
  require 'json_pure' 
  data = JSON.parse(text)
end

简而言之,给每个rb文件单独指定require。

0
我的最终解决方案是(如果有人发现它有用的话):
requires.rb 被从 web.rb 或 testweb.rb、rufus.rb 或 testrufus.rb 中调用。
called_from=caller[0].split(":")[0]


puts "loading web 'requires' for file: #{called_from} ..." if (["web"].any?{|s| called_from[s]})
puts "loading web 'requires' for file: #{called_from} ..." if (["rufus"].any?{|s| called_from[s]})
puts "loading web 'requires' for file: #{called_from} ..." if (["settings"].any?{|s| called_from[s]})

require 'rubygems'

require 'socket'        if (["web","settings"].any?{|s| called_from[s]})
require 'ruby-growl'    if (["web","settings","rufus"].any?{|s| called_from[s]})
require 'sinatra'       if (["web"].any?{|s| called_from[s]}) 

感谢 @Andrew 的解释和 @peter 提供的解决方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接