2017-09-05 9 views
1

Rails의 content_tag 도우미를 사용하여 HTML 코드 블록을 작성합니다. 현재 직면 한 문제는 배열의 HTML 문자열에 content_tag에 의해 생성 된 HTML 요소를 결합하는 것입니다.safe_join 및 content_tag 접근 방식으로 html_safe 대체

RuboCop Rails/OutputSafety 참조. 예를 들어

: 나는 다음과 같은 html_safe 접근 방식을 사용하는 경우

options = ["<li>Three</li>", "<li>Four</li>", "<li>Five</li>"] 

# This is code to generate blocks of HTML 
out = [] 
out << content_tag(:ul, 
    content_tag(:li, "One") + 
    content_tag(:li, "Two") + 
    options.join(''), 
:class => ["class_1", "class_2"]) 
safe_join(out) 

# Expect result should be like 
<ul class="class_1 class_2"> 
    <li>One</li> 
    <li>Two</li> 
    <li>Three</li> 
    <li>Four</li> 
    <li>Five</li> 
</ul> 

# Actual result 
<ul class="class_1 class_2"> 
    <li>One</li> 
    <li>Two</li> 
    "<li>Three</li><li>Four</li><li>Five</li>" 
</ul> 

그러나, 그것은 작동합니다.

내가 바꿔야 할 것에 대한 제안 사항이 있으십니까?

# New apporach 
options = ["Three", "Four", "Five"] 
out = [] 
out << content_tag(:ul, 
    content_tag(:li, "One") + 
    content_tag(:li, "Two") + 
    options.collect do |option| 
     content_tag(:li, "#{option[0]}") 
    end.join(""), 
:class => ["class_1", "class_2"]) 
safe_join(out) 

# New approach result 
<ul class="class_1 class_2"> 
    <li>One</li> 
    <li>Two</li> 
    "<li>Three</li><li>Four</li><li>Five</li>" 
</ul> 
+0

합니다. 완전하고 기술적 인 해결책에 대한 답을보십시오. – zihaow

답변

3

출력은 options 배열에서 오는 안전하지 않은 문자열로 연결하는 것이 문제입니다. 이것은 당신이 안전을 위해 전체 출력 html_safe 방법을 사용해야하는 유일한 장소 : html_safe 방법처럼 작동하지 않는 모든 safe_join 방법의

먼저

out << content_tag(:ul, 
    content_tag(:li, "One") + 
    content_tag(:li, "Two") + 
    options.join('').html_safe, 
:class => ["class_1", "class_2"]) 

편집, 그것은뿐만 아니라 않습니다 결합 된 문자열을 html_safe로 만듭니다. 유해한 내용을 피하기 위해 결합 된 문자열이 html_safe가 아닌 경우 html을 이스케이프 처리합니다. 이미 때부터 out 배열의 문자열을 전혀 아무것도하지 않았다 귀하의 경우 safe_join 방법에서

https://apidock.com/rails/ActionView/Helpers/OutputSafetyHelper/safe_join

는 html_safe. 그것이 안전하지 이후 HTML을 탈출했다 그 순간 options.join('')에서

content_tag(:li, "Two") + options.join('') 

content_tag(:li, "Two").html_safe? # => true 
options.join('').html_safe?  # => false 

:

result = content_tag(:ul, 
      content_tag(:li, "One") + 
      content_tag(:li, "Two") + 
      options.join(''), 
      :class => ["class_1", "class_2"]) 

result.html_safe? # => true 

문제의 원인은 안전 하나 안전한 문자열을 연결된 것입니다. 예를 참조하십시오 :

# html tags in the second string are escaped, since it is not safe 
"<li>One</li>".html_safe + "<li>Two</li>" # => "<li>One</li>&lt;li&gt;Two&lt;/li&gt;" 

# nothing has been escaped, since everything is safe 
"<li>One</li>".html_safe + "<li>Two</li>".html_safe # => "<li>One</li><li>Two</li>" 

그래서, 위해 예상하려면 결과 두 조건이 충족되어야합니다 :

  1. safe_join 방법은 html_safe 문자열의 배열을해야합니다. html_safe가 아닌 경우 모든 html 태그가 이스케이프됩니다.
  2. 안전하지 않은 문자열을 안전한 문자열로 연결하지 마십시오. 그렇지 않으면 첫 번째 문자열을 이스케이프 처리합니다.

두 번째 조건을 충족하지 못했습니다. 새로운 접근 방식

.join("") 방법에 대한

제안 배열 안전 문자열이 포함 된 경우에도 결과 문자열이 안전합니다.safe_join 사용 safe_join 및 content_tag 헬퍼와 html_safe을 대체 할 대안 안전한 방법을 찾고 있습니다 분들을 위해

content_tag(:li, "One") + 
    content_tag(:li, "Two") + 
    safe_join(
    options.collect do |option| 
     content_tag(:li, option) 
    end 
    ) 
+0

예, html_safe 접근 방식을 사용했는데 정상적으로 작동했습니다. html_safe를 사용하지 않고도 달성 할 수있는 대안을 찾으려고 노력 중입니다. 그래서 내가 safe_join 방식을 사용했습니다. (참조 : http://rubocop.readthedocs.io/en/latest/cops_rails/#railsoutputsafety) – zihaow

+0

더 추가했습니다. 설명 – chumakoff

+0

당신이 설명했던 것이 정말 도움이됩니다. content_tag는 항상 HTML 안전 문자열을 생성하는지 궁금합니다. 그러나, [collect .. end] 범위 내에 content_tag를 래핑하면됩니다. HTML 안전 문자열을 생성하지 않습니다. 어떤 아이디어? 내 새로운 접근 방식을 참조하십시오. @chumakoff – zihaow