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
- 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
The Hash containing the fields of this model
Public Class Methods
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
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
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
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
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
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
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
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
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
Returns a human readable string
# File lib/intermine/model.rb 464 def to_s 465 return "#{@model.name}.#{@name}" 466 end
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