class InterMine::Metadata::ClassDescriptor

A class representing a table in the InterMine data model

A class descriptor represents a logical abstraction of a table in the InterMine model, and contains information about the columns in the table and the other tables that are referenced by this table.

It can be used to construct queries directly, when obtained from a webservice.

cld = service.model.table('Gene')
cld.where(:symbol => 'zen').each_row {|row| puts row}
author

Alex Kalderimis dev@intermine.org

homepage

www.intermine.org

Licence

Copyright (C) 2002-2011 FlyMine

This code may be freely distributed and modified under the terms of the GNU Lesser General Public Licence. This should be distributed with the code. See the LICENSE file for more information or www.gnu.org/copyleft/lesser.html.

Attributes

fields[R]

The Hash containing the fields of this model

model[R]

Public Class Methods

new(opts, model) click to toggle source

ClassDescriptors are constructed automatically when the model itself is parsed. They should not be constructed on their own.

Arguments:

opts

A Hash containing the information to initialise this ClassDescriptor.

model

The model this ClassDescriptor belongs to.

    # File lib/intermine/model.rb
353 def initialize(opts, model)
354     @model = model
355     @fields = {}
356     @klass = nil
357     @module = nil
358 
359     field_types = {
360         "attributes" => AttributeDescriptor,
361         "references" => ReferenceDescriptor,
362         "collections" => CollectionDescriptor
363     }
364 
365     opts.each do |k,v|
366         if (field_types.has_key?(k))
367             v.each do |name, field| 
368                 @fields[name] = field_types[k].new(field, model)
369             end
370         else
371             set_key_value(k, v)
372         end
373     end
374 end

Public Instance Methods

attributes → Array[AttributeDescriptor] click to toggle source

Returns an Array of all fields in the current table that represent attributes (ie. columns that can hold values, rather than references to other tables.)

The array returned will be sorted in alphabetical order by field-name.

    # File lib/intermine/model.rb
456 def attributes
457     return @fields.
458         select {|_, v| v.is_a?(AttributeDescriptor)}.
459         sort   {|(k0, _), (k1, _)| k0 <=> k1}.
460         map    {|(_, v)| v}
461 end
Alias for: get_field

Returns the field of the given name if it exists in the referenced table.

    # File lib/intermine/model.rb
432 def get_field(name)
433     return @fields[name]
434 end
Also aliased as: field
has_field?(name) → bool click to toggle source

Returns true if the table has a field of the given name.

    # File lib/intermine/model.rb
443 def has_field?(name)
444     return @fields.has_key?(name)
445 end
inspect() click to toggle source

Return a fuller string representation.

    # File lib/intermine/model.rb
469 def inspect 
470     return "<#{self.class.name}:#{self.object_id} #{to_s}>"
471 end

Construct a new query for the service this ClassDescriptor belongs to rooted on this table.

query = model.table('Gene').new_query
    # File lib/intermine/model.rb
384 def new_query
385     q = @model.service.new_query(self.name)
386     return q
387 end
Also aliased as: query
Alias for: new_query
select(*columns) → PathQuery::Query click to toggle source

Construct a new query on this table in the originating service with given columns selected for output.

query = model.table('Gene').select(:symbol, :name, "organism.name", "alleles.*")

query.each_result do |gene|
    puts "#{gene.symbol} (#{gene.organism.name}): #{gene.alleles.size} Alleles"
end
    # File lib/intermine/model.rb
403 def select(*cols)
404     q = new_query
405     q.add_views(cols)
406     return q
407 end
subclass_of?(other) → bool click to toggle source

Returns true if the class this ClassDescriptor describes is a subclass of the class the other element evaluates to. The other may be a ClassDescriptor, or a Path, or a String describing a path.

model.table('Gene').subclass_of?(model.table('SequenceFeature'))
true.

model.table('Gene').subclass_of?(model.table('Protein'))
false.
    # File lib/intermine/model.rb
486 def subclass_of?(other)
487     path = Path.new(other, @model)
488     if @extends.include? path.end_type
489         return true
490     else
491         @extends.each do |x|
492             superCls = @model.get_cd(x)
493             if superCls.subclass_of?(path)
494                 return true
495             end
496         end
497     end
498     return false
499 end
to_class → Class click to toggle source

Returns a Class that can be used to instantiate new objects representing rows of data in the InterMine database.

    # File lib/intermine/model.rb
637 def to_class
638     if @klass.nil?
639         mod = to_module
640         kls = Class.new(InterMineObject)
641         cd = self
642         kls.class_eval do
643             include mod
644             @__cd__ = cd
645         end
646         @klass = kls
647     end
648     return @klass
649 end
to_module → Module click to toggle source

Produces a module containing the logic this ClassDescriptor represents, suitable for including into a class definition.

The use of modules enables multiple inheritance, which is supported in the InterMine data model, to be represented in the classes instantiated in the client.

    # File lib/intermine/model.rb
511 def to_module
512     if @module.nil?
513         nums = Model::FLOAT_TYPES
514         ints = Model::INT_TYPES
515         bools = Model::BOOL_TYPES
516 
517         supers = @extends.map { |x| @model.get_cd(x).to_module }
518 
519         klass = Module.new
520         fd_names = @fields.values.map { |x| x.name }
521         attr_names = @fields.values.select { |x| x.is_a?(AttributeDescriptor)}.map {|x| x.name}
522         klass.class_eval do
523             include *supers
524             attr_reader *attr_names
525         end
526 
527         @fields.values.each do |fd|
528             if fd.is_a?(CollectionDescriptor)
529                 klass.class_eval do
530                     define_method("add" + fd.name.capitalize) do |*vals|
531                         type = fd.referencedType
532                         instance_var = instance_variable_get("@" + fd.name)
533                         instance_var ||= []
534                         vals.each do |item|
535                             if item.is_a?(Hash)
536                                 item = type.model.make_new(type.name, item)
537                             end
538                             if !item.is_a?(type)
539                                 raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
540                             end
541                             instance_var << item
542                         end
543                         instance_variable_set("@" + fd.name, instance_var)
544                     end
545                 end
546             end
547             
548             if fd.is_a?(ReferenceDescriptor)
549                 klass.class_eval do 
550                     define_method(fd.name) do 
551                         instance_var = instance_variable_get("@" + fd.name)
552                         if fd.referencedType.model.is_lazy and instance_var.nil? and not instance_variable_get("@" + fd.name + "_ISNULL")
553                             q = __cd__.select(:id, fd.name + ".*").where(:id => objectId).outerjoin(fd.name)
554                             first_result = q.results.first
555                             unless first_result.nil?
556                                 instance_var = first_result[fd.name]
557                                 if instance_var.nil?
558                                     if fs.is_a?(CollectionDescriptor) and instance_var.nil?
559                                         instance_var = []
560                                     else
561                                         instance_variable_set("@" + fd.name + "_ISNULL", true)
562                                     end
563                                 end
564                                 instance_variable_set("@" + fd.name, instance_var)
565                             end
566                         end
567                         if instance_var.nil? and fd.is_a?(CollectionDescriptor)
568                             return []
569                         else
570                             return instance_var
571                         end
572                     end
573                 end
574             end
575 
576             klass.class_eval do
577                 define_method(fd.name + "=") do |val|
578                     if fd.is_a?(AttributeDescriptor)
579                         type = fd.dataType
580                         if nums.include?(type)
581                             if !val.is_a?(Numeric)
582                                 raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be numeric"
583                             end
584                         elsif ints.include?(type)
585                             if !val.is_a?(Integer)
586                                 raise ArgumentError,  "Arguments to #{fd.name} in #{@name} must be integers"
587                             end
588                         elsif bools.include?(type)
589                             if !val.is_a?(TrueClass) && !val.is_a?(FalseClass)
590                                 raise ArgumentError,   "Arguments to #{fd.name} in #{@name} must be booleans"
591                             end
592                         end
593                         instance_variable_set("@" + fd.name, val)
594                     else
595                         type = fd.referencedType
596                         if fd.is_a?(CollectionDescriptor)
597                             instance_var = []
598                             unless val.nil?
599                                 val.each do |item|
600                                     if item.is_a?(Hash)
601                                         item = type.model.make_new(type.name, item)
602                                     end
603                                     if !item.is_a?(type)
604                                         raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
605                                     end
606                                     instance_var << item
607                                 end
608                             end
609                             instance_variable_set("@" + fd.name, instance_var)
610                         else
611                             if val.nil?
612                                 instance_variable_set("@" + fd.name + "_ISNULL", true)
613                             elsif val.is_a?(Hash)
614                                 val = type.model.make_new(type.name, val)
615                             end
616                             if !val.is_a?(type)
617                                 raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
618                             end
619                             instance_variable_set("@" + fd.name, val)
620                         end
621                     end
622                 end
623 
624             end
625         end
626         @module = klass
627     end
628     return @module
629 end
to_s() click to toggle source

Returns a human readable string

    # File lib/intermine/model.rb
464 def to_s
465     return "#{@model.name}.#{@name}"
466 end
where(*constraints) → PathQuery::Query click to toggle source

Returns a new query on this table in the originating service will all attribute columns selected for output and the given constraints applied.

zen = model.table('Gene').where(:symbol => 'zen').one
puts "Zen is short for #{zen.name}, and has a length of #{zen.length}"
    # File lib/intermine/model.rb
419 def where(*args)
420     q = new_query
421     q.select("*")
422     q.where(*args)
423     return q
424 end