Làm cách nào để hiển thị một phần của định dạng khác trong Rails?


114

Tôi đang cố tạo phản hồi JSON bao gồm một số HTML. Vì vậy, tôi có /app/views/foo/bar.json.erb:

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

Tôi muốn nó hiển thị /app/views/foo/_baz.html.erb, nhưng nó sẽ chỉ hiển thị /app/views/foo/_baz.json.erb. Vượt qua :format => 'html'không giúp ích gì.


Tiêu đề câu hỏi chung chung hơn nhiều so với vấn đề cụ thể của James. Nếu bạn đang tìm kiếm các giải pháp khác, hãy xem tại đây: stackoverflow.com/questions/7616097/…
miguelsan

Câu trả lời:


100

Bắt đầu với Rails 3.2.3, khi gọi kết xuất: một phần (chỉ hoạt động bên ngoài respond_tokhối).

render formats: [ :html ]

thay vì

render format: 'html'

Tôi đoán có thể có các câu trả lời "hay nhất" khác nhau tùy thuộc vào ngữ cảnh, vì vậy thật khó để tán thành có ý nghĩa cho câu hỏi này, nhưng điều này đáp ứng nhu cầu của tôi là dễ dàng hiển thị một mẫu HTML từ bên trong một RJS cùng tên sau khi hy vọng rằng một :formattùy chọn sẽ công việc. Cảm ơn!
ches

1
Điều này cũng hoạt động cho Rails 5.0.2. Tuy nhiên, lưu ý rằng bạn cũng có thể cần chỉ định :content_typetùy chọn trong một số trường hợp - ví dụ: format.pdfchỉ có thể thực hiện việc hiển thị mẫu HTML từ bên trong một khối render "template", formats: [:html], content_type: "text/html". Tôi cần điều này vì tôi chỉ cho phép tải xuống trực tiếp các mẫu sách của mình cho các thành viên trong danh sách email của tôi - những khách truy cập thông thường sẽ nhận được biểu mẫu đăng ký.
Michael Trojanek

64

Có chuyện gì với

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

? Tôi vừa thử điều này để hiển thị một phần HTML ERB từ bên trong mẫu trình tạo Atom và nó hoạt động tốt. Không cần phải lộn xộn với các biến toàn cục (vâng, tôi biết chúng có "@" ở phía trước, nhưng đó là những gì chúng đang có).

Tuy nhiên, with_format &blockcách tiếp cận của bạn rất thú vị và có ưu điểm là bạn chỉ xác định định dạng, trong khi cách tiếp cận đơn giản cũng chỉ định công cụ mẫu (ERB / ​​builder / etc).


26
Nhược điểm duy nhất của điều này là nếu một phần của bạn hiển thị các phần khác, nó sẽ không thành công trừ khi bạn truy cập và thay đổi tất cả các lệnh gọi từng phần hiển thị của mình để bao gồm ".html.erb" trên tên của chúng.
chrisrbailey 25-07-09

4
bạn không phải chỉ định công cụ tạo khuôn mẫu để điều này hoạt động. (Ít nhất là trên đường ray 3). Những thứ sau hoạt động tốt: render (: part => "baz.html")
Tim Harper

1
Không hoạt động nếu bạn có partials khác nhau cho địa phương khác nhau (ví dụ baz.en.html.erb, baz.fr.html.erb) và bạn muốn render :partials logic cho việc lựa chọn một trong những quyền (với fallbacks, vv).
John

1
Đối với đường ray 3.2.3, tôi thấy cảnh báo sau khi sử dụng giải pháp này: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 Xin chào

3
Một nhược điểm của phương pháp này là bản địa hóa sẽ tìm kiếm foo.baz.html.[your_string]thay vì foo.baz.[your_string]. câu trả lời của zgchurc là một giải pháp tốt hơn.
mbillard

32

Đối với Rails 3, khối with_format hoạt động, nhưng nó hơi khác một chút:

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

Làm việc với đường ray 3.2.0 quá :)
gucki

32

Rails 4 sẽ cho phép bạn chuyển một tham số định dạng. Vì vậy, bạn có thể làm

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

Lưu ý rằng bạn có thể làm điều gì đó tương tự trong Rails 3 nhưng nó sẽ không chuyển định dạng đó cho bất kỳ thành phần phụ nào (nếu biểu mẫu gọi các thành phần khác).

Bạn có thể có khả năng Rails 4 trong Rails 3 bằng cách tạo config / initializers / 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

Xem http://railsguides.net/2012/08/29/rails3-does-not-render-partial-for-specific-format/


kỳ lạ, tôi tự hỏi tại sao nó không hoạt động với tôi trong ứng dụng Rails 3.2.19, tự hỏi điều gì tạo nên sự khác biệt trong ứng dụng của tôi. Không thể kết xuất ActionView: một phần để tôn trọng: format arg, dường như không tạo ra sự khác biệt nào, ngay cả với bản vá này.
jrochkind

29

Dựa trên phản ứng của roninek , tôi đã tìm ra giải pháp tốt nhất là:

trong /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

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

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

Một giải pháp thay thế sẽ là xác định lại renderđể chấp nhận một :formattham số.

Tôi không thể render :filelàm việc với người dân địa phương và nếu không có một số tinh thần nhạy bén.


8
quá tệ đối với thị hiếu của tôi. Tốt hơn là chỉ định toàn bộ phần mở rộng.
Tim Harper

1
Đối với đường ray 3, hãy xem câu trả lời của zgchurch.
lillq

25

Trong Rails 3, Chế độ xem có một mảng định dạng, có nghĩa là bạn có thể đặt nó để tìm kiếm [: mobile,: html]. Cài đặt sẽ mặc định là tìm kiếm: mẫu di động, nhưng quay lại: mẫu html. Các hiệu ứng của việc thiết lập này sẽ phân chia thành các phần bên trong.

Cách tốt nhất, nhưng vẫn còn thiếu sót, mà tôi có thể tìm thấy để thiết lập điều này là đặt dòng này ở đầu mỗi mẫu di động đầy đủ (nhưng không phải phần tử).

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

Lỗ hổng là bạn phải thêm dòng đó vào nhiều mẫu. Nếu ai đó biết cách thiết lập điều này một lần, từ application_controller.rb, tôi rất muốn biết điều đó. Thật không may, việc thêm dòng đó vào bố cục di động của bạn sẽ không hiệu quả vì các mẫu được hiển thị trước bố cục.


Cảm ơn bạn đã giải thích điều này. Tôi đã kết thúc việc sử dụng nó ở nơi khác: stackoverflow.com/questions/47459724/…
Joshua Pinter

16

Chỉ cần giải thích thêm về những gì zgchurch đã viết:

  • tính đến các trường hợp ngoại lệ
  • trả về kết quả của khối được gọi

Nghĩ rằng nó có thể hữu ích.

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

10

Bạn có hai lựa chọn:

1) sử dụng render :file

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

2) thay đổi định dạng mẫu thành html bằng cách đặt biến @template_format

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

1
<% @template_format = "html"%> phù hợp với tôi, vì các phần khác được tải một phần của tôi, tôi không phải cập nhật các phần khác hiển thị trong chuỗi.
pagetribe

5

Tôi có một tệp có tên 'api / item.rabl' và tôi muốn hiển thị nó từ chế độ xem HTML nên tôi phải sử dụng:

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

( filebởi vì tệp không có dấu gạch dưới trong tên formatsvà không phải format(và chuyển và mảng))


2

Có vẻ như việc chuyển một formatstùy chọn sẽ hiển thị đúng trong phiên bản Rails mới hơn, ít nhất là 3.2:

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

1

Tôi gặp chủ đề này khi tôi đang cố gắng kết xuất một phần XML trong một tệp dạng xem xml.builder khác. Sau đây là một cách hay để làm điều đó

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

Và vâng ... Tên tệp đầy đủ cũng hoạt động ở đây ...


Điều này gặp phải cùng một vấn đề bên trong-chia phần mà @chrisrbailey đã đề cập trong một câu trả lời khác: nếu một phần bạn gọi với tên tệp đầy đủ sử dụng các phần tử (mà không chỉ định tên tệp đầy đủ cho mỗi phần), thì nó sẽ không thành công.
James A. Rosen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.