我是 ruby 和 rails 的新手。我看到我包含的任何 gem,我可以直接在我的代码中使用它的功能。我没有看到代码的任何导入,也没有看到函数的任何名称空间。如果宝石包含具有相同名称的函数,这不是冲突的秘诀吗?
所以 -
ruby/rails 如何导入函数,如何将函数映射到 gem ?当 2 个 gem 包含相同的功能时会导致冲突吗?如果我想显式使用 ruby 库,我将如何导入它的代码?红宝石中有命名空间吗?
我是 ruby 和 rails 的新手。我看到我包含的任何 gem,我可以直接在我的代码中使用它的功能。我没有看到代码的任何导入,也没有看到函数的任何名称空间。如果宝石包含具有相同名称的函数,这不是冲突的秘诀吗?
所以 -
ruby/rails 如何导入函数,如何将函数映射到 gem ?当 2 个 gem 包含相同的功能时会导致冲突吗?如果我想显式使用 ruby 库,我将如何导入它的代码?红宝石中有命名空间吗?
ruby 将一个文件中声明的函数导入另一个文件的方式是通过require
函数。load
完成类似的事情,但出于一般目的,require
通常是您想要的(有关更多详细信息,请参阅http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/)
hello_lib.rb
def say_hello
puts "hello"
end
# that's right, you can execute code when a library is required,
# so the sky's the limit of what you can do
puts "Hey, I've been required!"
hello_caller.rb
# load the code from `hello_lib.rb` in the same directory
require './hello_lib.rb'
子目录/hello_other_caller.rb
# for illustrative purposes, adding the parent directory to the load path
# so that ruby will look there for files I want to require
$: << '..'
require 'hello_lib.rb'
say_hello
Gems 可以被认为是一个 ruby 代码包或一个库。有几种加载 gem 的方法,但最常见的是通过require
假设您已安装progressbar
gem 以在终端中显示简单的进度条 ( gem install progressbar
)
进度条测试.rb
require 'rubygems'
require 'progressbar'
# this also works
# gem 'progressbar', '~> 0.9.2'
pbar = ProgressBar.new("test", 100)
100.times do
sleep 0.1
pbar.inc
end
pbar.finish
这样做的原因是,当我们需要时rubygems
,它会将进度条 gem 添加到 ruby 查找所需文件的路径中。
Rails 只是一组 gem,其中一些提供可执行脚本。在以前的版本中,您必须指定要加载的 gem,就像我们上面所做的那样。但是现在,有了bundler
,我们可以在一个中指定所有的 gem Gemfile
,以及版本控制和源信息。然后,Bundler 将计算出 gem 之间的依赖关系,并将项目的特定版本控制在Gemfile.lock
. 由于bundler
它本身就是一个 gem,你会经常看到这样的代码:
配置/应用程序.rb
require 'bundler'
Bundler.require(:default, Rails.env)
这段代码告诉 Bundler 加载我们在 gemfile 中简单列出的所有依赖项,以及我们在与当前 rails env 对应的组中列出的那些依赖项(例如:development)。
是的,您可以通过几种方式遇到问题。两个宝石可以具有相同的名称,尽管在这种情况下它们不能被推送到 rubygems,你会很快发现。一个更微妙的命名空间问题是,如果两个文件执行以下操作:
你好1.rb
def hello
puts "Hi"
end
你好2.rb
def hello
puts "Hello, there!"
end
你好3.rb
require './hello1'
require './hello2'
hello
在这里,我们看到当我们在全局命名空间中发生命名空间冲突时会发生什么。如果两个库在同一个类名中定义了同一个方法,就会发生类似的事情(这种猴子补丁虽然不鼓励,但仍然会发生!)。在实践中,您不会遇到太多这种情况,尤其是在使用模块命名空间代码方面使用良好的纪律时,例如我正在编写 gem hello
:
module Hello
# not such a good name, but won't conflict with ::Object
class Object
def to_s
puts 'this is a bad idea'
end
end
end
Gems 是名称空间的,因此您可以通过以下方式显式调用方法
ModuleName::Class
如果你没有显式调用一个包含的类,ruby 将遍历它的所有类,直到找到你调用的类,如果没有,那么它会抛出一个 NoMethod 错误。
要让 Ruby 看到该库,您需要它:
require 'some_library'
要将库包含在类中,您:
class SomeClass
include SomeLibrary
...
如果您查看config/application.rb
,您会看到它是如何做到的:
Bundler.require(*Rails.groups)
而已!Bundler 会自动处理所有需要的 gem,因此您不必在使用的每个文件中都处理。有关更多详细信息,请参阅文档。