rails笔记 active controller
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段必须匹配的正则表达式
- :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环境对象
-
request
- domain() 主机名
- remote_ip() 远程ip
- env 访问浏览器传过来的参数
- method http请求方法 :delete, :get,:head,:post,:put
- delete?,get?,head?,post?,put? 返回true or false
-
params 相当于jsp.parametermap,类似hash.使用params[:xxx]和params['xxx']等价, 推荐前者
- cookies 和params类似
- response 一般不用到它, 在filter中可能用到
- session
- headers 输出给浏览器的HEADER
- 还有一个logger对象
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 跳转页面