Ruby on Rails: jak wyrenderować string jako HTML?

154

mam

@str = "<b>Hi</b>"

i moim zdaniem:

<%= @str %>

Na stronie zostanie wyświetlone: <b>Hi</b>kiedy naprawdę chcę, to Cześć . W jaki sposób ruby ​​„interpretuje” ciąg znaków jako znaczniki HTML?


Edycja : przypadek, w którym

@str = "<span class=\"classname\">hello</span>"

Jeśli moim zdaniem tak

<%raw @str %>

Kod źródłowy HTML jest <span class=\"classname\">hello</span> tam, gdzie naprawdę chcę <span class="classname">hello</span>(bez ukośników odwrotnych przed podwójnymi cudzysłowami). Jaki jest najlepszy sposób na „odskoczenie” tych podwójnych cudzysłowów?

Tim
źródło
Możesz również rozważyć użycie składni% Q [] dla znaków ucieczki. np. %Q["quotation marks"] => "\"quotation marks\"" Źródło: en.wikibooks.org/wiki/Ruby_Programming/Syntax/… Nie wiem, czy to pomaga.
0112

Odpowiedzi:

328

AKTUALIZACJA

Ze względów bezpieczeństwa zaleca się używanie sanitizezamiast html_safe. Połączyć


Dzieje się tak, że ze względów bezpieczeństwa Railsy uciekają przed twoim ciągiem znaków, ponieważ może on zawierać osadzony w nim złośliwy kod. Ale jeśli powiesz Railsom, że twój łańcuch jest html_safe, to przepuści go od razu.

@str = "<b>Hi</b>".html_safe
<%= @str %>

LUB

@str = "<b>Hi</b>"
<%= @str.html_safe %>

Używanie rawdziała dobrze, ale wszystko, co robi, to konwertowanie ciągu na ciąg, a następnie wywołanie html_safe. Kiedy wiem, że mam ciąg, wolę wywoływać bezpośrednio html_safe, ponieważ pomija niepotrzebny krok i wyjaśnia, co się dzieje. Szczegóły dotyczące ucieczki ciągów i ochrony XSS znajdują się w tym Asciicast .

Jakub
źródło
Fantastyczny. Nie mogłem znaleźć, jak to zrobić, nawet po godzinnych poszukiwaniach. Dziękuję za odpowiedź.
Salil
1
Zawsze używałem raw. Bardzo się cieszę, że o tym wiem!
jmcharnes
Dając hanks z przyszłości =)
Carlos Morales
1
dezynfekcja została usunięta zgodnie ze stackoverflow.com/questions/44575106/…
Youness
16

Użyj surowego :

<%=raw @str >

Ale jak słusznie mówi @ jmort253, zastanów się, gdzie naprawdę należy HTML.

Michael Stum
źródło
Cześć, to rozwiązanie działa, z jednym zastrzeżeniem: zobacz edytowane pytanie
Tim
14

Jeśli railskorzystasz z Erubisa - najfajniejszy sposób to zrobić

<%== @str >

Zwróć uwagę na podwójny znak równości. Aby uzyskać więcej informacji, zobacz powiązane pytanie na SO.

jibiel
źródło
7

Mieszasz logikę biznesową z zawartością. Zamiast tego zalecałbym wysłanie danych na twoją stronę, a następnie użycie czegoś takiego jak JQuery, aby umieścić dane tam, gdzie są potrzebne.

Ma to tę zaletę, że cały kod HTML pozostaje na stronach HTML, do których należy, dzięki czemu projektanci stron internetowych mogą później modyfikować kod HTML bez konieczności przepuszczania kodu po stronie serwera.

A jeśli nie chcesz używać JavaScript, możesz spróbować tego:

@str = "Hi"

<b><%= @str ></b>

Przynajmniej w ten sposób twój HTML będzie na stronie HTML, do której należy.

jmort253
źródło
Problem polega na tym, że moja aplikacja pobiera słabo oznaczony plik i „tłumaczy” go za pomocą wyrażeń regularnych na dobry kod HTML, aby wysłać go do widoku. Dlatego generowany kod HTML jest dynamiczny, więc nie mogę z góry określić, które tagi mają otaczać @str. Gdzie bym wykonywał tę pracę „tłumaczeniową”, jeśli nie w modelach? Myślałem, że nie powinniśmy mieć w widokach obszernego kodu logicznego.
Tim
1
To naprawdę kwestia opinii. Podczas tworzenia nowej aplikacji wolę, aby wszystko było tak czyste, jak to tylko możliwe. Ale często musimy pracować w ramach ograniczeń tego, co zostawili nam inni. Jeśli twoje źródło danych zwraca znaczniki HTML, może przyjrzyj się używaniu „surowego”, jak opisano w rozwiązaniu Michaela Stuma.
jmort253
1
Jeśli odziedziczyłeś obsługę jakiegoś kodu, a kod zawiera obszary, które wykazują słabe myślenie lub projekt, to naprawdę częścią twojej odpowiedzialności jest wyczyszczenie go, aby był łatwiejszy w utrzymaniu. Pozostawienie go tak, jak znalazłeś, jest w porządku, gdy jest to świetny kod na początek, ale pozostawienie go lepszym niż uważasz, że jest dobry, gdy wymagał pracy. Część mojej pracy polega na zarządzaniu starszymi aplikacjami; Jestem fanem nie naprawiania rzeczy, które nie są zepsute, ale nie można ich łatwo ulepszyć ze względu na sposób ich napisania. Musiałem przepisać większość wywołań funkcji, ale teraz jest to o wiele łatwiejsze.
Tin Man
Nie powinieneś używać JavaScript do interpolacji HTML, jeśli nie ma innego powodu, aby używać JS. Spowoduje to uszkodzenie witryny pod kątem przeglądarek innych niż JS (tak, jest kilka).
Marnen Laibow-Koser
1
Oczywiście, jeśli zezwolisz na treści, które nie uciekły, odpowiadanie za upewnienie się, że znaczniki nie są złe, zależy od ciebie.
Macario
6

Lub możesz wypróbować metodę CGI.unescapeHTML .

CGI.unescapeHTML "&lt;p&gt;This is a Paragraph.&lt;/p&gt;"
=> "<p>This is a Paragraph.</p>"
Arman Ortega
źródło
0

ponieważ tłumaczysz i wybierasz pożądany kod z kiepskiego zakodowanego pliku danej osoby, czy mógłbyś użyć content_tag w połączeniu ze swoim wyrażeniem regularnym.

Kradnąc z dokumentów API, można interpolować ten przetłumaczony kod na content_tagpodobny do:

<%= content_tag translated_tag_type.to_sym, :class => "#{translated_class}" do -%>
<%= translated_text %>
<% end -%>
# => <div class="strong">Hello world!</div>

Nie znając swojego kodu, tego rodzaju myślenie sprawi, że przetłumaczony kod będzie zbyt zgodny.

pjammer
źródło
Zakładam, że przetłumaczony_tekst to rzeczywista zawartość elementu div, prawda? tj. w tym przykładzie byłoby to „Hello world!”? Co się stanie, jeśli przetłumaczony_tekst zawiera więcej HTML, tj. Zagnieżdżone elementy div lub span? Czy musiałbym wtedy wielokrotnie dzwonić do content_tag?
Tim
i ... przepraszam, wciśnij Enter wcześnie ... każdy zagnieżdżony element div / span jest nadal content_tag i nadal musisz go zweryfikować, prawda? Ponieważ nie możemy zobaczyć, co robisz ze swoim wymyślnym tłumaczeniem ;-), zakładam, że szukasz WSZYSTKICH tagów, niezależnie od tego, czy wyrażenie regularne znajduje się w „nadrzędnym” html ... na przykład <ul>. nie umieściłbyś do wydrukowania wszystkich li jako dużego łańcucha, prawda? każdy byłby własnym content_tag: li, tekst poprawny?
pjammer
0

@str = "<span class=\"classname\">hello</span>" Jeśli moim zdaniem tak

<%raw @str %> Kod źródłowy HTML jest <span class=\"classname\">hello</span>tym, czego naprawdę chcę <span class="classname">hello</span>(bez ukośników odwrotnych, które były przed podwójnymi cudzysłowami>). Jaki jest najlepszy sposób na „odskoczenie” tych podwójnych cudzysłowów?

Rozwiązanie: użyj podwójnych cudzysłowów wewnątrz pojedynczych cudzysłowów (lub pojedynczego wewnątrz podwójnego cudzysłowu), aby uniknąć znaków ucieczki z ukośnikiem odwrotnym.

@str = '<span class="classname">hello</span>'
<%raw @str %>
Wypadek
źródło
0

Wersja html_safe działa dobrze w Railsach 4 ...

<%= "<center style=\"color: green; font-size: 1.1em\" > Administrators only </center>".html_safe if current_user.admin? %
>
GA
źródło