在 Rails 上使用 ruby 时,通常使用终端命令,如rake db:migrate
or rails g devise:install
。但是这些命令中的究竟是什么:
意思?Inrake db:migrate
是migrate
参数还是其他?这似乎不是一个很难的问题,但是在谷歌上研究了几个小时并没有找到答案之后,我真的很想有人向我解释一下,拜托。
2 回答
您可以将冒号视为命名空间。在 Rails 中的某个地方有一个 rake 任务文件,看起来类似于:
namespace db
task :migrate do...
....
end
end
这是一种将相关任务组合在一起并防止它们与其他任务发生冲突的方法。这样,您可能会拥有 devise:migrate、db:migrate、foobar:migrate 等。
就像菲利普在使用 rake 时在他的回答中解释的那样,冒号定义了命名空间/任务之间的分隔符
使用rails g(enerate)
时基本相同。不同之处在于 Rails 生成器不是用 rake 的 DSL 定义的,而是类。
但是要回答您最初的问题:在这两种情况下,冒号都是分隔符,就是这样。
在代码中,唯一重要的是拆分字符串: https ://github.com/rails/rails/blob/4-0-stable/railties/lib/rails/generators.rb#L124
您可以在官方Ruby on Rails 指南中找到更多关于生成器以及如何创建生成器的信息(definetley 将帮助您了解其背后的机制)
//EDIT 好,我们来仔细看看生成器查找过程:
它接收 CLI 上传递的命名空间并将其拆分(使用冒号)
names = namespace.to_s.split(':')
然后它通过传递传递的命名空间的最后一部分(实际的生成器名称)得到相应的类,其余部分再次用冒号连接(命名空间路径,在我们的例子中是devise)Rails::Generators::Base.find_by_namespace
if klass = find_by_namespace(names.pop, names.any? && names.join(':'))
此方法将再次连接 base(命名空间路径)和 name(生成器名称)并将其推送到数组:
lookups = []
lookups << "#{base}:#{name}" if base
之后它调用Rails::Generators.lookup
它将查找要为被调用生成器调用的类:
lookup(lookups)
这将再次调用Rails::Generators.namepaces_to_paths
该方法没有什么大魔法,它只会为调用的生成器返回两个可能的源路径的数组,在我们的例子中,这两个是“设计/安装/安装”和“设计/安装”。
因此,这些不是 rails 将检查的实际路径,它们只是依赖于 namespace:generator 构造的部分。
该lookup
方法现在将采用这两个,让我们称它们为子路径,并在以下位置检查需要的文件:
- rails/generators/devise/install/install_generator
- 生成器/设计/安装/install_generator
- rails/generators/devise/install_generator
- 生成器/设计/install_generator
在我们的例子中,第二个路径是所需的文件,rails 需要它,并且通过它inherited
(更多关于回调回调的信息Rails::Generators::Base
将被调用,因为Devise::Generators::InstallGenerator
它继承自它。
这会将 Class 添加到映射到 Hash 的subclasses
数组中,该数组Rails::Generators
的格式为 { namespace => klass } ,因此 rails 最终能够获得所需的生成器类
并启动它