Rails에서 다른 형식의 일부를 어떻게 렌더링합니까?


114

일부 HTML을 포함하는 JSON 응답을 생성하려고합니다. 따라서 나는 /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'은 도움이되지 않습니다.


질문 제목은 James의 특정 문제보다 훨씬 일반적입니다. 다른 솔루션을 찾고 있다면 여기를보십시오 : stackoverflow.com/questions/7616097/…
miguelsan 2013-08-08

답변:


100

Rails 3.2.3부터 render : partial을 호출 할 때 ( respond_to블록 외부에서만 작동합니다 ).

render formats: [ :html ]

대신에

render format: 'html'

상황에 따라 다른 "최상의"답변이있을 수 있으므로이 질문에 대해 의미있게 찬성하기는 어렵지만, :format옵션이 있기를 바라면서 동일한 이름의 RJS 내에서 HTML 템플릿을 쉽게 렌더링해야 할 필요성을 채웠습니다. 작업. 감사!
ches

1
이것은 Rails 5.0.2에서도 작동합니다. 그러나 :content_type경우에 따라 옵션 을 지정해야 할 수도 있습니다. 예를 들어 format.pdf블록 내부에서 HTML 템플릿을 렌더링하는 것은으로 만 수행 할 수 있습니다 render "template", formats: [:html], content_type: "text/html". 내 이메일 목록의 회원에게만 내 도서 샘플을 직접 다운로드 할 수 있기 때문에 이것이 필요합니다. 일반 방문자는 대신 가입 양식을받습니다.
Michael Trojanek

64

뭐가 잘못 됐니

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

? Atom 빌더 템플릿 내부에서 HTML ERB 부분을 렌더링하기 위해 이것을 시도했지만 제대로 작동했습니다. 전역 변수가 필요하지 않습니다. (예, 앞에 "@"가 있다는 것을 알고 있지만 그게 바로 그 것입니다).

귀하의 with_format &block접근 방식 은 멋지고 형식 만 지정하는 반면 간단한 접근 방식은 템플릿 엔진 (ERB / ​​builder / etc)도 지정한다는 장점이 있습니다.


26
이것의 유일한 단점은 부분이 다른 부분을 렌더링하는 경우 이름에 ".html.erb"를 포함하도록 모든 렌더링 부분 호출을 변경하지 않으면 실패한다는 것입니다.
chrisrbailey

4
이 작업을 위해 템플릿 엔진을 지정할 필요가 없습니다. (최소한 레일 3부터). 다음은 잘 작동합니다. render (: partial => "baz.html")
Tim Harper

1
당신이 다른 로케일에 대해 서로 다른 부분 지문을 (예를 들어,이 경우 작동하지 않습니다 baz.en.html.erb, baz.fr.html.erb) 원하는 render :partial(폴백 (fallback)로 등)의에게 올바른 선택을위한 논리를.
John

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 Hello

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

Rails 4에서는 형식 매개 변수를 전달할 수 있습니다. 그래서 당신은 할 수 있습니다

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

Rails 3에서 비슷한 작업을 할 수 있지만 해당 형식을 하위 부분에 전달하지 않습니다 (양식이 다른 부분을 호출하는 경우).

config / initializers / renderer.rb를 생성하여 Rails 3에서 Rails 4 기능을 사용할 수 있습니다.

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 render : partial을 얻을 수 없습니다. : formats arg를 존중합니다.이 패치를 사용해도 전혀 차이가없는 것 같습니다.
jrochkind

29

roninek의 응답바탕으로 다음과 같은 최상의 솔루션을 찾았습니다.

/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
내 취향에는 너무 끔찍하다. 전체 확장자를 지정하는 것이 좋습니다.
Tim Harper

1
레일 3의 경우 zgchurch의 답변을 참조하십시오.
lillq

25

Rails 3에서 View에는 형식 배열이 있습니다. 즉, [: mobile, : html]을 찾도록 설정할 수 있습니다. 기본적으로 : mobile 템플릿을 찾도록 설정하지만 : html 템플릿으로 돌아갑니다. 이 설정의 효과는 내부 부분으로 계단식으로 내려갑니다.

이것을 설정하기 위해 찾을 수있는 최선이지만 여전히 결함이있는 방법은이 줄을 각 전체 모바일 템플릿의 상단에 배치하는 것입니다 (부분이 아님).

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

결함은 여러 템플릿에 해당 라인을 추가해야한다는 것입니다. 누군가 application_controller.rb에서 이것을 한 번 설정하는 방법을 알고 있다면 그것을 알고 싶습니다. 안타깝게도 템플릿이 레이아웃보다 먼저 렌더링되기 때문에 모바일 레이아웃에 해당 줄을 추가하는 것은 작동하지 않습니다.


설명 해주셔서 감사합니다. 나는 그것을 다른 곳에서 사용하게되었다 : stackoverflow.com/questions/47459724/…
Joshua Pinter 2017

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) @template_format 변수를 설정하여 템플릿 형식을 html로 변경

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

1
<% @template_format = "html"%> 내 부분이 다른 부분을로드했기 때문에 체인 아래에서 다른 렌더링을 업데이트 할 필요가 없었기 때문에 저에게 효과적이었습니다.
pagetribe 2011 년

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.builder 뷰 파일에서 XML 부분을 렌더링하려고 할 때이 스레드를 발견했습니다. 다음은 그것을하는 좋은 방법입니다

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

그리고 예 ... 전체 파일 이름이 여기에서도 작동합니다 ...


이것은 @chrisrbailey가 다른 답변에서 언급 한 것과 동일한 내부 부분 문제로 어려움을 겪습니다. 전체 파일 이름으로 호출하는 부분이 부분을 사용하면 (각각에 전체 파일 이름을 지정하지 않고) 실패합니다.
James A. Rosen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.