Posts Tagged Rails

Rails, OpenID, search, sort, tag cloud

Titolo invero strano, ma stamattina, con 300 righe di codice, ho fatto
questo: http://casamia.prosa.it.

A parte la stupidità, nonché inutilità del sito e la grafica assolutamente obrobriosa, quello che mi serviva era fare una prova di applicazione che avesse queste caratteristiche:

  1. supporto utenti via OpenID
  2. supporto i18n (globalize)
  3. supporto tag (act_as_taggable) e la sua bella “tag cloud”
  4. filtro AJAX
  5. sorting, sempre via AJAX

Beh, http://casamia.prosa.it, ha tutte queste caratteristiche, ed è stato anche piuttosto semplice realizzarle.

Su OpenID consiglio la lettura del blog di Dag Rorek. Per globalize c’è un semplice articolo su TheRubyMine,
per act_as_taggable e la “tag cloud” c’è tanta di quella roba che ve la cercate da soli; infine per il filtro e il sorting via AJAX, consiglio questo esempio.

Buon divertimento.

, ,

No Comments

Currency e globalize

Proge, il semi-quasi-gestionale in ruby on rails che sto cercando di scrivere, deve ovviamente gestire dei campi monetari; basta pensare all’ammontare di una fattura, o alla registrazione in contabilità di un movimento. Dato che sto usando il plugin globalize per l’i18n dell’applicazione (anche se al massimo, la userò solo io :-) ), ho pensato di avere il campo monetario localizzato a sua volta.

La documentazione mi ha un po’ tratto in inganno, percui lascio un paio di appunti sul blog a futura memoria e sperando che possano essere d’aiuto anche a altri.

Quello che volevo fare era avere un campo “price” salvato sul database come integer (sul perché è un male gestire queste cose con un float, c’è parecchia documentazione in giro) e che potesse essere gestito con la localizzazione.

Nel modello dell’oggetto, chiamiamolo nell’esempio “prodotto”, la documentazione dice di aggiungere:

composed_of :price, :class_name => “Globalize::Currency”, :mapping => [ %w(price cents) ]

Quando in una view farò <%= @product.price %> questo mi verrà visualizzato opportunamente localizzato.

E fin qua è facile. Il problema era che non capivo come salvare quel campo, lasciando libero l’utente di inserire un valore nel campo price seguendo le convenzioni della locale impostata. Insomma, se sono italiano, voglio essere libero di inserire 6,52 per esperimere 6 euro e 52 centesimi, e inserire 7.64 per inserire 7 dollari e 64 centesimi se sono americano: il controller dovrà salvare rispettivamente 652 e 764 nel database.

Nella view del classico _form.rhtml avrò l’ancora più classico:



<%= text_field 'pp', 'price' %>

Mentre nel controller, avrò:

@product.price = Currency.parse(@params[:pp][:price]).cents

In pratica devo fare il parsing del valore passato nel form, tramite la funzione della classe Currency e dovrò poi prendere l’attributo cents; dalla documentazione questo non era chiaro, sembrava che parse avrebbe fatto tutto, invece leggendo il codice ho capito dove stava l’inghippo.

Ah, infine, affinché il parse funzioni con qualsiasi locale bisogna patchare globalize con questa patch, altrimenti lui capisce solo valute americane.

, ,

No Comments

preview per Freego

Da quando uso Typo per il blog, mi sono abituato alla preview: quando sto inserendo un articolo, questo viene visualizzato “al volo” così come dovrebbe apparire nel blog.

Ho pensato, quindi, di aggiungerlo a Freego, che essendo scritto in Ruby on Rails mi facilita il “porting” di questa feature. Tra l’altro su Freego mi torna utile: le news che inserisco li’, infatti, sono spesso piene di link e non ci si accorge di errori sull’html se non visualizzando la news già salvata.

Aggiungere la preview di una news (o qualsiasi altra cosa simile) è stato molto semplice.

Nella view news/new.rhtml ho aggiunto (partendo dallo scaffold):

<%= javascript_include_tag :defaults %>

Il start_form_tag ora ha un id, per poterlo identificare:

<%= start_form_tag ({:action => 'create'}, :id => 'form_edit_news') %>
  <%= render :partial => 'form' %>
  <%= submit_tag "Invia" %>
<%= end_form_tag %>

Poi ho aggiunto una chiamata AJAX:

<%= observe_form "form_edit_news",
                    :frequency => 3.0,
                    :update    => 'ajaxWrapper',
                    :loading_text => "Retrieving data...",
                    :complete  => "Element.hide('spinner')",
                    :before    => " Element.show('spinner')",
                    :url       => {:action=>'preview', :o nly_path => false} %>

Questa chiamata controlla modifiche al form per l’editing della news, ogni 3.0 secondi, e aggiorna l’elemento ‘ajaxWrapper’, chiamando l’azione ‘preview’. Quello che segue è l’elemento ‘ajaxWrapper’, che tramite un partial rende la preview della news.

<div id='ajaxWrapper'>
<%= render :partial=>'preview', :o bject => @new_news, :layout => false %>
</div>

Piuttosto banale, eh? Qui ho descritto solo le parti fondamentali; se qualcuno vuole proprio vedere il codice intero, ricordo che Freego è GPL.

, ,

No Comments

Proge, globalize

Oggi ho aggiunto a Proge, il “gestionale” di cui parlavo alcuni giorni fa che sto sviluppando con Ruby On Rails, il supporto per l’internazionalizzazione. In realtà non ho fatto molto, dato che come al solito in Ruby On Rails è sufficiente installare un plugin e iniziarlo a usarlo. Giusto mentre lo stavo usando, è uscito un articolo in italiano a tal proposito su therubymine.com.

Proge comincia a avere la sua consistenza e gestisce ad oggi (più o meno correttamente :-) ):

  • clienti/fornitori
  • prodotti e servizi
  • registrazione fatture attive e passive
  • categorie (di prodotti, servizi o altro)
  • progetti e ticketing system con priorità
  • movimentazione merci, carico, scarico, trasferimenti
  • lotti/partite di merci, in acquisto e vendita
  • magazzini/porti, vettori e altro utile alla movimentazione merci

Il tutto senza aver scritto quasi una riga di codice. Dico quasi, perché la situazione di magazzino non sono riuscito a farla senza.

Pur avendo detto che magazzini has_many :lotti, :through quantità, non sono riuscito a fare qualcosa tipo Magazzino.quantità.sum(:group quantità) e ho dovuto farmi un find_by_sql a mano. Amen.

,

No Comments

Typo trunk su ubuntu

Tenere un blog, non è il mio forte, si sa.

Ho avuto da fare in questo periodo e non ci sono stato dietro,
così non mi sono accorto che questo blog per un po’ non ha funzionato.

Il problema era ancora una volta Typo, questo maledetto, e la sua sporca compagna Rails, il vendicativo Ruby e il falso Mysql.

La versione che era precedentemente installata di Typo, non funzionava con Rails 1.1; questo non funzionava con Ruby 1.8.3; Rails vs Mysql non funzionava, se non con libmysql-ruby1.8; etc. etc.

Ho dovuto quindi aggiornare Typo alla versione ”trunk”, aggiornare Ubuntu all”ultima versione, installare libmysql-ruby1.8, rinunciare a fcgi, dare un colpo di `rake migrate RAILS_ENV=production`, reimpostare tutti i file con i permessi e l’owner giusti (lo erano già in teoria … boh), e ora, se leggete questo articolo va.
Ma che fatica.

Comincia a starmi sulle balle, dover essere aggiornato su tutte le combinazioni esatte di versioni dei vari programmi che devo avere, affinché tutto funzioni. Ma un minimo di retrocompatibilità, no, eh?
Qua, il software libero, è un po’ troppo “libero” :-)

, ,

No Comments

Le tasse in Ruby On Rails

Provando Ruby on Rails su una applicazione “reale”, mi sono scontrato con un problema di pluralizzazione (si dice cosi`?).

Avevo creato una semplice tabella “taxes”, e usando il metodo ’scaffold’ per generare controller, model e view varie.

Richiamando http://applicazione/taxes/list però, ottenevo un errore, in quanto Ruby On Rails non era in grado di trovare la costante “Taxis”. Si, avete letto bene, cercava il plurale di “Taxi” e non di “Tax”; il bello è che trova correttamente il plurale di “Tax”, ma non il singolare di “Taxes” :-) .

Ho risolto, forzando il corretto plurale e singolare in enviroment.rb:

Inflector.inflections do |inflect|
  inflect.plural ''tax'', ''taxes''
  inflect.singular ''taxes'', ''tax''
end

Però mi sono fatto due risate: tu, RoR, mi “costringi” a usare queste tue convenzioni per tabelle, nomi di controller, etc. e poi fai questi errori? :-)

,

No Comments