Rails整个工程涉及的模块很多,当然文件更多,在学习源码的时候经常要查找文件和方法,有一个好的IDE可以令这个过程变得轻松一些。可以使用Ecplise中的Ruby插件,把Rails的源码导入到工程中,这样查看这些文件以及查找一些方法会很方便。
继续上次的内容,当我们用命令创建出一个App的框架之后,还会使用script/generate model(controller,scaffold)等命令生成Model、Controller模板文件。先看下面这张图:
[img]http://meladet.iteye.com/upload/picture/pic/40266/33645970-8bdb-3ba3-a0a5-379f4e3457c9.png[/img]
这张图概括了生成模板文件的主要过程以及涉及到的主要源文件,我以script/generate controller 为例,联合源码做一些说明。
script/generate controller首先会执行你的App中script文件夹下的generate命令,我们看一下这个文件的内容:
这个文件很简单,就是启动Rails,然后调用commands文件夹下的genrate.rb文件,boot这个过程暂时不讲,在之后的文章中在具体说明,boot做的事情启动Rails,检查需要加载的Rails版本等。
我们直接看commands文件夹下的generate.rb文件:
这个文件代码也很少,其中envrironment.rb文件配置了你启动的Rails的环境,里面有数据库的配置、框架的配置、时区配置、i18n等。
rails_generator.rb文件,主要是准备好生成器,包括调用生成器的名字,需要生成的模板文件等。最后Rails::Generator::Scripts::Generate.new.run(ARGV)运行生成器生成模板文件。看文件rails_generator/scripts/generate.rb,generate中有一个:command=>:create,这个参数在Commands模块中会使用到,用来生成一个Create类型的Generator Command来执行模板文件的拷贝等工作。下面是源码:
下面要看看rails_generator.rb文件里面的代码,看看是如何通过用户参数找到对应的生成器,然后生成器怎样生成那些模板文件的:
这个文件先加载本地的active_support,如果本地没有就通过gem加载,然后给Rails::Generator::Base类中混入Rails::Generator::Lookup、Rails::Generator::Commands两个模块的功能,最后初始化Rails::Generator::Base中的logger,以便使用。
Lookup类主要是用来通过用户输入的参数,查找对应的generator。比如本例中,我们要执行的命令是script/generate controller,那么Lookup将会通过controller这个参数,去加载rails_generator/generators/components/controller/controller_generator.rb这个文件,生成一个ControllerGenerator。
到这里,我们先说一下generator的目录结构,看下图:generator有两种,一种是applications,我们上一次讲的生成整个app的框架时,调用的就是这里面的generator。另一种是components,可以看到我们平时常用的几个生成器都有对应的文件夹,看controller的文件夹会发现,除了有一个生成器之外还有一个templates文件夹和USAGE文件,templates文件夹里的文件就是通过controller_generator会生成的模板文件,从图上可以看出controller_generator会生成一个controller的文件一个功能测试,一个helper的测试,一个helper文件以及对应controller中action的view文件。USAGE文件是这个generator的使用说明信息。
每个组件生成器都有对应的文件夹,里面都有templates和一个生成器,通过这些信息就能生成模板文件。
[img]http://meladet.iteye.com/upload/picture/pic/40262/0183e934-9065-3779-8bc1-87f13610226f.png[/img]
Commands模块的功能主要是生成一个generator的委托,来完成generator的工作。Rails中有create,destroy,update,list几个命令,对应有Create,Destroy,Update,List这几种Generator Command。之前介绍过的在command文件夹下的generate.rb文件中,通过Rails::Generator::Scripts::Generate.new.run(ARGV)构造出的Generator会传递:command=>:create这个参数,那么Commands模块就会对应的生成一个Create类型的generator,它完成了创建目录,拷贝模板文件等工作。
Generator Command的定义都在commands.rb文件中,每种Command都有对应的实例方法。这边不一一列举,大家可以自己看看源码。这些实例方法会在之后介绍的manifest方法中用到。
到现在已经基本上把通过用户输入,找到对应的生成器并且生成模板文件的过程介绍完了。这个过程中涉及到的源码比较少,主要是讲解生成器的工作流程。之后将会通过源码来详细说明这个流程。
继续上次的内容,当我们用命令创建出一个App的框架之后,还会使用script/generate model(controller,scaffold)等命令生成Model、Controller模板文件。先看下面这张图:
[img]http://meladet.iteye.com/upload/picture/pic/40266/33645970-8bdb-3ba3-a0a5-379f4e3457c9.png[/img]
这张图概括了生成模板文件的主要过程以及涉及到的主要源文件,我以script/generate controller 为例,联合源码做一些说明。
script/generate controller首先会执行你的App中script文件夹下的generate命令,我们看一下这个文件的内容:
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/generate'
这个文件很简单,就是启动Rails,然后调用commands文件夹下的genrate.rb文件,boot这个过程暂时不讲,在之后的文章中在具体说明,boot做的事情启动Rails,检查需要加载的Rails版本等。
我们直接看commands文件夹下的generate.rb文件:
require "#{RAILS_ROOT}/config/environment"
require 'rails_generator'
require 'rails_generator/scripts/generate'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
Rails::Generator::Scripts::Generate.new.run(ARGV)
这个文件代码也很少,其中envrironment.rb文件配置了你启动的Rails的环境,里面有数据库的配置、框架的配置、时区配置、i18n等。
rails_generator.rb文件,主要是准备好生成器,包括调用生成器的名字,需要生成的模板文件等。最后Rails::Generator::Scripts::Generate.new.run(ARGV)运行生成器生成模板文件。看文件rails_generator/scripts/generate.rb,generate中有一个:command=>:create,这个参数在Commands模块中会使用到,用来生成一个Create类型的Generator Command来执行模板文件的拷贝等工作。下面是源码:
require File.dirname(__FILE__) + '/../scripts'
module Rails::Generator::Scripts
class Generate < Base
mandatory_options :command => :create
end
end
下面要看看rails_generator.rb文件里面的代码,看看是如何通过用户参数找到对应的生成器,然后生成器怎样生成那些模板文件的:
$:.unshift(File.dirname(__FILE__))
$:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib")
begin
require 'active_support'
rescue LoadError
require 'rubygems'
gem 'activesupport'
end
require 'rails_generator/base'
require 'rails_generator/lookup'
require 'rails_generator/commands'
Rails::Generator::Base.send(:include, Rails::Generator::Lookup)
Rails::Generator::Base.send(:include, Rails::Generator::Commands)
# Set up a default logger for convenience.
require 'rails_generator/simple_logger'
Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
这个文件先加载本地的active_support,如果本地没有就通过gem加载,然后给Rails::Generator::Base类中混入Rails::Generator::Lookup、Rails::Generator::Commands两个模块的功能,最后初始化Rails::Generator::Base中的logger,以便使用。
Lookup类主要是用来通过用户输入的参数,查找对应的generator。比如本例中,我们要执行的命令是script/generate controller,那么Lookup将会通过controller这个参数,去加载rails_generator/generators/components/controller/controller_generator.rb这个文件,生成一个ControllerGenerator。
到这里,我们先说一下generator的目录结构,看下图:generator有两种,一种是applications,我们上一次讲的生成整个app的框架时,调用的就是这里面的generator。另一种是components,可以看到我们平时常用的几个生成器都有对应的文件夹,看controller的文件夹会发现,除了有一个生成器之外还有一个templates文件夹和USAGE文件,templates文件夹里的文件就是通过controller_generator会生成的模板文件,从图上可以看出controller_generator会生成一个controller的文件一个功能测试,一个helper的测试,一个helper文件以及对应controller中action的view文件。USAGE文件是这个generator的使用说明信息。
每个组件生成器都有对应的文件夹,里面都有templates和一个生成器,通过这些信息就能生成模板文件。
[img]http://meladet.iteye.com/upload/picture/pic/40262/0183e934-9065-3779-8bc1-87f13610226f.png[/img]
Commands模块的功能主要是生成一个generator的委托,来完成generator的工作。Rails中有create,destroy,update,list几个命令,对应有Create,Destroy,Update,List这几种Generator Command。之前介绍过的在command文件夹下的generate.rb文件中,通过Rails::Generator::Scripts::Generate.new.run(ARGV)构造出的Generator会传递:command=>:create这个参数,那么Commands模块就会对应的生成一个Create类型的generator,它完成了创建目录,拷贝模板文件等工作。
Generator Command的定义都在commands.rb文件中,每种Command都有对应的实例方法。这边不一一列举,大家可以自己看看源码。这些实例方法会在之后介绍的manifest方法中用到。
到现在已经基本上把通过用户输入,找到对应的生成器并且生成模板文件的过程介绍完了。这个过程中涉及到的源码比较少,主要是讲解生成器的工作流程。之后将会通过源码来详细说明这个流程。