Rails: response_to против условного "case" - PullRequest
3 голосов
/ 08 февраля 2012

В чем преимущество использования respond_to в Rails вместо оператора case?У меня есть несколько переменных экземпляра, которые я хочу установить одинаковым образом для некоторых форматов, но не для HTML.Кажется, это не работает:

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 не будет выглядеть лучше?

Ответы [ 4 ]

8 голосов
/ 15 сентября 2013

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)

Однако, если вы просто отфильтруете request.format, используя case, как в вашем примере, клиент получит ошибку 500, поскольку rails не может найти соответствующий шаблон для формата запроса.

Конечно, вы также можете вызвать respond_to на уровне class , а также указать формат ответа в rout.rb

Погружение в rails исходный код и APIдокументация, если вы хотите получить более подробное объяснение этому.

3 голосов
/ 12 сентября 2013

Прежде всего, причина того, что блок respond_to не работает, заключается в том, что вы используете format.any(:csv, :xml) в сочетании с format.csv. Вы можете использовать только один из них.

Это должно быть четким признаком того, что вы пытаетесь сделать слишком много в своем контроллере. Например, если вы делаете обычные вещи для ответов csv и xml, то, возможно, вам следует создать класс в каталоге 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 Way ™

  2. Заботится о рендеринге правильного файла

  3. Не только выглядит лучше, но и более удобен в обслуживании

Вы должны попытаться придерживаться этого.

2 голосов
/ 28 февраля 2013

Поле 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
0 голосов
/ 08 февраля 2012

Я работаю с Rails некоторое время, и я всегда видел response_to в этой форме:

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

Я не знаю, где вы могли бы увидеть что-то с вложенным do.

РЕДАКТИРОВАТЬ:

Для нумерации страниц см.

https://github.com/mislav/will_paginate

РЕДАКТИРОВАТЬ 2:

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

или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...