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.