Forum: Italian Ruby user group uso degli helpers - ciclo if else

Posted by Paola Andriani (corto_maltese)
on 2010-02-24 13:10
Buongiorno a tutti, premetto che non sono per niente esperta di rails e
ruby ma sto cominciando da poco a bazzicarlo.
Detto questo, sto facendo un po' di esperimenti in un progetto che
prevede tra le tante cose, una tabella anagrafica di determinate
personalità storiche. Queste Persone (ho chiamato così la tabella) non
hanno una data di nascita o morte precisa ma un intervallo di date.
Vorrei che fossero visualizzati entrambi gli intervalli se sono stati
inseriti, solo uno dei due se è stato completato solo un campo.
Ho usato un ciclo if else e ho fatto quindi così (dove int_nascita1 e
int_nascita2 sono appunto i due intervalli relativa alla data) :

app/views/index.html.erb

<% @persone.each do |persona| %>
<tr>
    <td><%= link_to persona.nome, :action =>'show', :id => persona.id
%></td>

  <% if persona.int_nascita2.nil? or persona.int_nascita2 == "" %>
  <td><%=h persona.int_nascita1 %></td>
  <% else %>
  <td><%=h persona.int_nascita1 %> - <%=h persona.int_nascita2 %></td>
  <% end %>

resto del codice[...]

Il tutto funziona. Mi hanno però consigliato di spostare i cicli if
dalle views agli helpers in modo da tenere il codice più pulito ma io
non sono riuscita a farlo.

Ho pensato di farlo così, ma non funziona, qualcuno sa dirmi gentilmente
dove sbaglio??

app/views/index.html.erb

<% @persone.each do |persona| %>
    <td><%= link_to persona.nome, :action =>'show', :id => persona.id
%></td>

  <td><% hidden_data(persona.int_nascita2.nil?, persona.int_nascita2 ==
"", persona, persona.int_nascita1) %></td>

resto del codice[...]


app/helpers/persone_helper.rb

module PersoneHelper
  def hidden_data(condition1, condition2, column1, column2)
    if condition1 or condition2
       Persona.column1
    else
    Persona.column1 + "-" + Persona.column2
    end
  end
end

Grazie in anticipo a chiunque abbia voglia di aiutarmi!
paola
Posted by Pietro Giorgianni (giorgian)
on 2010-02-24 13:42
(Received via mailing list)
Il 24 febbraio 2010 13.10, Paola Andriani <nuvola@elbalink.it> ha 
scritto:
> [...] una tabella anagrafica di determinate
> personalità storiche. Queste Persone (ho chiamato così la tabella) non
> hanno una data di nascita o morte precisa ma un intervallo di date.
> Vorrei che fossero visualizzati entrambi gli intervalli se sono stati
> inseriti, solo uno dei due se è stato completato solo un campo.
> [...]
> Il tutto funziona. Mi hanno però consigliato di spostare i cicli if
> dalle views agli helpers in modo da tenere il codice più pulito ma io
> non sono riuscita a farlo.

ciao,

Poiché il test nil? e == "" è uno dei più frequenti, rails ha
introdotto un più stringato blank?, che è comodissimo.

Ecco un esempio di come potresti fare:
# app/helpers/persone_helper.rb
module PersoneHelper
  def valore_o_intervallo_di_nascita persona
    if persona.int_nascita2.blank?
      h(persona.int_nascita1)
    else
      "#{h(persona.int_nascita1)}-#{h(persona.int_nascita2)}"
    end
  end
end

<% @persone.each do |persona| %>
  <tr>
    <td><%= link_to h(persona.nome), :action =>'show', :id => persona.id 
%></td>
    <td><%= valore_o_intervallo_di_nascita persona %></td>
    ...

Ultima considerazione: se stai usando rails nel modo più comodo, cioè 
seguendo le varie convenzioni tra cui REST (ad esempio, se usi
scaffold o simili), il link lo puoi scrivere 
così:
<%= link_to h(persona.nome), persona %>

Più breve e leggibile.


pietro
Posted by Paola Andriani (corto_maltese)
on 2010-02-24 18:11
Grazie!! Funziona perfettamente!
Mi spiegheresti gentilmente un paio di cose?

il significato dell'h e delle parentesi tonde qui davanti
 h(persona.int_nascita1)
e le virgolette, il cancelletto e le parentesi graffe qui davanti
"#{h(persona.int_nascita1)}-#{h(persona.int_nascita2)}"

insomma gli accorgimenti per costruire il tutto, ne ho giusto una vaga 
idea.

Grazie ancora!
Posted by Pietro Giorgianni (giorgian)
on 2010-02-24 18:45
(Received via mailing list)
Il 24 febbraio 2010 18.11, Paola Andriani <nuvola@elbalink.it> ha 
scritto:
> Grazie!! Funziona perfettamente!
> Mi spiegheresti gentilmente un paio di cose?
>
> il significato dell'h e delle parentesi tonde qui davanti
>  h(persona.int_nascita1)

h è un'abbreviazione (un alias) per html_escape:

http://api.rubyonrails.org/classes/ERB/Util.html#M000315

Come dice il nome, fa l'escape dell'html, vale a dire rimpiazza tutti
i caratteri che in html hanno un significato particolare in apposite
sequenze con la loro versione "innocua".
Ad esempio, < viene trasformato in &lt; e > in &gt;.
Questa è un'operazione importantissima, da effettuare *sempre* su
*tutti* i caratteri digitati dall'utente, per impedire il Cross Site
Scripting (anche detto XSS):

http://it.wikipedia.org/wiki/Cross-site_scripting

In pratica, un utente potrebbe riempire un form con valori tipo:
<script type="text/javascript" 
src="url/di/uno/script/che/fa/cose/brutte.js">

Così facendo, potrebbe danneggiare gli utenti che accedono alla pagina
che mostra quei dati.
L'html escape fa sì che la riga precedente venga tradotta in


&lt;script type=&quot;text/javascript&quot;
src=&quot;url/di/uno/script/che/fa/cose/brutte.js&quot;&gt

Col risultato che il javascript non verrebbe eseguito: un utente che
guardasse i dati vedrebbe esattamente la stringa come l'ha inserita
l'utente, cioè di nuovo:
<script type="text/javascript" 
src="url/di/uno/script/che/fa/cose/brutte.js">

Anche se sai che la tua applicazione sarà usata solo da pochi fidati,
è buona norma usare *sempre* h o equivalenti, perché non si sa mai (ad
esempio, magari tra un anno si decide di esporre al pubblico tutta o
parte dell'applicazione...).

> e le virgolette, il cancelletto e le parentesi graffe qui davanti
> "#{h(persona.int_nascita1)}-#{h(persona.int_nascita2)}"

Questa è una sintassi di ruby:

"#{a}"

è equivalente a:

a.to_s

(to_s trasforma un oggetto in stringa, se non lo è già).

Esempio:

"#{3 + 2}" dà come risultato "5".

pietro
Posted by Paola Andriani (corto_maltese)
on 2010-02-25 12:50
Grazie!!
paola
Posted by Paola Andriani (corto_maltese)
on 2010-02-26 10:53
Già che ci sono chiedo un'altra cosa.
Ho una serie di attributi per la visualizzazione delle fonti secondarie:

<h1>Elenco fonti secondarie</h1>


<% @secondarie.each do |secondaria| %>
 <ul>
  <li>
    <%=h secondaria.autore %> (<%=h secondaria.anno_edizione %>) 
<em><%=h secondaria.titolo %></em>, <%=h secondaria.luogo %>, <%=h 
secondaria.casa_editrice %>

  <br />

resto del codice [...]

Sono quasi tutti opzionali, quindi nel momento in cui vado a 
visualizzarli ovviamente se uno è mancante si vede il segno di 
interpunzione senza avere il campo stampato.
Ho pensato quindi di utilizzare sempre i cicli per stampare quelli 
presenti con virgola annessa, ma inutile dirlo, non ci sono riuscita.

Ho provato così:

  def bibliografia secondaria
    a = [secondaria.autore, secondaria.anno_edizione, secondaria.titolo]
    a.each do |x|
      "#{h(secondaria.autore)}(#{h(secondaria.anno_edizione}),#{h(secondaria.titolo)}"
    end
  end

o così:
 def bibliografia secondaria
    a.each do |secondaria.autore, secondaria.anno_edizione, 
secondaria.titolo|
      "#{h(secondaria.autore)}(#{h(secondaria.anno_edizione)}),#{h(secondaria.autore)}"
    end
  end

più altri tentativi con
if secondaria.autore.present?

ma senza arrivare a nulla.
Avete qualche suggerimento?
Grazie ancora paola



Posted by Pietro Giorgianni (giorgian)
on 2010-02-26 10:58
(Received via mailing list)
Il 26 febbraio 2010 10.53, Paola Andriani <nuvola@elbalink.it> ha 
scritto:
> <em><%=h secondaria.titolo %></em>, <%=h secondaria.luogo %>, <%=h
> secondaria.casa_editrice %>
>
>  <br />
>
> resto del codice [...]
>
> Sono quasi tutti opzionali, quindi nel momento in cui vado a
> visualizzarli ovviamente se uno è mancante si vede il segno di
> interpunzione senza avere il campo stampato.

Non ho capito bene: è possibile che ci sia ad esempio autore e titolo
ma non anno_edizione e luogo? Oppure è possibile che ci sia un record
interamente bianco?

Cioè, quali sono i campi che sicuramente non sono vuoti?


pietro
Posted by Paola Andriani (corto_maltese)
on 2010-02-26 11:15
Si quello che ho postato è l'esperimento con le fonti secondarie, quindi 
in linea di massima avranno tutti i campi completati, la stessa cosa 
però dovrò farlo con le fonti primarie dove regna l'incertezza. Spesso 
può esserci un campo solo completato o due, etc, insomma estremamente 
variabile.

Vorrei quindi che venisse fuori una sorta di bibliografia settata 
correttamente, ovviamente nei limiti del possibile.

Ho provato anche così:

  def bibliografia secondaria
    i = [secondaria.autore, secondaria.anno_edizione, secondaria.titolo]
      while i.present?
        puts "#{h(i)},"
    end
  end

dato che in realtà prima stavo solo facendo delle prove, senza 
effettivamente dirgli "metti la virgola dopo ogni campo presente".

In realtà la cosa è ancora un pelo più complicata, quello che 
effettivamente devo dirgli è:
se c'e l'autore visualizzalo
se c'è l'anno di edizione visualizzalo fra parentesi
se c'è il titolo visualizzalo in corsivo (cioè fra gli <em></em>) e dopo 
mettici la virgola
se c'e il luogo di edizione visualizzalo e dopo mettici la virgola
se c'è la casa editrice visualizzalo

spero di essere stata più chiara!
grazie ancora!
Posted by Paola Andriani (corto_maltese)
on 2010-02-26 11:24
Diciamo che il campo che ci sarà sicuramente sarà quello del titolo, in 
effetti potrei anche mettere una validazione su di esso.
Posted by Pietro Giorgianni (giorgian)
on 2010-02-26 11:53
(Received via mailing list)
Il 26 febbraio 2010 11.15, Paola Andriani <nuvola@elbalink.it> ha 
scritto:
> In realtà la cosa è ancora un pelo più complicata, quello che
> effettivamente devo dirgli è:
> se c'e l'autore visualizzalo
> se c'è l'anno di edizione visualizzalo fra parentesi
> se c'è il titolo visualizzalo in corsivo (cioè fra gli <em></em>) e dopo
> mettici la virgola
> se c'e il luogo di edizione visualizzalo e dopo mettici la virgola
> se c'è la casa editrice visualizzalo

Parti da questo:

  def bibliografia_secondaria secondaria
    result = []
    result << h(secondaria.autore) unless secondaria.autore.blank?
    result << " (#{h secondaria.anno_edizione})" unless
secondaria.anno_edizione.blank?
    result << " <em>#{h secondaria.titolo}</em>"
    result << ", #{h secondaria.luogo}" unless secondaria.luogo.blank?
    result << ", #{h secondaria.casa_editrice}" unless
secondaria.casa_editrice.blank?
    result.join ''
  end

da usare con:

<ul>
  <% @secondarie.each do |secondaria| %>
   <li>
     <%= bibliografia_secondaria secondaria %>
  </li>
  <% end %>
</ul>

E aggiustalo secondo le tue 
necessità.

pietro
Posted by Paola Andriani (corto_maltese)
on 2010-02-26 14:14
Intanto ringraziamenti infiniti...poi mi spiegheresti qualcosa così 
imparo (se hai voglia e tempo)?

> Parti da questo:
> 
>   def bibliografia_secondaria secondaria
bibliografia_secondaria (nome del modulo), secondaria cos'è? cosa gli 
dice di recuperare? i campi della tabella "secondaria"?

>     result = []
questo crea un array con i "risultati delle operazioni"?

>     result << h(secondaria.autore) unless secondaria.autore.blank?

<< cos'è? restituisce il valore dopo averlo processato?

al posto di unless secondaria.autore.blank? potevo usare anche if 
secondaria.autore.present? ?

>     result.join ''
join?

paola






Posted by Pietro Giorgianni (giorgian)
on 2010-02-26 14:45
(Received via mailing list)
Il 26 febbraio 2010 14.14, Paola Andriani <nuvola@elbalink.it> ha 
scritto:
>>   def bibliografia_secondaria secondaria
> bibliografia_secondaria (nome del modulo), secondaria cos'è? cosa gli
> dice di recuperare? i campi della tabella "secondaria"?

Qui definisco una funzione, bibliografia_secondaria, e dico che ha un
parametro, che in questo caso ho chiamato secondaria ma che avrei
potuto chiamare anche a, oppure la_vispa_teresa, e sarebbe stata la
stessa cosa. Naturalmente nel corpo della funzione avrei poi dovuto
usare a oppure la_vispa_teresa.

Quello che poi conta è ciò che gli viene passato; nel mio esempio gli
viene passata la variabile "secondaria", che esiste solo all'interno
del blocco passato a each, e in quel contesto contiene un elemento
dell'array @secondarie:

 <% @secondarie.each do |secondaria| %>
  <li>
    <%= bibliografia_secondaria secondaria %>
 </li>
 <% end %>

>>     result = []
> questo crea un array con i "risultati delle operazioni"?

Questo crea un array che, casualmente, ha il nome result, ma anche qui
avrei potuto scegliere un nome diverso, come un_nome_diverso; è però 
convenzione chiamare result la variabile che conterrà i dati da
restituire.


>>     result << h(secondaria.autore) unless secondaria.autore.blank?
>
> << cos'è? restituisce il valore dopo averlo processato?

<< è un metodo della classe Array, che aggiunge ciò il parametro o i
parametri forniti alla fine dell'array ed ha come valore di ritorno
l'array stesso.

Ti consiglio la lettura della documentazione della classe Array, e in
particolare di questo metodo:
http://ruby-doc.org/core/classes/Array.html#M002167

> al posto di unless secondaria.autore.blank? potevo usare anche if
> secondaria.autore.present? ?

Sì.
>>     result.join ''
> join?

join è un altro metodo della classe Array:

http://ruby-doc.org/core/classes/Array.html#M002182

Quello che fa è restituire una stringa contenente gli elementi
dell'array trasformati in stringa, separati dall'eventuale separatore
(che se manca è stringa vuota, come quella che gli passo io, quindi in
effetti avrei potuto scrivere
result.join
e sarebbe stato uguale).

Esempio:
>> a = ["oggi", "ieri", "domani"]
>> a.join " ma anche "
=> "oggi ma anche ieri ma anche domani"


pietro
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.