Skip to content

Instantly share code, notes, and snippets.

@silvioq
Created November 20, 2009 09:36
Show Gist options
  • Save silvioq/239382 to your computer and use it in GitHub Desktop.
Save silvioq/239382 to your computer and use it in GitHub Desktop.
Best Describe
# BestDescribeRecord
module ActiveRecord
# Best Describe!
class Base
# Definición de cómo describir al registro
# Si no se ha especificado el "best_describe",
# entones el plugin intentará descubrir cómo
# mejor descibir al registro ... Si hay un atributo
# :name, entones lo usa. Si no, toma el primer atributo
# del tipo string.
#
# Uso:
# class Client
# best_describe { |r| "#{r[:last_name]}, #{r[:first_name]}" }
# end
# Client.find(:first).best_describe
#
# class Product
# best_describe :desription
# end
# Product.find(:first).best_describe
#
def self.best_describe(what=nil,&proc)
if proc
@best_describe = proc
else
@best_describe = what.to_sym
end
end
# Descubre qué atributo describe mejor al
# registro
def self.best_describe_discover
if column_names.include? "name"
best_describe :name
else
content_columns.each{ |col|
if col.type.to_sym == :string
best_describe col.name.to_sym
return
end
}
if content_columns[0]
best_describe content_columns[0].name.to_sym
return
else
best_describe columns[0].name.to_sym
end
end
end
# Devuelve la definición de cómo describir
def self.best_describe_def; @best_describe; end
# Uso:
# Client.find(:first).best_describe
def best_describe
d = self.class.best_describe_def
if d.nil?
self.class.best_describe_discover
d = self.class.best_describe_def
end
raise "No puedo describir al registro" if d.nil?
if d.class == Symbol and d.respond_to? d
self.send d
elsif d.class == Symbol
self[d]
elsif d.class == Proc
d.call self
else
"No describe"
end
end
#
#
# = Best describe column
# Define como se describe una columna
# Parametros
# - Nombre de la columna
# - Forma de describir: :self, :proc, :reflection, :constant, :description_method o :describe_method
# - Parámetro auxiliar: Para :reflection es el nombre de la misma y para :constant el nombre de la constante
def self.best_describe_column( column, way, param = nil, &proc )
raise "#{column} no es una columna" unless self.columns_hash[column.to_s]
raise "Parámetro #{way} incorrecto" unless [:self, :reflection, :proc, :constant, :description_method, :describe_method].include? way
raise "#{param} no es una constante" if way == :constant and !self.constants.include? param
raise "#{param} no es una refleccion" if way == :reflection and !self.reflections[param]
@best_describe_columns[column.to_sym] = { :way => way, :param => param, :proc => proc }
end
def self.column_belongs_to_discover(column)
self.reflections.each{ |name,r|
return r.name if r.macro == :belongs_to and r.primary_key_name.to_s == column.to_s
}
false
end
# Descubre la mejor forma de describir una columna ...
# Si es un belongs_to, devuelve descripción del registro
# asociado en la tabla externa.
# Si existe la función [columna]_description o [columna]_describe,
# devuelve eso.
# Si existe la constante columna.pluralize.upcase y es un hash,
# intenta con eso.
# Si no, devuelve el valor del dato.
#
def self.best_describe_column_discover(column)
# Chequeo por un belongs to ...
reflection_name = column_belongs_to_discover(column)
if reflection_name
return self.best_describe_column column, :reflection, reflection_name
end
# Existe "#{column}_description"
if self.instance_methods.include? "#{column}_description"
return self.best_describe_column column, :description_method
end
# Existe "#{column}_describe"
if self.instance_methods.include? "#{column}_describe"
return self.best_describe_column column, :describe_method
end
# Existe constante?
if self.constants.include? column.to_s.pluralize.upcase
return self.best_describe_column column, :constant, column.to_s.pluralize.upcase
end
self.best_describe_column column, :self
end
# Devuelve la definición de cómo describir
def self.best_describe_column_def(column);
@best_describe_columns = {} unless @best_describe_columns
desc = @best_describe_columns[column.to_sym]
return desc if desc
best_describe_column_discover(column.to_sym)
end
# Devuelve la forma de describir a la columna
def best_describe_column(column)
d = self.class.best_describe_column_def column
raise "No puedo describir a #{column}" if d.nil?
case d[:way]
when :self
self.send column
when :reflection
r = self.send(d[:param])
r.best_describe if r
when :constant
eval "self.class::#{d[:param]}[\"#{self.send column}\"]"
when :description_method
self.send( column.to_s + "_description" )
when :describe_method
self.send( column.to_s + "_describe" )
when :proc
d[:proc].call self
end
end
# Devuelve los elementos para una selección de la columna.
def best_describe_column_selection(column)
d = self.class.best_describe_column_def column
raise "No puedo describir a #{column}" if d.nil?
case d[:way]
when :self, :proc
[]
when :reflection
eval(d[:param].camelize).find(:all).collect{ |rec|
[rec.best_describe, rec.id]
}
when :constant
eval( "self.class::#{d[:param]}" ).collect{ |k,v| [v,k] }
when :description_method, :describe_method
if self.constants.include? column.to_s.pluralize.upcase
eval( "self.class::#{d[:param]}" ).collect{ |k,v| [v,k] }
else
[]
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment