rails 如何从 gems 隐式导入函数? [英] how does rails implicitly import functions from gems?

查看:36
本文介绍了rails 如何从 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 可以具有相同的名称,但在这种情况下它们不能被推送到 ruby​​gems,您很快就会发现这一点.一个更微妙的命名空间问题是如果两个文件做这样的事情:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆