Rails每周闲碎(三): Controller

本文介绍Rails控制器的多种实用技巧,包括Filter的使用与顺序控制、Ajax重定向、文件流与下载、响应不同格式、安全性设置、参数处理、Session与Cookie管理等。

1. Filter

 

    Filters enable controllers to run shared pre- and post-processing code for its actions. These filters can be used to do authentication, caching, or auditing before the intended action is performed. Or to do localization or output compression after the action has been performed. Filters have access to the request, response, and all the instance variables set by other filters in the chain or by the action (in the case of after filters).

 

    Filter的功能很强大,包括before filter,after filter和aroud filter;filter的类型可以是一个方法,一个proc,也可以是一个类或者对象;filter还可以定制顺序,成为filter chain。

 

   具体详情还是请见:http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html

 

    Filter的顺序

 

    有时候我们会关心filter之间的顺序。比如我们定义了一个transaction filter(around filter),这个filter的作用是在非get的请求上包一个transaction,以保证数据的一致性。

 

    如果我们还定义了一个after filter,它会插入一些新数据或者对数据做一些变更。我们同样希望它能在transaction内,这时候filter之间的顺序就很重要。

 

    对同一类filter,Rails可以定制它们的顺序(请见http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html )。但对不同类filter之间的顺序,rails并没有提供api来定制它们的顺序。就比如上面所提到的一个around filter和一个after filter之间的顺序。

 

    根据观察,它们之间的顺序应该跟声明顺序有关:声明越在前的filter越在filter chain的内部。以上面那个为例,如果transaction filter先于OneAfterFilter定义:

 

 

    OneBeforeFilter#before  
      TransactionFilter#before
        # run the action
      TransactionFilter#after
    OneAfterFilter#after

 

    Transaction并没有把OneAfterFilter包括在内。但这没有保证。所以在使用需要明确顺序的filter时要注意。

 

2. Ajax redirect?

 

   不要奢望用normal http response的那种方式来redirect(通过response header),ajax的机制是不一样的,看看下面这段:

 

   XMLHttpRequest (XHR ) is a DOM API that can be used inside a web browser scripting language , such as JavaScript , to send an HTTP or an HTTPS request directly to a web server and load the server response data directly back into the scripting language [ 1] . Once the data is within the scripting language, it is available as both an XML document, if the response was valid XML markup [ 2] , and as plain text [ 3] . The XML data can be used to manipulate the currently active document in the browser window without the need of the client loading a new web page document. Plain text data can be evaluated within the scripting language to manipulate the document, too; in the example of JavaScript, the plain text may be formatted as JSON by the web server and evaluated within JavaScript to create an object of data for use on the current DOM.

 

   那如何在ajax response中实现redirect?rails的代码很简单:

 

 

render :update do |page|
  page.redirect_to some_path
end

 

  背后的实现:

 

 

def redirect_to(location)
  # some other code
  record "window.location.href = #{url.inspect}"
end

 

 

3. ActionController::Streaming

 

    Methods for sending files and streams to the browser instead of rendering.

     http://guides.rubyonrails.org/action_controller_overview.html#streaming-and-file-downloads

 

     特别注意到上面这个页面中提及的RESTful url的例子,对于下载一个client的pdf的行为,并不需要定义一个新的action:

 

 

class ClientsController < ApplicationController 
  # The user can request to receive this resource as HTML or PDF.  
  def show 
     @client = Client.find(params[:id])  
     respond_to do |format| 
       format.html 
       format.pdf { render :pdf => generate_pdf(@client) } 
     end  
  end 
end 

 

   在config/initializers/mime_types.rb :注册一种mime type:

 

 

Mime::Type.register "application/pdf", :pdf 
 

   url请求:

 

 

GET /clients/1.pdf 
 

 

4 . render :partial => 'shared/search', locals => {:objects => ... }

 

 

   Why do we need locals ? Partial is designed for reuse , so, you donot have to have the same name instance variable in your action, and locals make the reuse possible.

 

 

5. respond_to

 

 

respond_to do |format|
      format.html # do nothing, allow Rails to render index.rhtml
      format.js # do nothing, allow Rails to render index.rjs
      format.xml { render :xml => @some_thing.to_xml }
end

 

    根据HTTP头部的Accept-Type值进行相应操作。

 

6.  Security

 

    在ApplicationController里面有一句

  # See ActionController::RequestForgeryProtection for details
  # Uncomment the :secret if you're not using the cookie session store
  protect_from_forgery # :secret => 'aacb6ea3f7484b1a5b56c2d8f45121c3'

 

   这是对Cross-site request forgery 的一种防御。

 

   对于由rails的一些html helper方法生成的html里面(比如form_for等post相关的html),会自动加上一个hidden的参数authenticity_token:

 

 

<% form_for @user do |f| -%>  
  <%= f.text_field :username %>  
  <%= f.text_field :password -%> 
<% end -%> 
 
<form action="/users/1" method="post"> 
  <input type="hidden" value="67250ab105eb5ad10851c00a5621854a23af5489"  
     name="authenticity_token"/> 
  <!-- fields --> 
</form> 
 

   对于不能自动生成的地方,可以用form_authenticity_token方法生成 authenticity_token。

 

 

7. Access controller information in views.

 

    controller.controller_path => Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat".

    controller.controller_name => Converts the class name from something like "OneModule::TwoModule::NeatController" to "neat".

    controller.controller_class_name  => Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".

 

    Of course, you can access this in the controller directly.

 

8. Parameters

 

   Rails对get和post请求的参数并不做区分。

 

   Rails对Array和Hash类的参数有很方便的支持:

 

 

GET /clients?ids[]=1&ids[]=2&ids[]=3

 

 

<form action="/clients" method="post">  
    <input type="text" name="client[name]" value="Acme" />  
    <input type="text" name="client[phone]" value="12345" />  
    <input type="text" name="client[address][postcode]" value="12345" />  
    <input type="text" name="client[address][city]" value="Carrot City" /> 
</form> 

 

 

    Prameter还有另外一种形式,routes中的parameter。这种参数出现在url中,但不跟上面query string的参数一样:

 

 

map.connect "/clients/:status"

 

    另外,我们有时候需要给每个url都加上一个默认参数:

 

 

class ApplicationController < ActionController::Base 
  # The options parameter is the hash passed in to 'url_for'  
  def default_url_options(options)  
      {:locale => I18n.locale} 
  end 
end 

 

9. Session

 

   http://guides.rubyonrails.org/action_controller_overview.html#session

 

   介绍了几种session存储方式,以及如何配置session存储方式:

 

 

# Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information 
# (create the session table with "rake db:sessions:create") 
# ActionController::Base.session_store = :active_record_store 

 

    最重要的,介绍了CookieStore这种方式:

 

 

# Your secret key for verifying cookie session data integrity. 
# If you change this key, all old sessions will become invalid! 
# Make sure the secret is at least 30 characters and all random, 
# no regular words or you'll be exposed to dictionary attacks. 
ActionController::Base.session = {  
  :key => '_yourappname_session',  
  :secret => '4f50711b8f0f49572...' } 

 

    同时,提到session的获取是一种lazy load的方式,所以不需要因为性能问题在任何时候关闭。

 

 

10. Cookie

 

    http://guides.rubyonrails.org/action_controller_overview.html#cookies

 

    介绍了cookie的add和remove,跟session一样,它也可以像一个hash一样处理。

 

11. Verification

 

    http://guides.rubyonrails.org/action_controller_overview.html#verification

 

 

class LoginsController < ApplicationController 
  verify :params => [:username, :password],  
           :render => {:action => "new"},  
           :add_flash => {  :error => "Username and password required to log in"  },  
            :only => :create # Run only for the "create" action 
end 

 

12. Rescue

 

   匹配exception和错误页面。

 

   http://guides.rubyonrails.org/action_controller_overview.html#rescue

 

13. head

 

     returns a response that has no content (merely headers): http://api.rubyonrails.org/classes/ActionController/Base.html#M000660

 

 

标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值