`
meladet
  • 浏览: 26815 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Rails源码学习(二) 上

阅读更多
    Rails整个工程涉及的模块很多,当然文件更多,在学习源码的时候经常要查找文件和方法,有一个好的IDE可以令这个过程变得轻松一些。可以使用Ecplise中的Ruby插件,把Rails的源码导入到工程中,这样查看这些文件以及查找一些方法会很方便。
    继续上次的内容,当我们用命令创建出一个App的框架之后,还会使用script/generate model(controller,scaffold)等命令生成Model、Controller模板文件。先看下面这张图:

    这张图概括了生成模板文件的主要过程以及涉及到的主要源文件,我以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和一个生成器,通过这些信息就能生成模板文件。

    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方法中用到。
    到现在已经基本上把通过用户输入,找到对应的生成器并且生成模板文件的过程介绍完了。这个过程中涉及到的源码比较少,主要是讲解生成器的工作流程。之后将会通过源码来详细说明这个流程。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics