将目录添加到 $LOAD_PATH (Ruby)
我见过两种常用的技术,用于将当前正在执行的文件的目录添加到 $LOAD_PATH(或 $:)。 我看到了这样做的好处,以防您不使用 gem。 显然,其中一个似乎比另一个更冗长,但是有理由选择其中一个而不是另一个吗?
第一种,冗长的方法(可能有点过分):
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
以及更直接,快速和肮脏的方法:
$:.unshift File.dirname(__FILE__)
有什么理由选择其中一个而不是另一个?
I have seen two commonly used techniques for adding the directory of the file currently being executed to the $LOAD_PATH (or $:). I see the advantages of doing this in case you're not working with a gem. One seems more verbose than the other, obviously, but is there a reason to go with one over the other?
The first, verbose method (could be overkill):
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
and the more straightforward, quick-and-dirty:
$:.unshift File.dirname(__FILE__)
Any reason to go with one over the other?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
Ruby 加载路径通常写为 $: ,但仅仅因为它很短,并不能使它变得更好。 如果你更喜欢清晰而不是聪明,或者如果简洁本身就让你心痒痒,那么你不必因为其他人都这样做而这样做。
向......打招呼
,向......说再见
The Ruby load path is very commonly seen written as $: , but just because it is short, does not make it better. If you prefer clarity to cleverness, or if brevity for its own sake makes you itchy, you needn't do it just because everyone else is.
Say hello to ...
... and say goodbye to ...
我会说使用
$:.unshift File.dirname(__FILE__)
而不是另一个,因为我在代码中看到它比$LOAD_PATH
一,而且还更短!I would say go with
$:.unshift File.dirname(__FILE__)
over the other one, simply because I've seen much more usage of it in code than the$LOAD_PATH
one, and it's shorter too!我不太喜欢“快速而肮脏”的方式。
任何刚接触 Ruby 的人都会思考
$:.
是什么。我觉得这一点更明显。
或者如果我关心完整路径...
更新 2009/09/10
截至最近我一直在做以下事情:
我在一大堆不同的红宝石项目中看到了它浏览 GitHub。
好像是约定俗成的?
I'm not too fond on the 'quick-and-dirty' way.
Anyone new to Ruby will be pondering what
$:.
is.I find this more obvious.
Or if I care about having the full path...
UPDATE 2009/09/10
As of late I've been doing the following:
I've seen it in a whole bunch of different ruby projects while browsing GitHub.
Seems to be the convention?
我在使用 Rspec 时遇到的最好的情况是通过相对路径添加目录。 我发现它足够冗长,但仍然是一个很好的衬里。
Best I have come across for adding a dir via relative path when using Rspec. I find it verbose enough but also still a nice one liner.
如果您在 Rails 项目中输入
script/console
并输入$:
,您将获得一个数组,其中包含加载 Ruby 所需的所有目录。 这个小练习的要点是$:
是一个数组。 既然如此,您可以对其执行函数,例如使用unshift
方法或<<
运算符在其他目录前面添加。 正如您在声明中所暗示的$:
和$LOAD_PATH
是相同的。正如您提到的那样,以快速而肮脏的方式执行此操作的缺点是:如果您的引导路径中已有该目录,则它会重复自身。
示例:
我创建了一个名为 todo 的插件。 我的目录结构如下:
在 init.rb 文件中,我输入了以下代码:
请注意我如何告诉代码块对字符串“models”、“controllers”和“models”执行块内的操作,其中我重复“模型”。 (仅供参考,
%w{ ... }
只是告诉 Ruby 保存字符串数组的另一种方式)。 当我运行script/console
时,我键入以下内容:我键入此内容是为了更轻松地读取字符串中的内容。 我得到的输出是:
正如您所看到的,虽然这是我在使用我当前正在处理的项目时可以创建的简单示例,但如果您不小心,这种快速而肮脏的方式将导致重复的路径。 较长的方法将检查重复的路径并确保它们不会发生。
如果您是一位经验丰富的 Rails 程序员,您可能非常清楚自己在做什么,并且可能不会犯重复路径的错误。 如果你是新手,我会走更长的路,直到你真正理解你在做什么。
If you type
script/console
in your Rails project and enter$:
, you'll get an array that includes all the directories needed to load Ruby. The take-away from this little exercise is that$:
is an array. That being so, you can perform functions on it like prepending other directories with theunshift
method or the<<
operator. As you implied in your statement$:
and$LOAD_PATH
are the same.The disadvantage with doing it the quick and dirty way as you mentioned is this: if you already have the directory in your boot path, it will repeat itself.
Example:
I have a plugin I created called todo. My directory is structured like so:
In the init.rb file I entered the following code:
Note how I tell the code block to perform the actions inside the block to the strings 'models', 'controllers', and 'models', where I repeat 'models'. (FYI,
%w{ ... }
is just another way to tell Ruby to hold an array of strings). When I runscript/console
, I type the following:And I type this so that it is easier to read the contents in the string. The output I get is:
As you can see, though this is as simple an example I could create while using a project I'm currently working on, if you're not careful the quick and dirty way will lead to repeated paths. The longer way will check for repeated paths and make sure they don't occur.
If you're an experienced Rails programmer, you probably have a very good idea of what you're doing and likely not make the mistake of repeating paths. If you're a newbie, I would go with the longer way until you understand really what you're doing.
有一个 gem 可以让您使用更好、更干净的代码设置加载路径。 看看这个:https://github.com/nayyara-samuel/load-path 。
它还有很好的文档
There is a gem which will let you setup your load path with nicer and cleaner code. Check this out: https://github.com/nayyara-samuel/load-path.
It also has good documentation
我的 2 美分:我喜欢
$LOAD_PATH
而不是$:
。 我已经老了……我已经学习了 92,000 种语言。 我发现很难掌握所有的习俗和习语。我开始厌恶命名空间污染。
最后,当我处理路径时,我总是删除然后附加或前置 - 这取决于我希望搜索如何进行。 因此,我这样做:
My 2¢: I like
$LOAD_PATH
rather than$:
. I'm getting old... I've studied 92,000 languages. I find it hard to keep track of all the customs and idioms.I've come to abhor namespace pollution.
Last, when I deal with paths, I always delete and then either append or prepend -- depending upon how I want the search to proceed. Thus, I do:
您可以执行以下操作:
甚至:
You can do things like:
And even:
我知道自从第一次问这个问题以来已经过去很长时间了,但我还有一个想要分享的答案。
我有几个 Ruby 应用程序,这些应用程序是由另一位程序员花了几年时间开发的,尽管它们可能访问相同的数据库,但它们在不同的应用程序中重复使用相同的类。 由于这违反了 DRY 规则,因此我决定创建一个由所有 Ruby 应用程序共享的类库。 我本可以将它放在主 Ruby 库中,但这会将自定义代码隐藏在公共代码库中,这是我不想做的。
我遇到了一个问题,即已定义的名称“profile.rb”与我正在使用的类之间存在名称冲突。 在我尝试创建公共代码库之前,这种冲突并不是问题。 通常,Ruby 首先搜索应用程序位置,然后转到 $LOAD_PATH 位置。
application_controller.rb 找不到我创建的类,并在原始定义上抛出错误,因为它不是一个类。 由于我从应用程序的 app/models 部分删除了类定义,Ruby 无法在那里找到它,因此在 Ruby 路径中查找它。
因此,我修改了 $LOAD_PATH 变量以包含我正在使用的库目录的路径。 这可以在初始化时在environment.rb 文件中完成。
即使将新目录添加到搜索路径中,Ruby 也会抛出错误,因为它优先考虑系统定义的文件。 $LOAD_PATH 变量中的搜索路径优先搜索 Ruby 路径。
因此,我需要更改搜索顺序,以便 Ruby 在搜索内置库之前先找到我的公共库中的类。
这段代码在environment.rb文件中完成了它:
我认为您不能在这个级别使用之前给出的任何高级编码结构,但如果您想在应用程序的初始化时设置某些内容,它就可以很好地工作。 当原始 $LOAD_PATH 变量添加回新变量时,您必须保持其原始顺序,否则一些主要 Ruby 类会丢失。
在 application_controller.rb 文件中,我只需使用 a
即可加载整个应用程序的自定义库文件,即我不必在每个控制器中使用 require 命令。
对我来说,这就是我正在寻找的解决方案,我想我会将其添加到这个答案中以传递信息。
I know it's been a long time since this question was first asked, but I have an additional answer that I want to share.
I have several Ruby applications that were developed by another programmer over several years, and they re-use the same classes in the different applications although they might access the same database. Since this violates the DRY rule, I decided to create a class library to be shared by all of the Ruby applications. I could have put it in the main Ruby library, but that would hide custom code in the common codebase which I didn't want to do.
I had a problem where I had a name conflict between an already defined name "profile.rb", and a class I was using. This conflict wasn't a problem until I tried to create the common code library. Normally, Ruby searches application locations first, then goes to the $LOAD_PATH locations.
The application_controller.rb could not find the class I created, and threw an error on the original definition because it is not a class. Since I removed the class definition from the app/models section of the application, Ruby could not find it there and went looking for it in the Ruby paths.
So, I modified the $LOAD_PATH variable to include a path to the library directory I was using. This can be done in the environment.rb file at initialization time.
Even with the new directory added to the search path, Ruby was throwing an error because it was preferentially taking the system-defined file first. The search path in the $LOAD_PATH variable preferentially searches the Ruby paths first.
So, I needed to change the search order so that Ruby found the class in my common library before it searched the built-in libraries.
This code did it in the environment.rb file:
I don't think you can use any of the advanced coding constructs given before at this level, but it works just fine if you want to setup something at initialization time in your app. You must maintain the original order of the original $LOAD_PATH variable when it is added back to the new variable otherwise some of the main Ruby classes get lost.
In the application_controller.rb file, I simply use a
and this loads the custom library files for the entire application, i.e., I don't have to use require commands in every controller.
For me, this was the solution I was looking for, and I thought I would add it to this answer to pass the information along.