레일 부분 템플릿의 선택적 로컬 변수 : (정의 된 foo) 혼란에서 어떻게 벗어날 수 있습니까?


225

나는 나쁜 아이였으며 부분 템플릿을 렌더링 할 때 : locals 해시에 값이 명시 적으로 정의되지 않은 경우 부분 템플릿에서 다음 구문을 사용하여 로컬 변수의 기본값을 설정했습니다.

<% foo = default_value unless (defined? foo) %>

이것은 통과되지 않은 변수가 정의되지 않은 것이 아닌 nil로 정의 된 것처럼 행동하기 시작한 이유가 무엇인지 알 수없는 최근까지도 잘 작동하는 것처럼 보였습니다.

SO에서 다양한 도움을받은 사람들이 지적했듯이 http://api.rubyonrails.org/classes/ActionView/Base.html 은 사용 하지 말라고 합니다.

defined? foo

대신에

local_assigns.has_key? :foo

내 방식을 수정하려고하지만 많은 템플릿을 변경하는 것을 의미합니다.

미리 청구하고 모든 템플릿에서이 변경을 수행 할 수 있습니까? 주의해야 할 까다로운 점이 있습니까? 각 테스트를 얼마나 부지런히해야합니까?

답변:


324

나는 이것을한다:

<% some_local = default_value if local_assigns[:some_local].nil? %>

1
나는 hgimenez의 제안에 대한 간단한 구문을 정말로 좋아하지만 (위의)이 접근법은 매우 분명한 장점이 있습니다. (여전히 로컬 값으로 nil을 전달하지 못하게하는 단점이 있습니다)
brahn

1
nil을 통과하려는 사용 사례는 무엇입니까?
jonnii

아, 나는 특별한 경우를 염두에 두지 않는다. 전체 의미를 이해하려고합니다. 이것은 나에게이 대답을 받아들이도록 상기시켰다 :-)
brahn

4
무의미한 문제를 극복하기 위해 OP의 링크 ( api.rubyonrails.org/classes/ActionView/Base.html ) <% if local_assigns.has_key 에서 코드를 복사하고 있습니까? : headline %> 헤드 라인 : <% = headline %> <% end %>-has_key는 nil / false 상황을 피하고 아마도 대답과 같이 한 줄로 단축 될 수 있습니다
Phil

5
Pablo의 답변을 확인하십시오 : local_assigns.fetch0이 아닌 짝수 키를 완벽하게 처리합니다. 키가 전혀 설정 되지 않은 경우에만 기본값을 반환 합니다.
quetzalcoatl

158

local_assigns해시 이므로 fetch 를 optional과 함께 사용할 수도 있습니다 default_value.

local_assigns.fetch :foo, default_value

설정되지 않은 default_value경우 반환 됩니다 foo.

경고:

어쨌든 결과를에 전달하기 위해 호출되므로 local_assigns.fetch :foo, default_valuewhen default_value가 메소드 인 경우 주의하십시오 fetch.

당신이 경우 default_value방법은, 당신은 블록을 포장 할 수 있습니다 local_assigns.fetch(:foo) { default_value }필요하지 않을 때의 호출을 방지하기 위해.


1
명시 적으로 말하면 nil가치가 있습니다. 여기서 값은 보존됩니다. 해시가 포함되어있는 경우 :foo에 매핑 nil, 다음 fetch이 반환됩니다 nil. 그것은 적어도 내 v1.9.3에 있습니다. 나는 1.8이 어떻게 행동했는지 기억하지 못한다.
quetzalcoatl

맞습니다. local_assigns[:foo] || default_valuefoo가 잘못된 값을 반환하면 default_value대신에 대한 문제가 기억 됩니다. @some_value ||= expensive_method메서드가 잘못된 값을 반환하면 항상 실행되는 것이 일반적으로 메모 화의 문제입니다 .
Pablo Cantero

1
왜 이것이 최선의 대답인지 이해하지 못하는 사람은 루비를 오랫동안 사용하지 않았습니다. 브라보 파블로!
mastaBlasta

2
최적화는 다음과 같으므로 변수를 사용할 때마다 'fetch guard'를 사용하는 대신 템플릿 상단에서 한 번만 호출하면됩니다. foo ||= local_assigns[:foo] = local_assigns.fetch(:foo, default_value)
sethcall

나는 왜 그것이 작동하지 않는지 궁금해했다. 나는 그것이 또한 변수를 만들었다 고 가정했지만, 우리는 여전히 반환 된 값을 사용해야한다 :foo = local_assigns.fetch :foo, true
Vadorequest

84

어때요?

<% foo ||= default_value %>

" foo아니오가 아니면 참이면 사용합니다. 그렇지 않으면 default_valuefoo에 할당 합니다 "라고 말합니다 .


2
로컬 해시를 통해 전달되지 않으면 foo가 정의되지 않았으므로 이것이 작동하는지 확실하지 않습니다.
jonnii

1
이것은 작동하지만 이와 같은 기본값이있는 경우 도우미를 사용해야한다는 신호 일 수 있습니다.
psyho

2
여기 마법이 없습니다. 주제에 대한 추가 자료 : groups.google.com/group/comp.lang.ruby/browse_thread/thread/…
hgmnz

37
구문이 너무 작아서이 버전이 정말 마음에 듭니다. 큰 단점은 기본 값으로 덮어 쓰므로 로컬 값으로 nil 또는 false를 전달할 수 없다는 것을 의미한다고 생각합니다.
brahn

16
@brahn, 그게 좋은 지적이야. 실제로 foo부울 인 경우이를 피해야합니다 . 의 값을 정당하게 가질 수 false있으며 default_value실수 로 재정의 될 수 있습니다 .
hgmnz

10

나는 이것이 http://api.rubyonrails.org/classes/ActionView/Base.html 에서 반복되어야한다고 생각한다 .

특정 로컬 변수에 특정 렌더 호출에서 값이 할당되었는지 확인해야하는 경우 다음 패턴을 사용해야합니다.

<% if local_assigns.has_key? :headline %>
  Headline: <%= headline %>
<% end %>

정의를 사용한 테스트? 헤드 라인이 작동하지 않습니다. 이것은 구현 제한 사항입니다.


6

내 경우에는 다음을 사용합니다.

<% variable ||= "" %>

내 부분에.
그게 좋은지 모르겠지만 내 생각은 괜찮습니다.


이것은 실제로 꽤 잘 작동합니다. 정의되지 nil않고 부분 호출에서 로컬로 전달할 때도 작동합니다 .
Joshua Pinter

3
아, 아래를 읽으면 variable부울 인 경우 실패 하고로 설정해야합니다 false. 값을 사용하는 대신 기본값을 사용합니다 false. 자신의 책임하에 사용하십시오.
Joshua Pinter

5

나는 오래된 스레드하지만 여기 내 기부 알고 : 내가 사용하는 것이 local_assigns[:foo].presenceA의 조건 부분의 내부. 그런 다음 foo렌더 호출에 필요할 때만 설정했습니다 .

<%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>

테에서 보라 공식 레일 여기 안내 . RoR 3.1.0에서 유효합니다.


나는 사이의 진정한 차이 볼 수 없습니다 local_assigns[:foo]local_assigns[:foo].presence. 어느 하나를 반환 nil키가 해시와 존재를 않는 경우 값에 존재하지 않는 경우.
jamesmarkcook

1

여러 기본 변수를 허용하는 더 나은 옵션이라고 생각합니다.

<% options = local_assigns.reverse_merge(:include_css => true, :include_js => true) %>
<%= include_stylesheets :national_header_css if options[:include_css] %>
<%= include_javascripts :national_header_js if options[:include_js] %>

1

이것은 파블로의 대답에서 파생 된 것입니다. 이를 통해 기본값 ( 'full')을 설정할 수 있으며 결국 'mode'는 local_assigns 및 실제 로컬 변수에 설정됩니다.

haml / slim :

- mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full')

erb :

<% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %>

0

보다 직관적이고 컴팩트 한

<% some_local = default_value unless local_assigns[:some_local] %>


3
다음과 같이 부분을 호출하면 이것이 실패 할 것이라고 생각합니다.:locals => {:some_local => false}
brahn

0

호출 할 때마다 로컬 변수를 부분적으로 전달하지 않으려면 다음을 수행하십시오.

<% local_param = defined?(local_param) ? local_param : nil %>

이렇게하면 undefined variable오류 를 피할 수 있습니다 . 이를 통해 지역 변수가 있거나없는 부분을 호출 할 수 있습니다.


또는 local_param = 정의 된 경우 local_param? (local_param)
Kinaan Khan Sherwani

0

루비 2.5

어브

가능하지만 범위에서 기본값을 선언해야합니다.

VARIABLE 교체 단어.

# index.html.erb
...
<%= render 'some_content', VARIABLE: false %>
...

# _some_content.html.erb
...
<% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
<% if VARIABLE %>
    <h1>Do you see me?</h1>
<% end %>
...

-6

다음과 같이 도우미를 만들 수 있습니다.

somearg = opt(:somearg) { :defaultvalue }

다음과 같이 구현되었습니다.

module OptHelper
  def opt(name, &block)
    was_assigned, value = eval(
      "[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]", 
      block.binding)
    if was_assigned
      value
    else
      yield
    end
  end
end

방법과 이유에 대한 자세한 내용 은 내 블로그 를 참조하십시오 .

이 솔루션을 사용하면 값을 무시하지 않고 nil 또는 false를 값으로 전달할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.