2013-07-10 8 views
10

Ho una lista di valori nelle coppie url/titolo che vorrei visualizzare. (Più specificamente, ogni oggetto ha il proprio elenco di collegamenti, alcuni con 0, alcuni con 1, altri con più.) Vorrei che comparissero in un elenco separato da virgole. Così ho scritto questo nel mio file .erb:Posso creare una serie di collegamenti usando link_to in Rails?

<%= links.map{|wl| link_to wl.title, wl.url}.join(', ') %> 

Un po 'con mia grande sorpresa, questa visualizzato un elenco separato da virgole di il codice HTML per i link ho voluto creare; cioè stava prendendo tutte le parentesi angolari e le e commerciali e le codifica. Giusto per assicurarsi che non ci fosse nulla di divertente nelle funzioni di ordine superiore, ho provato una versione più imperativo:

<% a = [] %> 
<% links.each do |wl| %> 
    <% a << link_to(wl.title, wl.url) %> 
<% end %> 
<%= a.join(', ') %> 

con, ovviamente, lo stesso risultato. Ma non credo che sto abusando link_to, perché se io modifico che a

<% links.each do |wl| %> 
    <%= link_to(wl.title, wl.url) %>, 
<% end %> 

allora crea in realtà collegamenti. È quasi esattamente quello che voglio, tranne che c'è una virgola extra dopo l'ultima. C'è qualcosa di magico sotto il cofano con link_to che lo fa agire in modo diverso a seconda di dove si sta dirigendo il suo output? C'è un modo per bypassare quella magia? La semantica join sarebbe esattamente ciò che voglio qui, e posso ovviamente capire come eseguire il rollover (usando each_index, credo) ma sembra una soluzione terribilmente pesante e non-Ruby a quello che deve essere un problema comune.

+1

<% = links.map {| wl | link_to wl.title, wl.url} .join (',') .html_safe%>? – oldergod

risposta

4

Mentre i suggerimenti per utilizzare html_safe otterranno il risultato desiderato, suggerisco di non inserire loop come quello nella visualizzazione. C'è un modo perfetto di rotaie per fare quello che stai cercando:

Nel file vista principale in cui attualmente si dispone il ciclo cambiamento a questo:

<%= render partial: 'links/link', collection: links, spacer_template: 'shared/comma' %> 

quindi creare un parziale links/_link.html.erb

<%= link_to link.title, link.url %> 

Quindi creare un parziale shared/_comma.html.erb

, 

La cosa bella di questo approccio è che non devi preoccuparti se il contenuto del link è effettivamente sicuro e se scegli di elencarlo o modificarlo in un altro modo è semplice come cambiare uno o entrambi i modelli. Ad esempio se invece di virgole decidi di volerlo in verticale e usa <br> invece di , nel tuo modello di spaziatore.

+0

Aha grazie! Avevo il sospetto che ci sarebbe stato qualcosa come 'html_safe', ma * questo * è quello che stavo davvero cercando --- sapevo che doveva esserci un idioma per questo. Nota per i futuri lettori di questa domanda: ho dovuto forzare no-EOL-at-EOF per il file che contiene il link partial per evitare spazi bianchi tra il link e la virgola, ma una volta fatto ciò ha funzionato perfettamente. – blahedo

+0

Questo ha un sacco di riferimenti indiretti. Non sembra il miglior design. –

+0

L'indirizzamento è generalmente negativo per la leggibilità e la manutenibilità. Forse, se spieghi perché attaccare i loop nella vista è male, capirò di più il tuo ragionamento. –

0

Rails convertirà le stringhe in html per impostazione predefinita. La tua chiamata di join trasforma l'output dei link in una stringa, motivo per cui il testo viene quindi sottoposto a escape. Prova ad aggiungere .html_safe dopo la chiamata di join, che indicherà ai binari che il testo che stai fornendo è html sicuro e quindi non ha bisogno di essere scappato. C'è di più su come funziona in: http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/

+0

Questo ha lo stesso problema con cui la risposta di Jim Lim mette il tuo codice a rischio di una vulnerabilità facilmente sfruttata. Usa 'safe_join'. –

11

Prova

<%= links.map{|wl| link_to wl.title, wl.url}.join(', ').html_safe %> 

Ciò indica Rails di non sfuggire al testo.

+0

Mi piace questa risposta perché riduce l'indirezione. L'indirizzamento è generalmente negativo per la leggibilità e la manutenibilità. –

+4

sii molto attento se lo fai. Quando wl.title proviene da una fonte esterna, si tratta di una vulnerabilità sfruttabile. Usa 'h (wl.title)' o, meglio, usa 'safe_join' – levinalex

1

prova a mettere questo nel tuo ApplicationHelper

def sep(separator) 
    ->(a, b){ a << separator.html_safe << b } 
    end 

Poi fare questo nel modello

links.map{|wl| link_to wl.title, wl.url}.reduce(&sep(", ")) 

È possibile utilizzare qualsiasi separatore ti piace in questo modo. Inoltre, non è necessario chiamare lo html_safe sull'intera cosa. Solo il separatore. Quindi questo metodo è più sicuro.

12

Utilizzare safe_join combinato con html_safe sulla stringa di separazione.

Esempio:

<%= safe_join(links.map { |l| link_to(l.title, l.url) }, ", ".html_safe) %> 
+0

Sei il re! – fatfrog

Problemi correlati