rails如何从gem中隐式导入函数?

我是ruby和rails的新手。 我看到我所包含的任何gem,我都可以直接在我的代码中使用它的function。 我没有看到代码的任何导入,也没有看到函数的任何名称空间。 如果gem包含具有相同名称的函数,那么这不是冲突的配方吗?

所以 –

ruby / rails如何导入函数,如何将函数映射到gem? 当2颗gem包含相同的function时,它会导致冲突吗? 如果我想显式使用ruby库,我将如何导入其代码? ruby中有名字空间吗?

ruby

ruby将在一个文件中声明的函数导入另一个文件的方式是通过require函数。 load实现了类似的function,但是出于一般目的,通常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 

gem

Gems可以被认为是一个ruby代码包或库。 有几种加载gem的方法,但最常见的是via require你已经安装了progressbar gem来在终端中显示简单的进度条( 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查找所需文件的路径中。

轨道

Rails只是一组gem,其中一些提供可执行的脚本。 在以前的版本中,您必须指定要加载的gem,这与我们上面的方式非常相似。 但是现在,使用bundler ,我们可以在一个Gemfile指定所有gem,以及版本控制和源信息。 Bundler然后将在gem中解决依赖关系,并在Gemfile.lock保留我们针对项目的特定版本。 由于bundler本身是一个gem,你经常会看到这样的代码:

配置/ application.rb中

 require 'bundler' Bundler.require(:default, Rails.env) 

这段代码告诉Bundler加载我们在gemfile中平面列出的所有依赖项,以及我们在当前rails env对应的组中列出的依赖项(例如:development)。

命名空间

是的,您可以通过几种方式遇到问题。 两个gem可以具有相同的名称,虽然在这种情况下它们不能被推送到rubygems,你会很快发现它。 一个更微妙的命名空间问题是如果两个文件做这样的事情:

hello1.rb

 def hello puts "Hi" end 

hello2.rb

 def hello puts "Hello, there!" end 

hello3.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 ...