RSS
 

Posts Tagged ‘Rails’

Leonardo: un generatore di applicazioni Rails 3.1

22 Aug

L’aggiornamento alla versione più recente lo trovi sul mio nuovo blog. Click here for the english version.

Ho creato un nuovo generatore per creare applicazioni rails 3.1 (che attualmente si trova in rc6) ed automatizzare le operazioni che risultano ripetitive.

Il nome della gemma è leonardo ed è suddivisa in due generatori:

  1. leolay: per creare il layout
  2. leosca: per creare la risorsa (sostituisce lo scaffold)

Perchè creare un nuovo generatore se esiste già lo scaffold di rails?

Lo scaffold è un comodo generatore e si può anche personalizzare con facilità ma è adatto per scopi didattici e la personalizzazione è limitata alle sole viste. In produzione mi serviva qualcosa di più completo e personalizzabile.

Preparazione dell’ambiente ed installazione della gemma

Creiamo un nuovo ambiente ruby ed installiamo rails 3.1:
gem install rails –pre
usiamo il –pre perchè in questo momento si trova in release candidate, toglietelo se invece è stata rilasciata

Possiamo installare la gemma semplicemente con:
gem install leonardo

…ma non è necessario e consiglio di usare il procedimento che sto per descrivere:
creiamo una nuova applicazione utilizzando il template che ho preparato, raccomandato per agevolare l’avvio e per meglio sfruttare la gemma:

rails new NewApp -m http://cloud.github.com/downloads/marcomd/Leonardo/template.rb

Se non dovesse funzionare il link potete comunque trovare il template nella root della gemma

Il template chiederà se installare determinate gemme esterne, per una prova consiglio di installarle tutte rispondendo y o premendo invio quando propone un default (es. devise)

Verrà poi eseguito un bundle install per verificare la presenza delle gemme ed in seguito verranno eseguite le varie generazioni, il tutto durerà qualche minuto circa.
La generazione del layout chiederà una conferma per sostituire il file en.yml, rispondete y. Preferisco non forzare la sostituzione per permettere altre ed eventuali esecuzioni del generatore leolay nel caso si volesse aggiornare il layout.

Al termine otterrete un applicazione “pronta per partire” potendo così orientare lo sviluppo sulla parte applicativa.

Spostiamoci nella cartella dell’applicazione ed avviamo il server
cd NewApp
rails s
indirizziamo il browser all’indirizzo http://localhost:3000 per accedere alla home

Se clicchiamo su “Sign in” verrà richiesta l’autenticazione (se l’avete inclusa), per un rapido accesso potete inserire:
email: admin@newapp.com
password: abcd1234

Signed in

Vengono create tre utenze con tre ruoli diversi (nel caso avete incluso le autorizzazioni):

  1. admin@newapp.com
  2. manager@newapp.com
  3. user@newapp.com

Naturalmente si tratta di utenze con finalità legate allo sviluppo per cui ricordate di eliminarle prima di qualsiasi rilascio. Possiamo consultare e modificare i ruoli accedendo al file app/models/ability.rb in quanto la gestione è affidata alla gemma cancan.

Per cambiare la lingua è sufficiente inviare la nuova come valore del parametro lang, esempio:

http://localhost:3000/?lang=it

il generatore attualmente gestisce :en e :it ma aggiungere il supporto ad un’altra lingua è semplice, basta aggiungere il file yml nella cartella dove si trovano i primi due, naturalmente deve avere gli stessi tags.

Generare le risorse

Ora generiamo qualche risorsa utilizzando il generatore leosca, una sorta di scaffold personalizzato:

rails g leosca category name:string active:boolean

rails g leosca product category:references name:string description:text price:decimal

ora creiamo le due nuove tabelle anche sul database:
rake db:migrate

ed eseguiamo anche il popolamento con qualche dato che leosca ha preparato per noi:
rake db:seed

Listing Categories

Alcune note:

  • L’esportazione dei dati in csv attualmente non funziona se attiva la paginazione ajax, sto cercando un buon metodo per risolvere.
  • Nelle liste vengono inseriti in automatico tutti i campi per poter applicare dei filtri, eliminiamo quelli che non ci interessano. I filtri su campi boolean non funzionano con sqlite3 a causa di un bug nel driver che non genera un sql corretto. Con SQLServer funziona alla perfezione.
  • Gli oggetti relazionati mostrano un link col nome e cliccando si effettua una :show. Nel caso la tabella non abbia il campo :name viene utilizzato l’id che è possibile sostituire con il dato che più lo rappresenta.
  • Solo l’operazione destroy è gestita tramite ajax. Show, edit e create attualmente sono gestite tramite http.
  • Riguardo le utenze create in automatico: con i ruoli di default admin può fare tutto, manager tutte le operazioni crud, user tutte tranne la delete.
  • Le etichette dei campi vengono inserite in automatico ma la traduzione è necessario farsela da se all’interno dei files config/locales/*.yml

Personalizzare il generatore

E’ sufficiente installarlo nel progetto e personalizzarlo secondo le proprie esigenze:
rails g leosca:install
si trova sotto lib ed eventuali modifiche avranno la precedenza sulla gemma

Conclusioni

Per ulteriori approfondimenti o aggiornamenti sugli sviluppi futuri è possibile consultare la homepage del progetto:
https://github.com/marcomd/Leonardo

Altri riferimenti:
http://edgeguides.rubyonrails.org/generators.html
http://railscasts.com/episodes/216-generators-in-rails-3
http://railscasts.com/episodes/218-making-generators-in-rails-3
http://railscasts.com/episodes/242-thor
http://rdoc.info/github/wycats/thor/master/Thor
http://textmate.rubyforge.org/thor/Thor/Actions.html
http://railscasts.com/episodes/265-rails-3-1-overview

 
 

Pluralizzare in tutte le lingue

08 Sep

In questo articolo mostrerò come utilizzare quel comodo helper di rails, pluralize, con tutte le lingue mediante l’utilizzo di I18n.

Diamo per scontato che l’applicazione sia internazionalizzata, quindi modelli e campi presenti nei file yaml di configurazione.
Ora dobbiamo aggiungere i termini per i quali vogliamo internazionalizzare la pluralità: modelli, attributi ecc.

activerecord: &activerecord
    models: &models
      user: "Utente"
      users: "Utenti"
      activity: "Impiego"
      activities: "Impieghi"
      task: "Incarico"
      tasks: "Incarichi"
      project: "Progetto"
      projects: "Progetti"
 
    attributes: &attributes
      activity:
        task: "Incarico"
        day: "Giorno"
        hours: "Ore"
        hour: "Ora"
        description: "Descrizione"

Ipotizziamo che il nostro modello “Incarico” sia relazionato col modello “Impiego” e che questo abbia un campo di nome “Ore”. Vogliamo creare una frase che descriva quanti impieghi sono presenti per tale incarico ed il totale delle ore.

In base ai dati nel database, vogliamo ottenere frasi del tipo:
Questo incarico ha 1 impiego per un totale di 1 ora.
Questo incarico ha 13 impieghi per un totale di 0 ore.
Questo incarico ha 1 impiego per un totale di 15 ore.

…e in tutte le lingue:

This task has 1 activity with an amount of 15 hours.
Diese Aufgabe haben 1-Aktivität für eine Gesamtmenge von 15 Stunden.
Cette tâche a 1 activité pour un total de 15 heures.
Esta tarea tiene 1 actividad para un total de 15 horas.
このタスクは、 15時間の量1活性を持つ

Vogliamo evitare:
Questo incarico ha 1 impieghi per un totale di 1 ore
This task has 1 activities with an amount of 1 hours

Aggiungiamo la frase in ogni file yaml I18n:

  #it.yml
  task_activities: "Questo incarico ha <strong>{{activities}}</strong> per un totale di <strong>{{hours}}</strong>."
  #en.yml
  task_activities: "This task has <strong>{{activities}}</strong> with an amount of <strong>{{hours}}</strong>."
  #etc.

Per fare ciò ci avvaliamo del comodo helper di rails, pluralize, opportunamente modificato per eliminare il numero dal risultato. Pluralizziamo il termine inglese da usare come chiave per I18n.

Creiamo nell’helper dell’applicazione:

module ApplicationHelper
   #Pluralize without the number
   def I18n_pluralize(count, singular, plural = nil)
     ((count == 1 || count =~ /^1(\.0+)?$/) ? singular : (plural || singular.pluralize))
   end
end

Nella view richiamiamo la frase I18n passando il numero di impieghi ed il totale di ore (per motivi descrittivi ho inserito nella view operazioni che però riterrei più opportuno posizionare nel controller):

  <% tot_hours = @activities.map{|a| a.hours}.inject{|tot,h| tot+h}  || 0 %>
  <% str_hour = t("attributes.activity.#{I18n_pluralize(tot_hours,'hour')}") %>
  <% str_activity = t("models.#{I18n_pluralize(@activities.size,'activity')}") %>
  <%= t :task_activities, :activities => "#{@activities.size} #{str_activity}", :hours => "#{@tot_hours} #{str_hour}" %>

Osserviamo questa riga alla moviola:

t("attributes.activity.#{I18n_pluralize(tot_hours,'hour')}")

In base al numero di ore otteniamo la chiave I18n: hour o hours

chiave = I18n_pluralize(tot_hours,'hour')

equivale

t("attributes.activity.#{chiave}")

se tot_hours = 1 avremo:

t("attributes.activity.hour")

altrimenti:

t("attributes.activity.hours")

Questo è il risultato:
Esempio Pluralize I18n

 
Comments Off

Posted in Ruby on Rails