文章目錄
- active controller
- 命名routes map.xxx
- action方法
- controller環境對象
- response處理
- redirect
- cookies
- session
- flash
- filter
- verification
active controller
model指令 提前load model對象 model :Product
基本對應關係
http://xxx.com/admin/hello/list 對應為app/controllers/admin/hello_controller.rb中的list方法如下 module Admin class Hello def list end end end
ctroller是每次都建立
url自動對應 map.connect
在config/routes.rb中可以定義最底層的url和action對應的關係,這使得rails的url映射可以異常靈活,
預設的映射如下 map.connect ':controller/:action/:id' 他會自動匹配有三段的url請求, 詳細的規則如下
- url按照前置的"/"分段為components
- ":name"會建立以name為名的參數,同時把對應url段賦值給它
- "name" 匹配所有剩下的url段,會建立以name為名的數組,"name"只能出現在最後
- 其他以文本出現字元的均嚴格匹配
map.connect接受的參數如下
- :defaults=>{:name=>'value',...} 設定對應name的url段預設值,比如:action=>'index'
- :requirements=>{:name=>/regexp/,...} 要求對應name的url段必須匹配的Regex
- :name=>value 也是設定預設值, 不過這個對應的name可以自己取, 不一定必須要在url匹配中出現,相當於追加的參數
- :name=>/regexp/ 和:requirements一樣的功能, 設定正則
url自動產生 url_for
和url自動對應對應, rails可以利用map.connect中儲存的資訊來自動構造url,實現友好的url功能如預設設定中, 通過url_for :controller=>"xx",:action=>"fda",:id=>"fdas"可以構造這三個特殊的url段
url_for會根據傳入的url來填寫預設值, 比如url_for(:action=>"fda")會預設:controller為當前的,假設url段為目錄那樣的結構,url_for預設值工作如下: 子目錄變化,他的父級目錄都會填入預設值,但是他的子級目錄都會捨棄, 這裡的變化是值的變化,顯式賦相同的值是沒有變化的
如果要阻止url_for智能預設值,可以顯式的賦最進階目錄為nil,這樣從最高到下的預設值都捨棄了
如果改變了進階,仍然要低級不捨棄, 可以通過url_for(:overwrite_params=>{:xxx=>yyy})來完成, 這樣rails會認為沒有改變, 所有低級目錄段都會填充進來
url_for的擴充參數
- :anchor 指定anchor(頁內聯結),rails會自動添加
#
- :host 指定主機(可以帶連接埠)
- :only_path 只產生path, host, port,protocol都省略
- :protocol 協議名 比如"https://"
- :trailing_slash 在末尾添加"/",注意有報告說末尾有"/"的時候,頁面cache系統有混亂
to_param
實現了to_param的對象, 在傳入url_for的時候, 會自動抽取to_param的值,否則會抽取to_s, rails的model的to_param會自動擷取id
命名routes map.xxx
使用map.xxx 來代替map.connect 可以建立一個xxx的route,這個route還對應了一個xxx_url的方法,使用和url_for一樣,只是規則只針對當前route
action方法
rails會自動把url請求轉寄到對應的controller類的方法中, 這個方法就叫action方法, action方法如果沒有找到,會調用method_missing,傳入action名和空參數列表, 如果沒有action方法調用,rails直接跳轉到action對應的template中實現純view ,如果沒有找到action, 就報錯Unknown Action
隱藏方法: private或者hide_action都可以 注意 如果使用hide_action的目的是想公開private的方法給其他類, 可以考慮使用helpers類來完成, hide_action為下策也
controller環境對象
response處理
三種處理 1.使用view模板輸出 2.直接render文本 3 輸出其他資料(pdf,檔案)
response只能被render一次, 再次render會產生DoubleRenderError 注意 使用erase_render_results可以清除以前的render,但是這個方法無任何保證( undocumented method)
rails檢查render,如果controller執行完畢以後還沒有render,就會去調對應的view,如果render了, 就不掉view了
使用view輸出
模板有.rhtml和.rxml(builder)兩種, 預設在app/views/control/* 中, 預設位置app/views/可以通過ActionController::Base.templdate_root=xxx來更新設定
直接render文本
- render(:text=>string) 直接render出文本
- render(:inline=>string,[:type=>"rhtml"|"rxml"]) 把傳入的string當成模板處理, 相當於rhtml的內容
- render(:action=>action_name) 直接調用某個action的模板,相當於forward到一個view
- render(:file=>path;[:use_full_path=>true|false]) 使用某個模板檔案render, 當use_full_path開啟時可以傳入相對路徑
- render(:template=>name) 使用模板名render ,例子如下 render(:template => "blog/short_list") # 自動使用/app/views/blog/short_list.rhtml(rxml)
- render(:partial=>name) ???
- render(:nothing=>true) 什麼也不輸出,包括layout
- render() 預設的的render, 相當於render(:action=>self)
所有的render都接收:status 和:layout兩個額外參數 :layout為false的時候表示不使用layout, nil和true都表示使用layout :layout為string的時候, 使用string表示的名字的layout
使用render_to_string(用法和render一樣)可以得到輸出的string而不是直接輸出到瀏覽器
輸出其他資料
send_data(data,options...) 支援的options有
- :filename 給瀏覽器建議的檔案名稱
- :type 檔案類型,預設為"application/octet-stream"
- :disposition 給瀏覽器的處理建議,"inline"表示直接顯示,"attachment"表示下載另存
send_file 和send_data一樣, 多了一個參數:streaming,當stream為false的時候,整個檔案被讀入記憶體傳輸,反之則使用:buffer_size傳輸串流
redirect
- redirect_to(:action=>'xxx') 使用文法和url_for一樣(底層用url_for)
- redirect_to("/localpath")
- redirect_to("http://url")
預設的redirect都是tempoary
cookies
cookies必須使用string值 ,如果使用其他value ,可能會有"private method ‘gsub’ called" 這樣的錯誤
cookies的擴充參數 例子如下
cookies[:marsupial] = { :value => "wombat",:expires => 30.days.from_now,:path => "/store" }
- :value 直接的value
- :domain 儲存和訪問的地址
- :expires 到期時間
- :path 和domain共同決定儲存和訪問地址
- :secure 是否只在https//中使用
session
session預設存為檔案的, 可以通過刪除它們實現更新class結構衝突(舊對象和新對象不一樣)
關於session具體配置可以在config/environments中配置,(session到期時間除外)
例子如下
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_key] = 'my_app'
- :database_manager Controls how the session data is stored on the server. We’ll have more to say about this shortly.
- :session_domain The domain of the cookie used to store the session id on the browser. Defaults to the application’s host name.
- :session_id Overrides the default session id. If not set, new sessions automatically have a 32-character key created for them. This key is used in subsequent requests.
- :session_key The name of the cookie used to store the session id. You’ll want to override this in your application, as shown previously.
- :session_path The request path to which this session applies (it’s actually the path of the cookie). The default is /, so it applies to all applications in this domain.
- :session_secure If true, sessions will be enabled only over https://. The default is false.
- :new_session Directly maps to the underlying cookie’s new_session option. However, this option is unlikely to work the way you need it to under Rails,and we’ll discuss an alternative in Section 16.8, Time-Based Expiry of Cached Pages, on page 323.
- :session_expires The absolute time of the expiry of this session. Like :new_session, this option should probably not be used under Rails.
更多設定查閱CGI::Session的文檔
DEFAULT_SESSION_OPTIONS還有一個database_manager能配置session的儲存方式(:database_manager=>xxxx),列表如下
- CGI::Session::PStore 預設的儲存方式,使用marshal
- CGI::Session::ActiveRecordStore 使用ActiveRecord儲存到表中 create table sessions ( id int(11) not null auto_increment, sessid varchar(255), data text, updated_at datetime default NULL, primary key(id), index session_index (sessid) );
- CGI::Session::DRbStore 使用drbserver訪問,內建有一個drb_server.rb
- CGI::Session::MemCacheStore 使用緩衝系統 ???
- CGI::Session::MemoryStore 直接記憶體儲存,不推薦
- CGI::Session::FileStore 直接檔案儲存體,不推薦,只能支援string儲存
設定 ::ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS = false可以禁用所有session以及依賴session的功能(flash)
session儲存方式比較
查看這裡 http://media.pragprog.com/ror/sessions/, 一句話 先用最簡單直接的,等到速度變慢時候認證測量, 然後再決策,不要overkill
session清除
rails目前比較原始, 居然要自己去清除, 寫crontab吧(清檔案, 清table) ???
flash
flash的生命期是兩次request,底層使用session儲存對象 flash.now建立臨時的flash(一個request內) flash.now[:xxx] flash.keep延遲一個request的生命期 flash.keep(:xxx) 或者flash.keep(全部)
filter
before_filter after_filter around_filter
設定filter的參數可以為一個方法symbol :method_a ,一個block 或者一個類, 該類的靜態方法self.filter()會被調用 預設filter作用於當前類的所有action方法和子類的action方法, :only 和 :except用來在controller中包含或者排除action
before_filter 和after_filter預設是添加filter到filter chains最後, 如果要添加到最前使用prepend_before_filter() 和 prepend_after_filter()
before_filter 主要用來作驗證 after_filter 主要用來控制內容(壓縮,替換) around_filter 可以用來記錄時間 設定參數必須為一個類, 該類有before(controller)和after(controller)兩個方法 around_filter XXXFilter.new
around_filter的添加是嵌套的, around_filter A.new,B.new的結果如下 A.before B.before action..... B.after A.after 注意順序和前面兩個filter不一樣
filter 在繼承中的關係
子controller會執行所有父controller的filter,但是父不會執行子的filter
verification
verify指令可以看做一個專門抽出來的filter功能,當verify失敗, 當前action就不會執行了 class BlogController < ApplicationController verify :only => :post_comment, :session => :user_id, :add_flash => { :note => "You must log in to comment"}, :redirect_to => :index #.... end 支援的參數如下啟用條件 :only=>:name or [:name,...] :except=>name or [:name,...] 測試條件 :flash=>:key or [:key,...] flash中必須包含某些key :method=>:symbol or [:symbol,...] 請求必須是某些http 方法 :session=>:key or [:key,...] session中必須包含某些key 執行操作 :add_flash=>hash 把傳入hash的值對寫入flash中 :redirect_to=>params 跳轉頁面