技术宅改变世界

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

转自:http://www.blogjava.net/cap/articles/rails_controller.html

 

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 跳转页面

posted on 2010-08-10 10:31  treeman  阅读(796)  评论(0编辑  收藏  举报