2012-02-08 96 views
3

在Rails中使用respond_to而不是case語句有什麼好處? 我有幾個實例變量,我想爲某些格式設置相同的方式,但不適用於HTML。這似乎並不工作:Rails:respond_to vs「case」conditional

respond_to do |format| 
    format.html do 
    # ... 
    end 
    format.any(:csv, :xml) do 
    # common stuff 
    end 
    format.csv do 
    # ... 
    end 
    format.xml do 
    # ... 
    end 
end 

我想我會最終使用了幾個case request.format,而不是使用respond_to都:

case request.format 
when 'html' 
    # ... 
when 'csv', 'xml' 
    # common stuff 
end 
# more common stuff 
case request.format 
when 'html' 
    # render 
when 'csv' 
    # custom render csv 
when 'xml' 
    # render xml with a template 
end 

所以我不知道什麼是很好用案例爲respond_to,其中case request.format看起來不會更好?

回答

8

respond_to不僅僅是找出什麼類型的響應客戶預期,但也有辦法告訴你rails願意提供何種類型的反應的一種方式。

例如一個簡單的場景,我們有此控制器:

class SimpleController < ApplicationController 
    def index 
    respond_to :html, :json 
    end 
end 

客戶端發送請求期望XML響應

curl -H "Accept: application/xml" \ 
    -H "Content-Type: application/xml" \ 
    -X GET "host:port/simple/index" 

Rails會響應與406

Completed 406 Not Acceptable in 0ms (ActiveRecord: 0.0ms) 

然而,如果您只是使用過濾就像在你的例子中,客戶端將收到一個500錯誤,因爲rails無法找到相應的請求格式模板。

當然,你也可以撥打respond_to水平以及在routes.rb中指定響應格式

潛入rails源代碼和API文檔,如果你想獲得更深入的解釋對此。

+0

我很懶,現在就試試,你的意思是'respond_to do | f | f.html; f.json end'也會告訴Rails在你的例子中以406錯誤迴應? (在你的例子中,它是'respond_to:html,:json') – Alexey 2013-09-15 13:02:32

+0

是的,所以respond_to需要** ** block或者'mime types'數組 – j03w 2013-09-15 23:39:16

0

我一直在使用Rails了一段時間,我一直看到的respond_to這種形式:

respond_to do |format| 
    format.js 
    format.html # index.html.erb 
    format.xml { render :xml => @posts } 
end 

我不知道你會看到與嵌套做的事。

編輯:

對於分頁,見

https://github.com/mislav/will_paginate

編輯2:

format.html { render :html => Post.paginate(:page => params[:page]) } 

或類似的東西。

+0

好吧,我同意,在這個基本情況下,它看起來更簡潔'case'request.format當'html'呈現...'但如果我想分頁的記錄列表,似乎很自然只能分頁html格式,所以我會把'format.html {...}'分頁。 – Alexey 2012-02-08 16:28:41

+0

查看更新的分頁評論。 – varatis 2012-02-08 16:51:36

+2

你可以使用'do'和'end'來代替'{'和'}'。這沒什麼不尋常的。 – shime 2012-02-08 16:55:04

2

request.format字段在respond_to塊不合適的情況下非常有用。

例如,我使用的是sunspot寶石可用於搜索,我的控制器看起來像這樣:

def index 
    case request.format 
    when 'xlsx' 
    per_page: Person.count 
    when 'html' 
    per_page: 30 
    end 
    @search = Person.search do 
    with :name, params[:name] 
    fulltext params[:search_term] 
    paginate page: params[:page], per_page: per_page 
    end 
    @people = @search.results 
    respond_to do |format| 
    format.xlsx {send_file @people.to_xlsx, filename: 'people.xlsx'} 
    format.html 
    end 
end 
3

首先,在respond_to塊不工作的原因是因爲您在使用format.any(:csv, :xml)format.csv一起。你只能使用其中之一。

這應該清楚地表明您試圖在控制器中執行太多操作。例如,如果你正在做普通的東西爲csvxml響應,那麼也許你應該在你的lib目錄下創建一個類:

# lib/foo_serializer.rb 
class FooSerializer 
    def initialize(bar) 
    @bar = bar 
    end 

    def do_stuff 
    @bar.to_s 
    end 
end 

,然後調用其方法之一爲每種類型的反應:

respond_to do |format| 
    format.html do 
    # ... 
    end 
    format.csv do 
    FooSerializer.new(data).do_stuff 
    # ... 
    end 
    format.xml do 
    FooSerializer.new(data).do_stuff 
    # ... 
    end 
end 

respond_to語法:

  1. 是該標準的Rails之路的一部分™

  2. 負責渲染正確的文件的

  3. 不僅看起來更好,但也更容易維護

你應該努力堅持下去。