2015-06-28 9 views
5

ho un aiutante che assomiglia a questo:Render uscita di molteplici espressioni in un'ERB bloccare

if current_user.find_voted_items(vote_scope: :inspired).include?(post) 
    link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do 
    "<i class='fa fa-lightbulb-o'></i> <br />Inspired".html_safe 
    end 
    link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do 
    "<i class='fa fa-smile-o'></i> <br />Happy".html_safe 
    end 
    link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do 
    "<i class='fa fa-meh-o'></i> <br />Disappointed".html_safe 
    end 
    link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do 
    "<i class='fa fa-frown-o'></i> <br />Upset".html_safe 
    end 
end 

ho bisogno di tutti i link e le loro nidificati <i> tag da rendere - ma per qualche ragione, questa versione è solo rendendo l'ultima riga.

Tutto ciò è all'interno di un metodo chiamato show_vote_buttons(post), che viene chiamato in questo modo nella vista: <%= show_vote_buttons(@post) %>

Qual è il modo migliore per affrontare questo?

risposta

4

Fondamentalmente, la ragione di ciò è che <%= %> restituisce l'output del metodo show_vote_buttons. Questo metodo non restituisce esplicitamente nulla, quindi viene restituita l'ultima espressione valutata, nel tuo caso l'ultimo output link_to.

In un caso generale, se non si è utilizzato un metodo di supporto e si è appena incollato il corpo con più chiamate link_to, si otterrebbe lo stesso comportamento. Il motivo è simile: <%= %> non esegue il rendering ogni link_to, esegue il codice all'interno di <%= %> e quindi restituisce il risultato dell'ultima espressione valutata.

vedo due diversi approcci per cambiare l'output:

  1. metodo di supporto: concatenare l'uscita di tutte le espressioni valutate e stampare come una stringa:
    1.1 utilizzando << e parentesi () intorno a ogni link_to;
    1.2 creazione di una stringa con virgolette " e interpolazione di ciascuna uscita link_to con #{};
    1.3 utilizzando concat;
  2. Viste parziali: creare una vista separata dal metodo di supporto esistente e utilizzare <%= %> per stampare ogni link_to.

P.S. Dopo aver provato tutti e quattro i metodi, sono giunto a una conclusione (qui viene un parere personale) che il secondo metodo è più preferibile, almeno perché mantiene il rendering nelle viste ed evita la concatenazione che può apparire disordinata. Un approccio simile viene utilizzato, ad esempio, nella gemma Devise, in cui tutti i collegamenti condivisi si trovano nel parziale app/views/devise/shared/_links.html.erb.

+0

Mi piacerebbe molto vedere la rappresentazione. Prendo un po 'quello che stai dicendo, sembra comunque un po' confuso. C'è un modo migliore per fare ciò che sto cercando di fare, oltre che in un aiuto? Sto cercando di non confondere le mie opinioni. – marcamillion

+0

Interessante, quindi avrei un partial per ogni stato - cioè un partial per 'inspired',' happy', 'disappointed',' upset', ecc.? – marcamillion

0

Il motivo è perfettamente spiegato da @suslov attorno a questa risposta. Metaprogrammazione potrebbe mantenere il codice SECCO:

DATA = { 
    inspired: { ico: 'fa-lightbulb-o', 
       msg: 'Are you sure this post Inspires you?', 
       btn: 'btn-default' }, 
    happy: { ico: 'fa-smile-o', 
       msg: 'Are you sure this post makes you happy?', 
       btn: 'btn-success' }, 
    ... } 

if current_user.find_voted_items(vote_scope: :inspired).include?(post) 
    DATA.map do |k, v| 
    instance_eval %Q{ 
    link_to vote_#{k}_post_path(post, vote_scope: :#{k}), 
       method: :post, 
       data: { confirm: #{v[:msg]} }, 
       class: "btn #{v[:btn]}" do 
     "<i class='fa #{v[:ico]'></i> <br />#{k.capitalize}".html_safe 
    end 
    }.join($/) # return them all, concatenated with separator 
    end 
end 
+0

Sono d'accordo sul fatto che il codice sia molto più ASCIUTTO, ma prima devo farlo funzionare. Detto questo, questa soluzione sembra troppo complessa e confusa. Apprezzo lo sforzo però. – marcamillion

+0

Per me sembra che sia più facile leggere, gestire e supportare, perché tutto è gestito dalla costante statica 'DATA', ma è troppo complicato per te, è una tua scelta. – mudasobwa

1

ma per qualche ragione, questa versione è solo rendendo l'ultima riga.

che la ragione è perché in Ruby, se un metodo non ha un esplicito return, allora il valore restituito di un metodo è il valore dell'ultima riga che ha ottenuto eseguito prima un metodo uscito. Se si desidera restituire più valori da un metodo, utilizzare la parola chiave return e virgola-separare i valori.

#will return an array [1,2,3] 
def some_method 
return 1,2,3 
end 

Inoltre, sono d'accordo con le altre risposte che il codice dovrebbe essere più asciutto, ma stavo solo cercando di chiarire la tua domanda iniziale.

0

avere una prova con questo codice

if current_user.find_voted_items(vote_scope: :inspired).include?(post) 
concat(link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do 
    safe_concat(content_tag(:i, "Inspired", calss: "fa fa-lightbulb-o")) 
end) 
concat(link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do 
    safe_concat(content_tag(:i, "Happy", calss: "fa fa-smile-o")) 
end) 
concat(link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do 
    safe_concat(content_tag(:i, "Disappointed", calss: "fa fa-meh-o")) 
end) 
concat(link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do 
    safe_concat(content_tag(:i, "Upset", calss: "fa fa-frown-o")) 
end) 
end 

Nota: Non hai testato.