Skip to content

Instantly share code, notes, and snippets.

@vendethiel
Last active February 21, 2024 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vendethiel/504c026965ddcfedece2 to your computer and use it in GitHub Desktop.
Save vendethiel/504c026965ddcfedece2 to your computer and use it in GitHub Desktop.
class RecordAddress
FIELDS = [:number, :country, :city_zip, :city_name, :street_name,
:latitude, :longitude, :geocoding_failed, :place_id]
BOOLEANS = [:geocoding_failed]
ASSOCIATIONS = [:place]
# @param [Object] object
# @param [Array] ary
def initialize(object, col)
@object = object
@col = col
# pour un `address_column :foo`, on recupere l'adresse serialisee dans "foo_text"
text = object.send("#{col}_text")
@attributes = if text.nil?
[''] * FIELDS.length # on genere un array vide avec des cases vides
else
text.split('|', -1) # -1 pour que "a|||" cree des elems vide pour ||| (trailing)
end
# quand on rajoute des colonnes ...
if @attributes.length < FIELDS.length
# ... on rajoute le nombre manquants de colonnes
@attributes.concat([''] * (FIELDS.length - @attributes.length))
end
end
def serialize
# on passe toutes les colonnes en String, on vire les | contenues,
# et on serialize en separant par |
@attributes.map{ |a| a.to_s.gsub('|', '') }.join('|')
end
def to_s
str = "#{self.number} #{self.street_name}, #{self.city_zip} #{self.city_name}"
return '' if str.strip == ','
str.gsub!(/\s+/, ' ')
str.gsub!(' ,', ',')
str
end
# @param [Hash] hash
def from_hash(hash)
FIELDS.each_with_index do |field, index|
@attributes[index] = hash[field] if hash[field].present?
end
do_serialize # save changes on parent object
end
def to_h(options = nil)
# champ -> valeur du getter
Hash[FIELDS.zip(FIELDS.map{ |c| self.send(c) })] # send() pour les getters overloaded
end
alias :as_json :to_h
def save
@object.save
end
# Lisp starts here ...
FIELDS.each_with_index do |field, index|
next if BOOLEANS.include?(field) # les booleens ont un autre getter genere
define_method field do # getter
# les attributs sont des array avec i=index du field dans FIELDS
# avec FIELDS=[:a,:b,:c], faire @attributes[1] c'est acceder a l'attribut :b
@attributes[index]
end
end # end getters
FIELDS.each_with_index do |field, index|
next if ASSOCIATIONS.include?("#{field}_id") # les assoc n'ont pas de `xxx_id=` (que des `xxx=`)
define_method "#{field}=" do |val| # setter
return if @attributes[index].to_s == val
@attributes[index] = val
@has_changed = true
do_serialize
end
end # end setters
BOOLEANS.each do |field|
define_method field do # specific getter
idx = FIELDS.index(field)
[1, '1', 'true'].include? @attributes[idx]
end
end
ASSOCIATIONS.each do |assoc| # on generate les associations
idx = FIELDS.index(:"#{assoc}_id") # field_id
klass = assoc.to_s.capitalize.constantize # la classe, ie Place
define_method("is_#{assoc}") { !@attributes[idx].blank? } #def is_place
define_method(assoc) { klass.find(@attributes[idx]) } #def place
define_method("#{assoc}=") do |val| #def place=
record = klass.find(val)
@attributes[idx] = record.id # val pourrait etre un objet (find le renverrait direct)
self.from_hash(record.address.to_h)
end
end
private
def do_serialize
@object.send("#{@col}_text=", self.serialize) # on met a jour l'objet qui inclut WithAddress
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment