rails 如何从 gems 隐式导入函数? [英] how does rails implicitly import functions from gems?
问题描述
我是 ruby 和 rails 的新手.我看到我包含的任何 gems,我可以直接在我的代码中使用它的函数.我没有看到代码的任何导入,也没有看到函数的任何命名空间.如果 gems 包含同名的函数,这不是冲突的秘诀吗?
I am new to ruby and rails. I see that any gems that I have included, I can directly use its functions in my code. I do not see any imports for the code, nor any name spaces for the functions. Isn't this recipe for conflicts, if the gems contain functions with same names ?
所以 -
ruby/rails 如何导入函数,如何将函数映射到 gem 中?当 2 个 gem 包含相同的函数时会导致冲突吗?如果我想明确使用 ruby 库,我将如何导入它的代码?ruby 中有命名空间吗?
How does ruby/rails imports the functions, how does it map a function to a gem ? Can it lead to conflicts when 2 gems contain the same funcitons ? If I want to explicitly use a ruby library, how will I import its code ? Is there namespacing in ruby?
推荐答案
Ruby
ruby 将一个文件中声明的函数导入另一个文件的方式是通过 require
函数.load
完成类似的事情,但对于一般用途,require
通常是您想要的(请参阅 http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/ 了解更多详情)
Ruby
The way ruby imports functions declared in one file into another file is via the require
function. load
accomplishes something similar, but for general purposes, require
is usually what you want (see http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/ for more details)
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'
subdir/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 安装进度条
)
Gems
Gems can be thought of as a package of ruby code, or a library. There are a couple ways of loading a gem, but the most common is via require
Say you've installed the progressbar
gem for displaying simple progress bars in the terminal (gem install progressbar
)
progressbar_test.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 查找所需文件的路径中.
The reason this works, is that when we require rubygems
, it's adding the progressbar gem to the path of where ruby looks for required files.
Rails 只是 gem 的集合,其中一些提供了可执行脚本.在以前的版本中,您必须指定要加载的 gem,就像我们上面所做的那样.但是现在,使用 bundler
,我们可以在一个 Gemfile
中指定所有 gem,以及版本和源信息.然后,Bundler 将计算 gems 之间的依赖关系,并在 Gemfile.lock
中保留项目的特定版本.由于 bundler
本身就是一个 gem,你会经常看到这样的代码:
Rails is just a collection of gems, some of which provide executable scripts. In previous versions, you had to specify the gems to load, much in the way we did above. But now, with bundler
, we can specify all our gems in one Gemfile
, along with versioning and source information. Bundler then will work out dependencies amongst the gems and keep our specific versioning for a project in Gemfile.lock
. Since bundler
itself is a gem, you'll often see code like this:
config/application.rb
require 'bundler'
Bundler.require(:default, Rails.env)
这段代码告诉 Bundler 加载我们在 gemfile 中明确列出的所有依赖项,以及我们在与当前 rails env 对应的组中列出的依赖项(例如:development).
This code tells Bundler to load all of the dependencies we listed flatly in our gemfile, as well as the ones we listed in the group corresponding to the current rails env (e.g. :development).
是的,您可以通过多种方式遇到问题.两个 gem 可以具有相同的名称,但在这种情况下它们不能被推送到 rubygems,您很快就会发现这一点.一个更微妙的命名空间问题是如果两个文件做这样的事情:
Yes, you can run into issues in a couple ways. Two gems could have the same name, although they can't be pushed to rubygems in that case, and you'll discover that quickly. A more subtle namespace issue is if two files do something like this:
hello1.rb
def hello
puts "Hi"
end
hello2.rb
def hello
puts "Hello, there!"
end
hello3.rb
require './hello1'
require './hello2'
hello
这里我们看看当我们在全局命名空间中发生命名空间冲突时会发生什么.如果两个库在相同的类名中定义相同的方法,就会发生类似的事情(这种猴子补丁虽然不鼓励,但仍然会发生!).在实践中,你不会遇到太多这种情况,尤其是在使用模块命名命名空间代码方面使用良好的纪律时,就像我在写一个 gem hello
:
Here we see what happens when we have a namespace conflict in the global namespace. Similar things can happen if two libraries define the same method in the same class name (and this type of monkey patching, while discouraged, still happens!). In practice, you don't run into this too much, especially when good discipline is used in terms of using Modules to namespace code, like if I'm writing a 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
这篇关于rails 如何从 gems 隐式导入函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!