327: def connect(other_reference, own_attr, other_attr)
328: unless other_reference.kind_of? FlexiRecord::Reference
329: raise TypeError, "Object of class FlexiRecord::Reference expected."
330: end
331: reference1 = self
332: reference2 = other_reference
333: attr1 = own_attr.to_s
334: attr2 = other_attr.to_s
335: unless self.source_class == other_reference.source_class
336: "Combining references having different source classes is not possible."
337: end
338: relationship_class = self.source_class
339: [
340: [reference1, reference2, attr1, attr2],
341: [reference2, reference1, attr2, attr1]
342: ].each do |source_reference, destination_reference, source_attr, destination_attr|
343: source_class = source_reference.destination_class
344: destination_class = destination_reference.destination_class
345: tmp1 = []
346: destination_reference.source_columns.each_index do |column_index|
347: tmp1 << [
348: destination_reference.source_columns[column_index],
349: destination_reference.destination_columns[column_index]
350: ]
351: end
352: source_class.set_loader source_attr do |source_records, arguments|
353: sql_arguments = arguments.dup
354: sql_snippet = sql_arguments.shift
355: unless sql_snippet.nil?
356: unless sql_snippet.respond_to? :to_str
357: raise "First argument of reader method is not a SQL snippet string."
358: end
359: sql_snippet = sql_snippet.to_str
360: end
361: destination_records = unless source_records.empty?
362: destination_class.sql(
363: 'SELECT ' << FlexiRecord::DefaultTableAlias << '.* FROM (' <<
364: 'SELECT "obj".*, ' << relationship_class.columns.collect { |column| '"rel"."' << column << '" AS "_flexirecord_rel_' << column << '"' }.join(', ') << ' FROM ' << relationship_class.table << ' "rel" JOIN ' << destination_class.table << ' "obj" ON ' << tmp1.collect { |tmp1a, tmp1b| '"rel"."' << tmp1a << '" = "obj"."' << tmp1b << '"' }.join(' AND ') << ' WHERE (' << source_reference.source_columns.collect { |column| '"rel"."' << column << '"' }.join(', ') << ') IN (' << source_records.collect { |record| '(' << source_reference.source_columns.collect { '$' }.join(', ') << ')' }.join(', ') << ')' <<
365: ') AS ' << FlexiRecord::DefaultTableAlias << ' JOIN ' << relationship_class.table << ' ' << FlexiRecord::RelationshipTableAlias << ' ON ' << relationship_class.primary_columns.collect { |column| '' << FlexiRecord::RelationshipTableAlias << '."' << column << '" = ' << FlexiRecord::DefaultTableAlias << '."_flexirecord_rel_' << column << '"' }.join(' AND ') << ' ' << sql_snippet.to_s,
366: *(source_records.collect { |record| source_class.primary_columns.collect { |column| record.read(column) } } + sql_arguments)
367: )
368: else
369: FlexiRecord::RecordArray.new(destination_class)
370: end
371: destination_record_hash = {}
372: destination_records.each do |destination_record|
373: (destination_record_hash[
374: source_reference.source_columns.collect { |column|
375: destination_record['_flexirecord_rel_' << column]
376: }
377: ] ||= FlexiRecord::RecordArray.new(destination_class)) << destination_record
378: relationship_hash = { destination_reference.src_to_dst_attr => destination_record }
379: relationship_class.columns.each do |column|
380: relationship_hash[column] =
381: destination_record.delete_from_cache("_flexirecord_rel_#{column}")
382: end
383: destination_record[FlexiRecord::RelationshipColumn] = relationship_class.new(relationship_hash)
384: end
385: source_records.each do |source_record|
386: source_record[source_attr, *arguments] = ((destination_record_hash[source_reference.destination_columns.collect { |column| source_record[column] } ]) || FlexiRecord::RecordArray.new(destination_class)).freeze
387: end
388: next destination_records
389: end
390: end
391: end