Forum OpenACS Q&A: Re: Extending ::xo::db::user class
Posted by
Malte Sussdorff
on 10/15/08 08:19 AM
To give a taster of what I mean, here is the change to the object class to fetch the data from the tables:
##################################
#
# Retrieve an IM Dynfield Object
#
##################################
::im::dynfield::Class ad_proc get_instance_from_db {
-id:required
} {
Create an XOTcl object from an acs_object_id. This method detemines the type and initializes the object
from the information stored in the database. The object is automatically destroyed on cleanup.
It differs from ::xo::db::Class in the way that it can deref the values
} {
ns_log Notice "Getting instance for ID : $id"
set type [::xo::db::Class get_object_type -id $id]
if {$type eq "user"} {
set type "person"
}
set class [my object_type_to_class "$type"]
if {![my isclass $class]} {
error "no class $class defined"
}
set r [$class create ::$id]
$r db_1row dbq..get_instance [$class fetch_query $id]
# Now set the multivalues
foreach attribute_name [$class set multival_attrs] {
set slot "${class}::slot::${attribute_name}"
switch [$slot table_name] {
im_dynfield_cat_multi_value {
$r set $attribute_name [db_list ids "select category_id from im_dynfield_cat_multi_value where object_id = :id and attrib
ute_id = [$slot dynfield_attribute_id]"]
$r set ${attribute_name}_deref [db_list values "select im_category_from_id(category_id) from im_dynfield_cat_multi_value
where object_id = :id and attribute_id = [$slot dynfield_attribute_id]"]
}
im_dynfield_attr_multi_value {
$r set $attribute_name [db_list values "select value from im_dynfield_attr_multi_value where object_id = :id and attribut
e_id = [$slot dynfield_attribute_id]"]
$r set ${attribute_name}_deref [$r $attribute_name]
}
}
}
$r set object_type $type
$r set object_types [::im::dynfield::Class object_supertypes -object_type person]
$r set object_id $id
$r destroy_on_cleanup
$r initialize_loaded_object
return $r
}
::im::dynfield::Class ad_instproc fetch_query {id} {
Returns the full SQL statement to get all non multivalue values for an object_id.
The object should be of a dynfield enable object though
} {
set tables [list]
set extra_tables [list]
set attributes [list]
set id_column [my id_column]
set left_joins ""
set join_expressions [list "[my table_name].$id_column = $id"]
set ref_column "[my table_name].${id_column}"
foreach cl [concat [self] [my info heritage]] {
if {$cl eq "::xotcl::Object"} break
set tn [$cl table_name]
if {$tn ne "" && [lsearch $tables $tn] < 0} {
lappend tables $tn
#my log "--db_slots of $cl = [$cl array get db_slot]"
foreach {slot_name slot} [$cl array get db_slot] {
# avoid duplicate output names
set name [$slot name]
if {[lsearch [im_dynfield_multimap_tables] [$slot table_name]] <0 && ![info exists names($name)]} {
lappend attributes [$slot attribute_reference $tn]
}
set names($name) 1
set names($name) 1
}
if {$cl ne [self]} {
lappend join_expressions "$tn.[$cl id_column] = $ref_column"
}
# Deal with the extra tables
db_foreach table "select table_name, id_column from acs_object_type_tables where object_type = '[$cl object_type]' and ta
ble_name not in ([template::util::tcl_to_sql_list $tables])" {
lappend extra_tables [list $table_name $id_column]
}
}
}
foreach extra_table $extra_tables {
set table_name [lindex $extra_table 0]
set id_column [lindex $extra_table 1]
if {[lsearch $tables $table_name] <0 } {
# Extra table, join_expression needed
lappend left_joins "left outer join $table_name on (acs_objects.object_id = ${table_name}.${id_column})"
}
}
return "SELECT [join $attributes ,]\nFROM [join $tables ,] [join $left_joins " "] \nWHERE [join $join_expressions { and }] limit 1"
}