부분이 존재하는지 확인하는 Rails 함수가 있습니까?


98

존재하지 않는 부분을 렌더링하면 예외가 발생합니다. 렌더링하기 전에 부분이 존재하는지 확인하고, 존재하지 않는 경우 다른 것을 렌더링하겠습니다. .erb 파일에서 다음 코드를 수행했지만이 작업을 수행하는 더 좋은 방법이 있어야한다고 생각합니다.

    <% begin %>
      <%= render :partial => "#{dynamic_partial}" %>
    <% rescue ActionView::MissingTemplate %>
      Can't show this data!
    <% end %>

1
사용하는 대답 rescue은 위험합니다. 사용하기 전에 다른 솔루션을 살펴 보겠습니다.
Grant Hutchins 2012 년

답변:


98

현재 저는 Rails 3 / 3.1 프로젝트에서 다음을 사용하고 있습니다.

lookup_context.find_all('posts/_form').any?

내가 본 다른 솔루션에 비해 장점은 레일 루트가 아닌 모든 뷰 경로에서 볼 수 있다는 것입니다. 레일 엔진이 많기 때문에 이것은 나에게 중요합니다.

이것은 Rails 4에서도 작동합니다.


9
lookup_context.exists? ( 'posts / find')가 작동하지 않았습니다. 대신이 예제에서는 lookup_context.exists? (name, prefix, partial) 또는 lookup_content.exists? ( 'find', 'posts', true)를 사용했습니다.
Jenn

2
이 템플릿 (소스를 확인하는 방법은 현재 (> = 3.2 레일)이다 apidock )
maček

1
부분이 현재 뷰 템플릿과 동일한 폴더에있는 경우 lookup_context.exists?("find", lookup_context.prefixes, true). 이렇게하면 뷰 디렉터리를 호출에 하드 코딩 할 필요가 없습니다. 이것은 부분에 대한 것입니다. 부분이 아닌 경우 마지막 인수를 생략 (또는 true 대신 false 사용)
나단 월러스

71

나도 이것으로 고군분투하고 있었다. 이것은 내가 사용한 방법입니다.

<%= render :partial => "#{dynamic_partial}" rescue nil %>

기본적으로 부분이 존재하지 않으면 아무것도하지 않습니다. 그래도 부분이 누락 된 경우 무언가를 인쇄하고 싶습니까?

편집 1 : 오, 나는 독해에 실패했습니다. 다른 것을 렌더링하고 싶다고 말씀하셨습니다. 그렇다면 이건 어때?

<%= render :partial => "#{dynamic_partial}" rescue render :partial => 'partial_that_actually_exists' %>

또는

<%= render :partial => "#{dynamic_partial}" rescue "Can't show this data!" %>

편집 2 :

대안 : 부분 파일의 존재 확인 :

<%= render :partial => "#{dynamic_partial}" if File.exists?(Rails.root.join("app", "views", params[:controller], "_#{dynamic_partial}.html.erb")) %>

6
: 내 질문은 내가 안티 패턴 흐름 제어, 할 예외를 사용하지 않는다는 것입니다 stackoverflow.com/questions/1546514/...
다니엘 Cukier

6
예외는 프로그램의 정상적인 작동을 넘어서 발생하는 일을 처리하는 데 사용되는 흐름 제어 유형입니다. 동적 부분이 있어야하는데 뭔가 잘못되어 결국 거기에 있지 않은 경우 예외에 대한 합리적인 사용입니다 (물론 IMO-예외의 적절한 사용은 거룩한 전쟁 그 자체입니다). 대안은 실제 파일이 있는지 여부를 파일 시스템에서 확인하는 것입니다. 그 코드로 내 대답을 업데이트하겠습니다.
Jeff

3
나는 해결책을 좋아하지만 그럼에도 불구하고 부분에 던져진 모든 종류의 예외를 삼킨다. IMHO 이것은 오류를 추적하기 어렵게 만듭니다.
Matt

5
다른 유형의 예외가있는 경우 rescue nil... rescue ...메서드는이를 숨 깁니다. 이는 디버그하기 어려운 버그로 이어집니다.
nicholaides 2011

8
이 솔루션이 정말 마음에 들지 않습니다. 구출은 비용이 많이 들고 File.exist? 부분이 한 위치에만있을 수 있다고 가정합니다. lookup_context를 사용하는 @Rein의 솔루션은 내가 믿는 방법입니다.
Bert Goethals

52

뷰 내부에서 template_exists? 작동하지만 호출 규칙은 단일 부분 이름 문자열로 작동하지 않고 대신 template_exists? (이름, 접두사, 부분)를 사용합니다.

경로에서 부분을 확인하려면 : app / views / posts / _form.html.slim

사용하다:

lookup_context.template_exists?("form", "posts", true)

Rails 3.0.10에서 app / views / posts / _foo.txt.erb와 같은 대체 확장자가있는 경우이를 인수에 다음과 같이 추가해야합니다. template_exists? ( "foo.txt", "posts" , true)
Gabe Martin-Dempesy

이것은 레일에서 3.2되지 않습니다
maček

Rails 3.2.x에서는 위임 된 것처럼 보이지 않지만 두 번째 인수는 접두사 배열입니다. 또한 현재 컨트롤러에 존재합니다.
Brendan

2
당신은 두 번째 인수로 lookup_context.prefixes를 사용할 수 있습니다 lookup_context.template_exists를 ( "양식", lookup_context.prefixes 사실)?
lion.vollnhals

뷰 레이어에서이 정보에 액세스하는 측면에서 더 나은 답변입니다.
Brendon Muir

30

Rails 3.2.13에서 컨트롤러에 있다면 다음을 사용할 수 있습니다.

template_exists?("#{dynamic_partial}", _prefixes, true)

template_exists?에 위임 lookupcontext당신이 볼 수 있듯이,AbstractController::ViewPaths

_prefixes 컨트롤러의 상속 체인의 컨텍스트를 제공합니다.

true 부분을 ​​찾고 있기 때문입니다 (일반 템플릿을 원한다면이 인수를 생략 할 수 있습니다).

http://api.rubyonrails.org/classes/ActionView/LookupContext/ViewPaths.html#method-i-template_exists-3F


찬성. 매개 변수에 대한 더 최신 및 더 나은 설명.
jacobsimeon

4
보기 (예 : 레이아웃)에서 다음과 같이 작동합니다 lookup_context.template_exists?("navbar", controller._prefixes, :partial).. 이것은이 레이아웃을 렌더링하는 현재 템플릿에 명시된 "navbar"부분이 있는지 여부와 렌더링 할 수 있는지 여부를 알려줍니다. 나는 :partial그 부울이 무엇인지 명시하기 위해 통과 :partial합니다. _prefixes비트 감사합니다 , @Flackou!
pdobb

교체 _prefixesnil다른 상위 디렉토리에 그의 일부를 호출하는 경우.
ben

8

나는 이것이 답을 얻었고 백만 년이라는 것을 알고 있지만, 여기에 내가 이것을 어떻게 고쳤는지가 있습니다 ...

레일즈 4.2

먼저 이것을 application_helper.rb에 넣습니다.

  def render_if_exists(path_to_partial)
    render path_to_partial if lookup_context.find_all(path_to_partial,[],true).any?
  end

그리고 지금 전화하는 대신

<%= render "#{dynamic_path}" if lookup_context.find_all("#{dynamic_path}",[],true).any? %>

난 그냥 전화 해 <%= render_if_exists "#{dynamic_path}" %>

도움이 되길 바랍니다. (rails3에서 시도하지 않았습니다)


1
대체를 제공하려는 경우에는 작동하지 않습니다. 또한 지역 변수를 고려하지 않습니다.
phillyslick

이것이 바로 제가 찾던 것입니다. 아주 깨끗한 대답.
Sunny

1
@BenPolinsky 나는 당신이 그것을 def render_if_exists(*args); render(*args) if ...위해 사용할 수 있다고 가정합니다
사이트

6

저는이 패러다임을 여러 번 사용하여 큰 성공을 거두었습니다.

<%=
  begin
    render partial: "#{dynamic_partial}"
  rescue ActionView::MissingTemplate
    # handle the specific case of the partial being missing
  rescue
    # handle any other exception raised while rendering the partial
  end
%>

위 코드의 이점은 특정 경우를 견인 할 수 있다는 것입니다.

  • 부분이 실제로 누락되었습니다.
  • 부분이 존재하지만 어떤 이유로 오류가 발생했습니다.

코드 <%= render :partial => "#{dynamic_partial}" rescue nil %>나 일부 파생물 만 사용하면 부분이 존재할 수 있지만 예외가 발생하여 조용히 먹히고 디버깅을위한 고통의 원인이됩니다.


4

자신의 도우미는 어떻습니까?

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.