`
fantaxy025025
  • 浏览: 1329319 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Rails源码阅读(一)_script/console

 
阅读更多
Rails源码阅读_script/console启动
 
rails中常用的命令script/console,一般来启动rails环境,在这里测试些脚本和函数等。
问题:
#1 启动到底做了什么,如何做到的
#2 console怎么用,能做什么,不能做什么
 
我其实最关心的是,这个命令如何启动了rails环境,这样我们就可以使用rails的很多组件了,例如active_record。如果不熟悉这个的话,我们就还是生活在“黑盒”之中,深感憋屈。
 
详细分析
script/console.rb脚本内容:
#!/usr/bin/env ruby
require File.expand_path('../../config/boot',  __FILE__)
require 'commands/console'
 就两行代码,用了expand_path~
 
script/boot
 
irb的使用
irb是ruby的交互运行控制台,方法是在命令行窗口输入irb。类似python中输入python后使用。
irb最常用的是不带任何参数的默认使用。但是还有另外还有很多的可选项。
 
$ irb -h
Usage:  irb.rb [options] [programfile] [arguments]
  -f    Suppress read of ~/.irbrc 
  -m    Bc mode (load mathn, fraction or matrix are available)
  -d                Set $DEBUG to true (same as `ruby -d')
  -r load-module    Same as `ruby -r'
  -I path           Specify $LOAD_PATH directory
  --inspect    Use `inspect' for output (default except for bc mode)
  --noinspect    Don't use inspect for output
  --readline    Use Readline extension module
  --noreadline    Don't use Readline extension module
  --prompt prompt-mode
  --prompt-mode prompt-mode
   Switch prompt mode. Pre-defined prompt modes are
   `default', `simple', `xmp' and `inf-ruby'
  --inf-ruby-mode   Use prompt appropriate for inf-ruby-mode on emacs. 
   Suppresses --readline. 
  --simple-prompt   Simple prompt mode
  --noprompt    No prompt mode
  --tracer    Display trace for each execution of commands.
  --back-trace-limit n
   Display backtrace top n and tail n. The default
   value is 16. 
  --irb_debug n    Set internal debug level to n (not for popular use)
  -v, --version    Print the version of irb
 
这里重点关注几个:
-r xxx
加载一个文件,类似require ‘xxx’
-I
指定LOAD_PATH
--inspect
交互接口默认输出调用obj.inspect的方法,也就是说你不需要调用inspect方法了
 
commands/console的源码
算是比较短的,简单的就添加了注释
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' #看平台

require 'optparse'

options = { :sandbox => false, :irb => irb }
OptionParser.new do |opt|
  opt.banner = "Usage: console [environment] [options]"
  opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
  opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
  opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
  opt.parse!(ARGV)
end

#(1)这里是重点!!
libs =  " -r irb/completion"
libs << %( -r "#{RAILS_ROOT}/config/environment")
libs << " -r console_app"
libs << " -r console_sandbox" if options[:sandbox]
libs << " -r console_with_helpers"

#这里是加载ruby-debug
if options[:debugger]
  begin
    require 'ruby-debug'
    libs << " -r ruby-debug"
    puts "=> Debugger enabled"
  rescue Exception
    puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
    exit
  end
end

#这里是切换console的环境(可以简写)
ENV['RAILS_ENV'] = case ARGV.first
  when "p"; "production"
  when "d"; "development"
  when "t"; "test"
  else
    ARGV.first || ENV['RAILS_ENV'] || 'development'
end

#这里是输出提示
if options[:sandbox]
  puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})"
  puts "Any modifications you make will be rolled back on exit"
else
  puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})"
end

#(2)这里是重点!!
exec "#{options[:irb]} #{libs} --simple-prompt"
 
整个代码,最重要的地方就2处:
#(1)处是拼接irb使用的字符串libs,libs这个名字虽然是正确的,但感觉不贴切。。。
#(2)处是执行这个字符串
最终,如果什么参数也不是用的话,libs字符串是这样的:
稍微改写一点点代码:
puts "="*50
puts libs
puts "="*50
执行并输出:
lijg@lijg-desktop:~/workruby/practice-2.3.5$ ruby script/console 
Loading development environment (Rails 2.3.5)
==================================================
 -r irb/completion -r "/home/lijg/workruby/practice-2.3.5/config/environment" -r console_app -r console_with_helpers
================================================== 
可以看出:
加载了几个文件:
irb/completion,代码提示不全的
config/environment,这个最重要,加载了rails的环境,下面讨论
console_app,下面讨论
console_with_helpers,下面讨论
 
config/environment文件的作用:
代码:
# Be sure to restart your server when you modify this file

# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION

# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')

Rails::Initializer.run do |config|
  
end
可以看出,加载这个文件,即会执行Rails::Initializer.run方法。
Rails::Initializer.run的执行详细,请看:Rails源码阅读(三)Rails::Initializer
这个方法主要作用是:加载rails环境。
 
console_app的作用:
提供了几个可以直接使用的方法:
#1 reload!方法
这个最常用,当修改了env配置的时候,需要重新加载。使用这个方法可以不必退出后在启动。
#2 app
app是个方法(我一直以为是个变量呢,ruby这个算好处么?隐藏起来了)
这个方法,还有个参数,用来重新new一个session
>> app.class
=> ActionController::Integration::Session
#3 new_session
根据代码可知,这个跟app是一样的,只不过是重新new一个新实例。
new_session接受block,可以对session进行一些配置(具体配置后面分析)。
上面的app只对配置了session的host。
 
代码:
require 'active_support/test_case'
require 'action_controller'

# work around the at_exit hook in test/unit, which kills IRB
Test::Unit.run = true if Test::Unit.respond_to?(:run=)

# reference the global "app" instance, created on demand. To recreate the
# instance, pass a non-false value as the parameter.
def app(create=false)
  @app_integration_instance = nil if create
  @app_integration_instance ||= new_session do |sess|
    sess.host! "www.example.com"
  end
end

# create a new session. If a block is given, the new session will be yielded
# to the block before being returned.
def new_session
  session = ActionController::Integration::Session.new
  yield session if block_given?
  session
end

#reloads the environment
def reload!
  puts "Reloading..."
  Dispatcher.cleanup_application
  Dispatcher.reload_application
  true
end
 
console_with_helpers
代码很短:
def helper
  @helper ||= ApplicationController.helpers
end

@controller = ApplicationController.new
 
作用:
#1 helper
也是个方法,定义并返回@helper,返回@helper ||= ApplicationController.helpers
这个helper是ActionView::Base的实例,见下面的代码@helper_proxy = ActionView::Base.new
>>  helper.class
=> ActionView::Base
>> @helper.class
=> ActionView::Base
 
这个好处是,可以使用view中的方法等。例如,helper方法等
例如,想知道view的helper方法check_box_tag和check_box的区别,可以在这里试试看(再也不用老刷页面了)
>> helper.check_box_tag :gender, 'male'
=> "<input id=\"gender\" name=\"gender\" type=\"checkbox\" value=\"male\" />"
>>
>> helper.check_box :user, :gender
=> "
*      <input name=\"user[gender]\" type=\"hidden\" value=\"0\" />
*      <input id=\"user_gender\" name=\"user[gender]\" type=\"checkbox\" value=\"1\" />
*    "
 
ApplicationController.helpers的代码:
      # Provides a proxy to access helpers methods from outside the view.
      def helpers
        unless @helper_proxy
          @helper_proxy = ActionView::Base.new
          @helper_proxy.extend master_helper_module
        else
          @helper_proxy
        end
      end
 
helper使用_2
1)由上面的代码:@helper_proxy.extend master_helper_module 知道,在Controller中用helper,helper_method等生成的helper方法也会加入view中;
2)某个Controller对应的helper也会加入view中;
这样helper方法可以访问ApplicationHelper中的方法。
module ApplicationHelper
  def helper_method_ind_application_helper
    puts "June testing. This is #{__method__}"
  end
end
>> helper.helper_method_ind_application_helper
June testing. This is helper_method_ind_application_helper
=> nil 
3)一般情况下不许要。正常开发中ApplicationController中的helper :all 会被注释掉,否则就可以访问任何helper方法了(应该注掉的)
4)一般情况下不许要。如果要访问某个特定的Controller对应的helper方法,需要直接去include(应该是extend),这样的前提是helper方法是独立的,依赖的参数都传进来,而不是直接使用,例如parameters等。
例如:自己的helper模块
module UsersHelper

  def user_help_1(user_name)
    puts "I am June!"
  end

  def user_help_2
    puts "I am June-Lee!"
  end

end
>> helper.send :extend, UsersHelper
=> #<ActionView::Base:0xb6d04bdc @controller=nil, @_current_render=nil, @assigns_added=nil, @_first_render=nil, @assigns={}, @view_paths=[], @helpers=#<ActionView::Base::ProxyModule:0xb6d04b8c>>
>> helper.user_help_2
I am June-Lee!
=> nil
 
#2 @controller
定义了实例变量@controller可以在控制台使用
代码:
@controller = ApplicationController.new
?> @controller.class
=> ApplicationController
 
好处:可以直接使用ApplicationController的方法等。
例如,在ApplicationController加入一个方法:
  def action_a
    puts "This is action: #{__method__}"
  end
那么可以在控制台调用了:
?> @controller.action_a
This is action: action_a
 
console_sandbox
如果启动console加入参数'-s' 或者 '--sandbox',会再加载console_sandbox文件。
作用:Rollback database modifications on exit.
代码:
ActiveRecord::Base.connection.increment_open_transactions
ActiveRecord::Base.connection.begin_db_transaction
at_exit do
  ActiveRecord::Base.connection.rollback_db_transaction
  ActiveRecord::Base.connection.decrement_open_transactions
end
代码即文档!
 
 
==>>总结: 
#1 加载了rails的配置和组建
boot装载了rails的load path,console加载了rails的配置和组建,另外,为了方便,加载了几个重要的辅助文件:
这样:
就可以直接使用active_record, active_resource, active_support了
尤其是active_support带来了很多好用的方法,在irb里不能使用,console里可以使用了。
#2 console_app
提供了方法:
reload!,#reloads the environment
app,返回一个session,sess.host! "www.example.com"
new_session,返回一个session,host没有设置
#3 console_with_helpers
提供了方法:
helper,返回View实例@helper,可以使用helper方法
@controller,ApplicationController.new,用来使用ApplicationController的资源
 
如果想在console中测试路由(请看原文),有几种方法:
在rails3中,好像已经自动加入了这个方法,可以直接使用*1的方法了,不需要include xxx了
*1 include ActionController::UrlWriter
ruby-1.9.2-p136 :002> app.root_path
   =>"/"
*2 use ActionDispatch::Routing
include ActionDispatch::Routing
include Rails.application.routes.url_helpers

# use routes normally
users_path #=> "/users"
*3 r =Rails.application.routes
>> r.recognize_path "/station/index/42.html"=>{:controller=>"station",:action=>"index",:format=>"html",:id=>"42"}

and see what URL is generated for a given controller/action/parameters combination:

>> r.generate :controller =>:station,:action=>:index,:id=>42=>/station/index/42
 
+
+
+
||
+
+
+
 
 
 
 
 
分享到:
评论

相关推荐

    safer_rails_console:使Rails Console的危险性降低!

    gem 'safer_rails_console' 然后执行: $ bundle install 或将其自己安装为: $ gem install safer_rails_console 将以下行添加到Rails应用程序中“ config / boot.rb”的末尾。 require 'safer_rails_...

    awesome_rails_console, Rails 控制台增强使你的Rails 控制台更加出色.zip

    awesome_rails_console, Rails 控制台增强使你的Rails 控制台更加出色 使你的Rails 控制台非常出色这个 gem 是由使用pry生产,jazz_hands和 jazz_fingers的激发 was 。awesome_rails_console的优点是:减少 gem ...

    redmine自定义插件开发

    红矿(Redmine)是一款基于Ruby on Rails的开源项目管理工具,提供了强大的插件机制,允许开发者创建自己的插件,以满足不同的需求。在本文中,我们将详细介绍如何开发一个红矿自定义插件,包括插件的创建、编辑、...

    Rails101_by_rails4.0

    《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...

    awesome_rails_console:Rails 控制台增强 - 让你的 Rails 控制台很棒

    其余都是可选的) 更简单的提示修改(类似于你已经熟悉的默认提示) 无需担心配置(因为反正没有太多选择)安装宝石档案: gem 'awesome_rails_console' 在终端: bundlerails g awesome_rails_console:install # ...

    rails_console_toolkit:可配置的 Rails 控制台助手

    安装将此行添加到应用程序的 Gemfile 中: gem 'rails_console_toolkit' 然后生成初始化程序: $ bin/rails generate rails_console_toolkit:install或手动编写: # config/initializers/console....

    rails3 和 thinking_sphinx安装

    Thinking Sphinx 是一个为 Rails 应用程序提供全文搜索功能的插件,它将数据库中的数据与 Sphinx 搜索引擎紧密结合,提供高效且高度定制化的搜索体验。 在 Rails3 中集成 Thinking Sphinx,首先你需要确保你的系统...

    rails上传文件_paperclip

    在Ruby on Rails框架中,Paperclip是一个非常流行的用于处理文件上传的库。它提供了一种简单而优雅的方式来管理和处理模型中的附件,如图片、文档等。Paperclip与ActiveRecord紧密集成,使得在Rails应用中添加文件...

    rails_emoji_picker:将表情符号添加到您的应用

    Rails表情符号选择器 表情符号选择器与Rails应用程序的简单集成。 预习 安装 将此行添加到您的应用程序的Gemfile中: gem 'rails_emoji_picker' 用法 运行命令 rails g rails_emoji_picker:install 它将表情符号...

    rails_semantic_logger, Rails 语义记录器用语义记录器替换 Rails 缺省记录器.zip

    rails_semantic_logger, Rails 语义记录器用语义记录器替换 Rails 缺省记录器 Rails 语义记录器 语义记录器用语义记录器替代 Rails 缺省记录器。http://github.com/rocketjob/rails_semantic_logger文档有关完整文档...

    rails_apps_composer, 一个 gem,为 Rails 启动应用程序创建 Rails 应用程序模板.zip

    rails_apps_composer, 一个 gem,为 Rails 启动应用程序创建 Rails 应用程序模板 Rails 应用编辑器 Rails 应用程序编辑器 gem 安装一个 命令行 工具来从"食谱"的Collection 组装 Rails 应用程序。"你可以使用 rails_...

    ama_styles:集中式AMA样式表

    AmaStyles 可以携带和部署AMA资产的宝石。起床并跑步运行bundle install 通过从ama_styles目录... 提交并推送审核并合并使用部署bin/assets ENVIRONMENT deploy (替换环境:暂存,生产)设置一个新的应用程序将gem 'a

    rails_admin_acts_as_list:rails_admin插件以对记录进行排序

    介绍插件,用于对记录进行排序(使用 gem)安装要启用rails_admin_acts_as_list,请将以下内容添加到您的Gemfile : gem 'rails_admin_acts_as_list'gem 'rails_admin' 重要提示: rails_admin_acts_as_list之前必须...

    rails open_flash_chart

    "Rails Open Flash Chart" 是一个基于Ruby on Rails框架的库,用于在Web应用程序中生成交互式的Flash图表。这个库允许开发者轻松地创建各种统计图表,如折线图、柱状图、饼图等,以便更好地可视化数据。由于Flash在...

    Api-rails5_api_tutorial.zip

    Api-rails5_api_tutorial.zip,了解如何在michael hartl的rails 5教程上构建一个现代api立即在rails应用程序中构建一个api!(Rails 5版本),一个api可以被认为是多个软件设备之间通信的指导手册。例如,api可用于web...

    inspinia admin - v2.5 Rails_Full_Version

    "inspinia admin - v2.5 Rails_Full_Version" 是一个基于Rails框架构建的后台管理系统的完整版本。这个系统采用流行的Inspinia Admin模板,提供了丰富的功能和自定义选项,旨在帮助开发者快速构建高效、现代且用户...

    RestFul_Rails_Dev_pdf_v_0.1.zip

    通过阅读这本书的翻译版,开发者不仅能学习到RESTful设计模式,还能掌握Rails框架下实现这些模式的具体方法和技术。无论是初学者还是经验丰富的Rails开发者,都能从中受益匪浅,提升自己的Web开发技能。

    rails-exporter-源码.rar

    《Rails Exporter 源码解析》 Rails Exporter 是一个用于 Rails 应用程序的开源工具,主要用于数据导出功能。源码分析将帮助我们深入理解其内部工作原理,以便更好地利用它来优化我们的应用。 一、Rails 框架基础 ...

    rails_email_preview:在Rails中预览和编辑应用程序邮件模板

    安装加 到Gemfile: gem 'rails_email_preview' , '~&gt; 2.2.2' 添加一个初始化程序和路由: $ rails g rails_email_preview:install 在app / mailer_previews /中生成预览类和方法存根$ rails g rails_email_preview:...

    themes_on_rails, 向 Rails 3/4/5 应用程序添加多个主题支持.zip

    themes_on_rails, 向 Rails 3/4/5 应用程序添加多个主题支持 ThemesOnRails 安装安装最简单的方法是使用 Bundler 。将这里 gem 添加到你的Gemfile:gem 'themes_on_rails'如果要对 liquid 模板使用

Global site tag (gtag.js) - Google Analytics