rails on ruby,ruby on rails 之Action Dispatch

Action Pack 是 Rails 应用的核心,包含三个 Ruby 模块:ActionDispatch、ActionController 和 ActionView。 Action Dispatch 负责把请求分派给控制器,就是我我们平时所说的路由; Action Controller 处理请求,得到响应; Action View 供 Action Controller 使用,用于格式化响应。以前一直觉得Dispatch这个名词很是高大上,但是读过《rails 敏捷开发》之后,突然觉得这部分也不是太晦涩。

Rails 对这种接口提供了直接支持,它提供了一个路由宏方法,即 resources。 下面是我们在一个命名空间里面定义了两个路由:

namespace :backend do
  root 'home#index'
  resources :admins, except: %i[show]
end

我们可以利用 rake routes 指令查询resource生成的路由:

backend_root       GET      /backend(.:format)                  backend/home#index
backend_admins     GET      /backend/admins(.:format)           backend/admins#index
new_backend_admin  GET      /backend/admins/new(.:format)       backend/admins#new
                   POST     /backend/admins(.:format)           backend/admins#create
edit_backend_admin GET      /backend/admins/:id/edit(.:format)  backend/admins#edit
backend_admin      PATCH    /backend/admins/:id(.:format)       backend/admins#update
                   PUT      /backend/admins/:id(.:format)       backend/admins#update
                   DELETE   /backend/admins/:id(.:format)       backend/admins#destroy

我们也顺便来看看我们控制器是什么样子的:

def index
   @roles = Role.where(manager_id: current_admin.id)
end

def new
    @admin = Admin.new
end

def create
     @admin = Admin.new(admin_params)
     if @admin.save
       redirect_to backend_admins_url, notice: "Admin was successfully created(register_admin)"
     else
       render :new
     end
end

def edit
    end

def update
    if @role.update(role_params)
      redirect_to backend_admins_url, notice: "Admin was successfully updated."
    else
        render :edit
     end
end

我们首先要来看看301和302重定向状态码的差别。301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于:301 redirect: 301 代表永久性转移(Permanently Moved),302 redirect: 302 代表暂时性转移(Temporarily Moved )。但其实对用户效果是一样,代表某个网页对跳转。

我们来分析一下resource的路由:

resources :products do
get :who_bought, on: :member
end

把请求分派给控制器
简单来说,Web 应用接收浏览器发来的入站请求,处理之后再发出响应。实际上,Rails 提供了两种分派请求的方式:一种是在需要时可以使用的详尽方式,另一种是通常使用的便利 方式。

处理请求
前面我们讨论来如何把Action Dispatch 如何把入站请求分派给应用中适当的代码,这一节讨论代码内部的事情。

控制器处理请求时,(1)会寻找与入站动作同名的公开实例方法,如果找到就会调用那个方法。如果未找到,而控制器实现了 method_missing() 方法,就会调用这个方法,并传入动作名称作为第一个参数,空的参数列表作为第二个参数。(2)如果未找到可调用的方法,控制器会寻找使用当前控制器和动作命名的模板,如果找到就会直接渲染那个模板。如果这些尝试都失败了,则会抛出 AbstractController::ActionNotFound 错误。

控制器为动作提供环境(进而也为动作调用的视图提供环境)。下述方法中有很多能直接访问 URL 或请求中:
的信息。
1. action_name
当前处理的动作的名称。
2. cookies
和请求相关的 cookie。发送响应后,请求对象中的值存储在浏览器的cookie 中。Rails 对会话的支持就基于cookie。
3. headers
一个散列,设定响应使用的 HTTP 首部。默认把 Cache-Control 设为 no-cache。有特殊用途的应用可能需要设定 Content-Type 首部。注意,不要直接在首部中设定 cookie 值,而应该使用 cookie API。
4. params
类似散列的对象,其中包含请求参数(以及路由分派过程中生成的伪参数)。之所以说是类似散列的对象,是因为其中的条目可以通过符号或字符串索引,例如 params[:id] 和params[‘id’] 返回相同的值。符 合习惯的做法是使用符号形式。
5. request
入站请求对象。具有下述属性: request_method 返回请求方法,即 :delete,:get ,:post 或 :put 中的一个。

Rails 会话
首先我想明确rails会话的概念。在这之前,先来回顾一下session和cookie之间的区别:
1:session 在服务器端,cookie 在客户端(浏览器)
2:session 默认被存在在服务器的一个文件里(不是内存)
3:session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了cookie ,同时session也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
4:session 可以放在 文件、数据库、或内存中都可以。
5:用户验证这种场合一般会用 session 因此,维持一个会话的核心就是客户端的唯一标识,即 session id

Rails 是一种类似于散列的结构,可以实现跨请求留存。与原始的cookie不同,会话中可以存储任何对象(只 要对象可以编组),因此特别适合保持 Web 应用的状态信息。比如在当我们编写购物网站的购物车模块时,Rails每次处理请求都会保存购物车,更为重要的是,开始处理入站,开始处理入站请求时,Rails 会恢复那个请求的购物车。有了会话,应用就好像 能记住请求一样。

这就引出一个有趣的问题:在请求之间,这些数据具体存储在哪里呢?一种选择是让服务器把这些数据发给 客户端,存储在 cookie 中。这是 Rails 默认采用的方式,虽然对数据的大小有限制,而且占用了带宽,但是 服务器不用耗费精力管理和清理。注意,会话内容(默认)是加密的,因此用户无法查看也无法篡改。但是我现在公司的项目中,并不是这么做的,而是使用下面的一种方法。

另一种选择是把数据存储在服务器中,这种方式要做很多工作,往往得不偿失。首先,Rails 要跟踪会话。为此,要创建一个(默认)由 32 个十六进制字符构成的键(因此有 16^32 种组合方式),这个键称作会话 ID, 实际上是随机的。Rails 会把这个会话 ID 存储在浏览器的 cookie 中(键为 _session_id),浏览器后续发送的请求带有 cookie,因此 Rails 能再次获得会话 ID。

其次,Rails 要在服务器中持久存储会话数据,并使用会话 ID 索引。收到请求后,Rails 使用会话 ID 在存储 器中查找数据,找到的数据是序列化后的 Ruby 对象。反序列化后,Rails 把结果存入控制器的 session 属性 中,提供给应用代码使用,应用可根据需要添加或修改这些数据。处理完请求后,Rails 会把会话数据再次写入数据存储器,然后坐等浏览器发送的下一次请求。关于添加或者修改session的属性,我们正在做一个登录跳转的实验,后面会将例子列出来。

会话中应该存储些什么呢?可以存储任何你想存储的数据,不过有些限制和注意事项(后面会再补充):

1.一般来说,会话中的对象必须能序列化(使用 Ruby 的 Marshal 模块中的函数),因此不能存储 I/O 对象。

2.别在会话数据中存储大型对象——应该存入数据库,然后在会话中引用。对基于cookie的会话来说这一点尤其重要,因为 cookie 的大小限制为 4 KB。

在这里,我们列出一些会话存储器,当然现在还有很多会话存储器,但是目前只是列出两个:

1.Rails 2.0 起使用的默认会话存储机制。这种存储器存储的是编组后的对象,因此会话中能存储任何可序列 化的数据,但是总量不能超过 4 KB。

session_store = :cookie_store
比如现在写在config/initializers/sessions_store.rb文件中:
Rails.application.config.session_store :cookie_store, key: "#{Rails.env}_apple-service_session"

2.使用 activerecord-session_store gem 2 提供的 ActiveRecordStore 把会话数据存入应用的数据库

session_store = :active_record_store
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值