|
說ruby是怪異的語法有點(diǎn)不妥當(dāng),動(dòng)態(tài)語言里面不乏這樣的語法出現(xiàn)。但是看了一些源碼后發(fā)現(xiàn),使用ruby的用法真的各有不同,就像大家以前說的,ruby每個(gè)人寫出來的可能都不同。 現(xiàn)來說Rails里面如何加載config的吧。 在java里面config絕對(duì)是一個(gè)resource文件,然后通過讀取配置的工具加入進(jìn)來,在分析處理。 在ROR里面完全不是這么回事。 1.首先大家要了解的是,在我們啟動(dòng) ruby script/server 的時(shí)候,rails做了一系列的處理,最后他執(zhí)行了environment.rb ruby 代碼
Rails::Initializer.run do | config | # 這里能插入我們自己的配置。 # config. 之類 end 這里的config其實(shí)是Initializer內(nèi)部的一個(gè)變量,掌控全局的配置信息,我們可以使用這個(gè)config來配置我們想要的。Rails::Initializer.run的源碼是這樣的,yield再一次顯示了他的威力,讓我們?cè)谂渲梦募械靡耘渲胏onfig。然后實(shí)例化了一個(gè)initializer 之后,把config作為參數(shù)傳入了。 ruby 代碼
def self.run(command = :process, configuration = Configuration.new) yield configuration if block_given? initializer = new configuration initializer.send(command) initializer end 我們接著往下走,可以看到initializer 做了一系列的初始化工作,包括load_path的設(shè)定,路由的初始化,和activerecord的初始化。我們關(guān)心的還是配置如何起作用,那么來看看environments目錄下面的配置文件是如何導(dǎo)入的吧。 ruby 代碼
def load_environment silence_warnings do config = configuration constants = self. class .constants eval(IO.read(configuration.environment_path), binding) (self. class .constants - constants).each do | const | Object.const_set(const, self. class .const_get(const)) end end end IO.read(configuration.environment_path) ,,這里就不使用什么回調(diào)不回調(diào)了,而是干脆IO拿出來eval一把,這里也是吃了一驚,這樣也可以呀~~~~~~~然后,我們可以看看,他處理常量的方法,把自己配置文件中的常量全部放入Object里面,起到全局常量的目的。 最絕的還是initialize_framework_settings,使用了有一個(gè)ruby的技巧。 ruby 代碼
def initialize_framework_settings configuration.frameworks.each do | framework | base_class = framework.to_s.camelize.constantize.const_get( " Base " ) configuration.send(framework).each do | setting, value | base_class.send( " #{setting}= " , value) end end end configuration.frameworks里面存放的是rails個(gè)個(gè)組件的名字,比方說active_record之類。然后把這個(gè)名字大寫轉(zhuǎn)換,然后用constantize取得ActiveRecord這個(gè)Module(注意,這些東在都在activerecord里面呢,activesupport/lib/active_support/core_ext/string/inflections.rb )。然后用const_get取得這個(gè)模塊的Base類,也就是ActiveRecord::Base這個(gè)類了(下面都叫做Base類),所有的Rails的組件都是這個(gè)命名規(guī)則改天我們自己想要做一個(gè)Rails的組件加進(jìn)來,也可以這樣(但是要稍微修改一個(gè)源碼)。 然后,我們吧config里面的內(nèi)容給Base類。configuration.send(framework)是調(diào)用一個(gè)組件名稱的方法,比方說active_record,就是去的config里面的active_record屬性(這是最基本的),通過后面的do我們可以看到config返回的是一個(gè)hash,然后把hash中每一個(gè)key作為變量,value為傳入值,傳入Base類。。。這里大家應(yīng)該沒什么問題了,看看我們的config文件是怎么寫的吧。 ruby 代碼
# Settings specified here will take precedence over those in config/environment.rb # In the development environment your application‘s code is reloaded on # every request. This slows down response time but is perfect for development # since you don‘t have to restart the webserver when you make code changes. config.cache_classes = false # Log error messages when you accidentally call methods on nil. config.whiny_nils = true # Enable the breakpoint server that script/breakpointer connects to config.breakpoint_server = true # Show full error reports and disable caching config.action_controller.consider_all_requests_local = true config.action_controller.perform_caching = false config.action_view.cache_template_extensions = false config.action_view.debug_rjs = true # Don‘t care if the mailer can‘t send config.action_mailer.raise_delivery_errors = false 哦,看著很暈吧,config就是我們的配置對(duì)象,按照我們上面的說法,config.action_view之類framework的變量應(yīng)該是一個(gè)hash才對(duì)呀,如果是hash的話,不應(yīng)該用這樣的方式傳入,可能會(huì)用 config.action_view = {:debug_rjs => true}來傳入。 OK.我們來看這個(gè)變量到底是什么樣的hash。 ruby 代碼
def initialize . . for framework in default_frameworks self.send( " #{framework}= " , OrderedOptions.new) end end 在初始化這些變量的時(shí)候,Rails給他賦值為OrderedOptions.new。這個(gè)特殊的類型可能就是關(guān)鍵。 ruby 代碼
class OrderedOptions < OrderedHash # :nodoc: def [] = (key, value) super(key.to_sym, value) end def [](key) super(key.to_sym) end def method_missing(name, * args) if name.to_s =~ / (. * ) = $ / self[$ 1 .to_sym] = args.first else self[name] end end end 看到其中的玄妙了么,method_missing~~~??! 如果調(diào)用一個(gè)**=的方法 ,就像當(dāng)用傳入一個(gè)HASH的值,key就是方法的名字。 也就是:config.action_view.debug_rjs = true 相當(dāng)于config.action_view[:debug_rjs] = true OK ,大體上描述了一下,可以看到簡(jiǎn)單的一個(gè)Rails初始化已經(jīng)給我們展示了幾乎全部ruby的靚麗之處,這能說明,這個(gè)亮點(diǎn)肯定是貫穿rails的基本,在以后的深入研究中我們就能看到了。 |
|
|