Ciao a tutti,
Ho appena fatto un banalissimo plugin per rails, e mi ha scatenato il
dubbio
che io non stia facendo nel modo migliore la generazione automatica di
metodi in ruby… ok, mi spiego meglio (non è necessaria la conoscenza di
rails per godersi il post)
Per questo vi sfido (per gioco ovvio, visto che so di perdere:-)) a
trovare
una soluzione migliore…
Ho un oggetto che mi rappresenta un record di stima di un preventivo,
nel
quale devo salvare un campo discount che è un Float (lo sconto deve avere
2
decimali).
Io NON voglio salvare il float a DB ma voglio moltiplicarlo e dividerlo
per
100 ogni volta che lo salvo/leggo da db, in pratica lo salvo in
centesimi.
La cosa si fa così, da documentazione di rails:
class Estimate < ActiveRecord::Base
def discount=(value)
write_attribute(:discount, value * 100)
end
def discount
read_attribute(:discount) / 100
end
end
(soprassediamo sul fatto che non converte a float, ma non è quello il
punto)
Il problema è che io potrei avere 200 campi che voglio salvare in questo
modo, quindi con il sopracitato plugin voglio convertire il codice in:
class Estimate < ActiveRecord::Base
store_as_cents :discount
end
A questo punto parte la sfida: devo definire il metodo store_as_cents in
modo che mi crei in modo dinamico i getter e i setter.
Ho implementato il plugin come modulo in modo da mixare
store_as_centsinvece che ‘aprire’ la classe
ActiveRecord::Base, mi pare una soluzione più pulita e meno invasiva, ma per
qualche motivo ho la sensazione che si possa fare di meglio.
Di seguito la mia soluzione:
require ‘active_record’
module StoreAsCents
def self.included(mod)
mod.extend(ClassMethods)
end
module ClassMethods
# dinamically creates
# getters and setter that divide or multiply by 100
def store_as_cents(field_sym)
methods = <<-EOF
def #{field_sym}=(value)
write_attribute(:#{field_sym}, value * 100)
end
def #{field_sym}
read_attribute(:#{field_sym}) / 100
end
EOF
class_eval methods
end
end
end
includes new methods
ActiveRecord::Base.class_eval do
include StoreAsCents
end
Mi pare contorto il fatto di dovere includere il modulo e poi dire al
modulo
che quando è incluso la classe deve estendere un’altro modulo interno e
bla
bla… ma così viene fatto nei plugins di rails che ho visto in giro…
Gabriele ormai mi ha convinto che rails fa schifo, quindi ora dobbiamo
trovare un modo migliore di fare sta cosa for god’s sake!!
Il per sempre vostro kamikaze,
Paolo