差沙的密碼 -- SSHWSFC's code
          閱讀本Blog請自備塑料袋一只
          posts - 14,  comments - 59,  trackbacks - 0

          說ruby是怪異的語法有點不妥當,動態語言里面不乏這樣的語法出現。但是看了一些源碼后發現,使用ruby的用法真的各有不同,就像大家以前說的,ruby每個人寫出來的可能都不同。

          現來說Rails里面如何加載config的吧。

          在java里面config絕對是一個resource文件,然后通過讀取配置的工具加入進來,在分析處理。

          在ROR里面完全不是這么回事。

          1.首先大家要了解的是,在我們啟動 ruby script/server 的時候,rails做了一系列的處理,最后他執行了environment.rb

          ruby 代碼
          Rails::Initializer.run?do? | config | ????
          ??
          # ?這里能插入我們自己的配置。????
          ?? # ?config.?之類????
          end???

          這里的config其實是Initializer內部的一個變量,掌控全局的配置信息,我們可以使用這個config來配置我們想要的。Rails::Initializer.run的源碼是這樣的,yield再一次顯示了他的威力,讓我們在配置文件中得以配置config。然后實例化了一個initializer?之后,把config作為參數傳入了。

          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的設定,路由的初始化,和activerecord的初始化。我們關心的還是配置如何起作用,那么來看看environments目錄下面的配置文件是如何導入的吧。

          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) ,,這里就不使用什么回調不回調了,而是干脆IO拿出來eval一把,這里也是吃了一驚,這樣也可以呀~~~~~~~然后,我們可以看看,他處理常量的方法,把自己配置文件中的常量全部放入Object里面,起到全局常量的目的。

          最絕的還是initialize_framework_settings,使用了有一個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個個組件的名字,比方說active_record之類。然后把這個名字大寫轉換,然后用constantize取得ActiveRecord這個Module(注意,這些東西都在activesupport里面呢,activesupport/lib/active_support/core_ext/string/inflections.rb )。然后用const_get取得這個模塊的Base類,也就是ActiveRecord::Base這個類了(下面都叫做Base類),所有的Rails的組件都是這個命名規則改天我們自己想要做一個Rails的組件加進來,也可以這樣(但是要稍微修改一個源碼)。

          然后,我們吧config里面的內容給Base類。configuration.send(framework)是調用一個組件名稱的方法,比方說active_record,就是去的config里面的active_record屬性(這是最基本的),通過后面的do我們可以看到config返回的是一個hash,然后把hash中每一個key作為變量,value為傳入值,傳入Base類。。。這里大家應該沒什么問題了,看看我們的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就是我們的配置對象,按照我們上面的說法,config.action_view之類framework的變量應該是一個hash才對呀,如果是hash的話,不應該用這樣的方式傳入,可能會用 config.action_view = {:debug_rjs => true}來傳入。

          OK.我們來看這個變量到底是什么樣的hash。

          ruby 代碼
          def ?initialize????
          ??.????
          ??.????
          ??
          for ?framework? in ?default_frameworks????
          ????self.send(
          " #{framework}= " ,?OrderedOptions.new)????
          ??end???
          end???

          在初始化這些變量的時候,Rails給他賦值為OrderedOptions.new。這個特殊的類型可能就是關鍵。

          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~~~?。?如果調用一個**=的方法 ,就像當用傳入一個HASH的值,key就是方法的名字。

          也就是:config.action_view.debug_rjs??=?true?相當于config.action_view[:debug_rjs] = true

          OK ,大體上描述了一下,可以看到簡單的一個Rails初始化已經給我們展示了幾乎全部ruby的靚麗之處,這能說明,這個亮點肯定是貫穿rails的基本,在以后的深入研究中我們就能看到了。

          posted on 2006-11-21 12:10 差沙 閱讀(3752) 評論(2)  編輯  收藏 所屬分類: ROR

          FeedBack:
          # re: 說說Rails吧,config的幕后工作
          2008-07-05 15:46 |
          撒卡拉 ;大大怕怕;;發撒;  回復  更多評論
            
          # re: 說說Rails吧,config的幕后工作
          2008-07-05 15:47 |
          看到其中的玄妙了么,method_missing~~~??! 如果調用一個**=的方法 ,就像當用傳入一個HASH的值,key就是方法的名字。

          也就是:config.action_view.debug_rjs = true 相當于config.action_view[:debug_rjs] = true

          OK ,大體上描述了一下,可以看到簡單的一個Rails初始化已經給我們展示了幾乎全部ruby的靚麗之處,這能說明,這個亮點肯定是貫穿rails的基本,在以后的深入研究中我們就能看到了。

            回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          這家伙很懶,但起碼還是寫了一句話。

          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(8)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 怀宁县| 东台市| 赫章县| 肥东县| 太保市| 翼城县| 周口市| 孟州市| 沈丘县| 乌兰察布市| 广丰县| 扬中市| 乳源| 盐边县| 大港区| 通江县| 北宁市| 海南省| 六盘水市| 潞城市| 东方市| 中宁县| 山东省| 洛川县| 潍坊市| 南阳市| 金昌市| 专栏| 大洼县| 泰顺县| 浮梁县| 邓州市| 贵溪市| 四会市| 英山县| 衡阳县| 嵊泗县| 邢台市| 吉木乃县| 昌宁县| 怀宁县|