Як зробити частку іншого формату в Rails?


114

Я намагаюся створити відповідь JSON, яка включає деякий HTML. Таким чином, я маю /app/views/foo/bar.json.erb:

{
  someKey: 'some value',
  someHTML: "<%= h render(:partial => '/foo/baz') -%>"
}

Я хочу, щоб це відображалося /app/views/foo/_baz.html.erb, але воно буде лише рендерінгом /app/views/foo/_baz.json.erb. Проходження :format => 'html'не допомагає.


Назва питання набагато загальніша, ніж особлива проблема Джеймса. Якщо ви шукаєте інші рішення, подивися тут: stackoverflow.com/questions/7616097 / ...
miguelsan

Відповіді:


100

Починаючи з Rails 3.2.3, при виклику візуалізації: частковий (працює лише поза respond_toблоком).

render formats: [ :html ]

замість

render format: 'html'

Я здогадуюсь, що залежно від контексту можуть бути різні "найкращі" відповіді, тому важко змістовно піднести це питання, але це заповнило мою потребу в простому відтворенні HTML-шаблону з одного однойменного RJS після того, як сподівався, що :formatпараметр буде робота. Дякую!
чес

1
Це також працює для Rails 5.0.2. Однак зауважте, що вам може знадобитися також вказати :content_typeваріант у деяких випадках - наприклад, надання HTML-шаблону зсередини format.pdfблоку може бути здійснено лише за допомогою render "template", formats: [:html], content_type: "text/html". Мені це потрібно, тому що я дозволяю безпосередньо завантажувати зразки моїх книг лише для членів мого списку електронних листів - регулярні відвідувачі отримують замість нього форму реєстрації.
Майкл Троянек

64

Що не так з

render :partial => '/foo/baz.html.erb'

? Я щойно спробував це зробити HTML ERB частковою з шаблону для побудови Atom, і він працював чудово. Не потрібно возитися з глобальними змінними (так, я знаю, що перед ними є "@", але це те, що вони є).

Однак ваш with_format &blockпідхід є класним і має перевагу в тому, що ви лише вказуєте формат, тоді як простий підхід визначає також механізм шаблону (ERB / ​​builder / тощо).


26
Єдиним недоліком цього є те, що якщо ваша часткова передасть інші партії, вона вийде з ладу, якщо ви не ввійдете і не зміните всі часткові дзвінки на надання, щоб на їх ім’я було вказано ".html.erb".
chrisrbailey

4
не потрібно вказувати двигун шаблону, щоб це працювало. (Принаймні, на рейки 3). Такі відмінно спрацьовують: візуалізація (: часткова => "baz.html")
Тім Харпер

1
Не працює, якщо у вас різні партії для різних локалів (наприклад baz.en.html.erb, baz.fr.html.erb), і ви хочете, render :partialщоб логіка вибирала потрібну (з резервними копіями тощо).
Іван

1
Станом на рейки 3.2.3, я бачу таке попередження при використанні цього рішення:DEPRECATION WARNING: Passing a template handler in the template name is deprecated. You can simply remove the handler name or pass render :handlers => [:erb] instead.
YWCA Привіт,

3
Недоліком такого підходу є те, що foo.baz.html.[your_string]замість них будуть шукати локалізації foo.baz.[your_string]. Відповідь zgchurc - краще рішення.
mbillard

32

Для Rails 3 блок with_format працює, але він трохи інший:

  def with_format(format, &block)
    old_formats = formats
    self.formats = [format]
    block.call
    self.formats = old_formats
    nil
  end

Працює з рейками 3.2.0 теж :)
gucki

32

Рейки 4 дозволять вам передати параметр форматів. Так ви можете зробити

render(:partial => 'form', :formats => [:html])} 

Зауважте, що ви можете зробити щось подібне в Rails 3, але він не передав би цей формат жодним підпартіям (якщо форма викликає інші партії).

Ви можете мати здатність Rails 4 у ​​Rails 3, створивши config / inicijalizers / renderer.rb:

class ActionView::PartialRenderer
  private
  def setup_with_formats(context, options, block)
    formats = Array(options[:formats])
    @lookup_context.formats = formats | @lookup_context.formats
    setup_without_formats(context, options, block)
  end

  alias_method_chain :setup, :formats
end

Дивіться http://railsguides.net/2012/08/29/rails3-does-not-render-partial-for-specific-format/


дивно, мені цікаво, чому це не працює для мене в додатку Rails 3.2.19, цікаво, що в моєму додатку має різницю. Неможливо отримати візуалізацію ActionView: частковою для дотримання: аргументів форматів, схоже, зовсім не має значення, навіть із цим патчем.
jrochkind

29

Спираючись на відповідь ронінека , я знайшов найкращим рішенням таке:

в /app/helpers/application.rb:

def with_format(format, &block)
  old_format = @template_format
  @template_format = format
  result = block.call
  @template_format = old_format
  return result
end

В /app/views/foo/bar.json:

<% with_format('html') do %>
  <%= h render(:partial => '/foo/baz') %>
<% end %>

Альтернативним рішенням було б переосмислити renderприйняття а:format параметра.

Я не зміг дістатися render :fileдо роботи з місцевими жителями і без певної негідності.


8
занадто хакерський на мій смак. Краще вказати все розширення.
Тім Харпер

1
Для рейок 3 див. Відповідь zgchurch.
lillq

25

У Rails 3 View має масив форматів, це означає, що ви можете встановити його для пошуку [: mobile,: html]. Налаштування за замовчуванням шукати: мобільні шаблони, але повернутися до: html-шаблонів. Ефекти від цього встановитимуться на внутрішні частки.

Найкращий, але все-таки хибний спосіб, який я міг би встановити для цього, - це ставити цю лінію у верхній частині кожного повного шаблону для мобільних пристроїв (але не з партій).

<% self.formats = [:mobile, :html] %>

Недолік у тому, що вам потрібно додати цей рядок до кількох шаблонів. Якщо хтось знає спосіб встановити це один раз, з application_controller.rb, я хотів би це знати. На жаль, це не працює, щоб додати цю лінію до вашого мобільного макета, оскільки шаблони надаються перед макетом.


Дякую за пояснення цього. Я в кінцевому підсумку використовував його в інших місцях: stackoverflow.com/questions/47459724/…
Джошуа Пінтер

16

Якраз детальніше пояснюючи те, що zgchurch написав:

  • враховуючи винятки
  • повернення результату викликаного блоку

Думав, що це може бути корисно.

def with_format(format, &block)
  old_formats = formats
  begin
    self.formats = [format]
    return block.call
  ensure
    self.formats = old_formats
  end
end

10

У вас є два варіанти:

1) використання render :file

render :file => "foo/_baz.json.erb"

2) змінити формат шаблону на HTML, встановивши змінну @template_format

<% @template_format = "html" %>
<%= h render(:partial => '/foo/baz') %>

1
<% @template_format = "html"%> працював на мене, оскільки мої часткові завантажені інші партії мені не довелося оновлювати інші рендери вниз по ланцюгу.
pagetribe

5

У мене був файл з назвою "api / item.rabl", і я хотів вивести його з перегляду HTML, тому мені довелося використовувати:

render file: 'api/item', formats: [:json]

( fileтому що в файлі немає підкреслення в імені, formatsа не format(і проходить і масив))


2

Здається, що передача formatsопції призведе до належного її використання в новій версії Rails, щонайменше, 3.2:

{
  someKey: 'some value',
  someHTML: "<%= h render('baz', formats: :html) -%>"
}

1

Я натрапив на цю тему, коли я намагався зробити частку XML в іншому файлі перегляду xml.builder. Далі - це приємний спосіб зробити це

xml.items :type => "array" do
    @items.each do |item|
        xml << render(:partial => 'shared/partial.xml.builder', :locals => { :item => item })
    end
end

І так ... Тут також працює повна назва файлу ...


Це страждає від тієї самої внутрішньої-часткової проблеми, яку @chrisrbailey згадував в іншій відповіді: якщо частинка, яку ви викликаєте, з повним іменем файлу, сама використовує партії (не вказуючи повне ім'я файлу для кожного), вона вийде з ладу.
Джеймс А. Росен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.