2008年1月23日星期三

Rails Environments and Configuration

Whenever you start a process to handle requests with Rails (such as a Webrick server), one of the first things that happens is that config/environment.rb is loaded. For instance, take a look at the top of public/dispatch.rb:
require File.dirname(__FILE__) + “/../config/environment”

A word of caution: If you were to set the RAILS_ENV environment variable to production here, or the constant variable RAILS_ENV for that matter, it would cause everything you did in Rails to run in production mode. For instance, your test suite would not work correctly, since test_helper.rb sets RAILS_ENV to test right before loading the environment.

因为在test/test_helper.rb中,先是:
ENV["RAILS_ENV"] = "test"
再是:
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
而在加载environment.rb时,又将RAILS_ENV覆写为prodoction。

项目中使用的Rails的版本:
# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.0.1' unless defined? RAILS_GEM_VERSION

定义项目根目录:
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)

RAILS_ROOT is used all over the place in the Rails codebase for finding files


read the config/environment.rb file as text (minus the commented lines) and parse out the RAILS_GEM_VERSION setting with a regexp.


parse_gem_version(read_environment_rb)

def parse_gem_version(text)
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*'([!~<>=]*\s*[\d.]+)'/
end

def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end

Default Load Paths:

def default_frameworks
[ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
end

def default_load_paths
paths = ["#{root_path}/test/mocks/#{environment}"]

# Add the app's controller directory
paths.concat(Dir["#{root_path}/app/controllers/"])

# Then components subdirectories.
paths.concat(Dir["#{root_path}/components/[_a-z]*"])

# Followed by the standard includes.
paths.concat %w(
app
app/models
app/controllers
app/helpers
app/services
components
config
lib
vendor
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }

paths.concat builtin_directories
end

def builtin_directories
# Include builtins only in the development environment.
(environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
end

def default_plugin_paths
["#{root_path}/vendor/plugins"]
end

上面这个builtin_directories指的是:

It is the place for Rails to include application behavior (meaning models, helpers, and controllers). You can think about it as kind of like a framework-provided plugin mechanism.


http://localhost:3000/rails/info/properties
和在命令行下用script/about是一样的

在Rails项目里,绝大多数情况下,都不需要手动去load一个class或module,Rails有默认的规则去自动load需要的文件,其规则如下:
• If the class or module is not nested, insert an underscore between the constant’s names and require a file of this name. For example:
EstimationCalculator becomes require ‘estimation_calculator’
• If the class or module is nested, Rails inserts an underscore between each of the containing modules and requires a file in the corresponding set of subdirectories.For example:
MacGyver::SwissArmyKnife becomes require ‘mac_gyver/swiss_army_knife’

you should rarely need to explicitly load Ruby code in your Rails applications (using require) if you follow the naming conventions.

哈哈,顺我者昌

Rails::Initializer.run do |config|
...
end
里面的代码是关于Configuration的

# Settings in config/environments/* take precedence over those specified here.

The comment reminds you that the settings in the mode-specific environment files will take precedence over settings in environment.rb, which is essentially because they are loaded afterward and will overwrite your settings.


# Skip frameworks you're not going to use (only works if using vendor/rails).
# To use Rails without a database, you must remove the Active Record framework
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
如果项目中不用数据库,就去掉Active Record,如果不用Web service或Email,也去掉相应的模块
为什么要去掉呢:

Ruby is, of course, interpreted, and if you can get away with a smallersized codebase for the interpreter to parse, you should do so, simply for performance reasons.


# Only load the plugins named here, in the order given. By default, all plugins
# in vendor/plugins are loaded in alphabetical order.
# :all can be used as a placeholder for all plugins not explicitly named
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
plugins默认是按照字母顺序load的,也可以指定先load哪些plugin,再load剩下的(:all)

Rails takes advantage of the fact that Ruby provides a callback mechanism for missing constants. When Rails encounters an undefined constant in the code, it uses a classloader routine based on file-naming conventions to find and require the needed Ruby script.

利用Ruby提供的"missing constants"回调机制,Rails根据命名惯例去找对应的文件来load。

Want to see the contents of your project’s load path? Just fire up the console and type $:

想看项目里的load path的话,就script/console,然后敲$:(注意加上后面的冒号),然后load path就打出来了,一长串。$:是一个数组。

除了Rails提供的三种environment外,还可以自定义environment,比如:

Use the normal environment settings for development mode, but point its database connection to a production database server. It’s a potentially life-saving combination when you need to quickly diagnose issues in production.

可以用来快速诊断生产环境的问题。

使用log的方法:在irb里敲入:

require ‘logger’

logger = Logger.new STDOUT

logger.warn “do not want!!!”


log的级别(按严重程度由低到高):
debug -> info -> warn -> error -> fatal
debug是开发时方便调试程序的,生产环境中用不到。
info是一些不常发生的事件,但仍然属于正常行为范围内。
warn表示正常范畴之外的事件发生了,需要注意,值得去研究研究问题,例如:
def create
begin
@group.add_member(current_user)
flash[:notice] = “Successfully joined #{@scene.display_name}”
rescue ActiveRecord::RecordInvalid
flash[:error] = “You are already a member of #{@group.name}”
logger.warn “A user tried to join a group twice. UI should not have allowed it.”
end

redirect_to :back
end
error表示还不需要重启服务器的错误。
fatal是指能想到的最坏的情况已经发生了,你的应用现在已经挂了,需要重启服务器了。

清空log/目录下的所有.log文件

rake log:clear


development.log里包含的信息:

• The controller and action that were invoked
• The remote IP address of the computer making the request
• A timestamp indicating when the request happened
• The session ID associated with the request
• The hash of parameters associated with the request
• Database request information including the time and the SQL statement executed
• Query cache hit info including time and the SQL statement triggering results from the cache instead of a roundtrip to the database
• Rendering information for each template involved in rendering the view output and time consumed by each
• Total time used in completing the request with corresponding request-per-second figures
• Analysis of the time spent in database operations versus rendering
• The HTTP status code and URL of the response sent back to the client


资源/链接:
Rails Plugins: Extending Rails Beyond the Core
http://weblog.jamisbuck.org/2007/1/31/more-on-watchingactiverecord
http://seattlerb.rubyforge.org/SyslogLogger/

没有评论: