intermine 0.99.03 → 1.00.00
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +39 -25
- data/lib/intermine/lists.rb +56 -20
- data/lib/intermine/model.rb +15 -102
- data/lib/intermine/query.rb +29 -58
- data/lib/intermine/results.rb +12 -27
- data/lib/intermine/service.rb +1 -0
- data/lib/intermine/version.rb +4 -6
- data/test/live_results.rb +164 -0
- data/test/live_summary_test.rb +59 -0
- data/test/live_test.rb +15 -20
- data/test/test_query.rb +22 -6
- data/test/test_result_row.rb +0 -30
- data/test/test_sugar.rb +14 -13
- metadata +8 -7
- data/TODO +0 -3
data/Rakefile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rubygems/specification' unless defined?(Gem::Specification)
|
3
|
+
require 'rubygems/package_task'
|
3
4
|
require 'rake/testtask'
|
4
|
-
require 'rake/gempackagetask'
|
5
5
|
|
6
|
-
gem 'rdoc', '=2.1.0'
|
7
|
-
require 'rdoc/rdoc'
|
8
|
-
require 'rake/rdoctask'
|
9
|
-
|
10
|
-
gem 'darkfish-rdoc'
|
11
|
-
require 'darkfish-rdoc'
|
6
|
+
#gem 'rdoc'# , '=2.1.0'
|
7
|
+
#require 'rdoc/rdoc'
|
8
|
+
#require 'rake/rdoctask'
|
9
|
+
#
|
10
|
+
#gem 'darkfish-rdoc'
|
11
|
+
#require 'darkfish-rdoc'
|
12
12
|
|
13
13
|
def gemspec
|
14
14
|
@gemspec ||= begin
|
@@ -38,30 +38,44 @@ task :release => :package do
|
|
38
38
|
sh "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
Gem::PackageTask.new(gemspec) do |pkg|
|
42
42
|
pkg.need_zip = true
|
43
43
|
pkg.need_tar = true
|
44
|
-
|
45
44
|
end
|
46
45
|
|
47
|
-
Rake::TestTask.new do |t|
|
48
|
-
t.libs << "test"
|
49
|
-
t.test_files = FileList['test/unit_tests.rb']
|
50
|
-
t.verbose = true
|
51
|
-
end
|
52
46
|
|
53
|
-
Rake::TestTask.new(:live_tests) do |t|
|
54
|
-
t.libs << "test"
|
55
|
-
t.test_files = FileList['test/live_test.rb'] << FileList['test/live_summary_test.rb'] << FileList['test/live_results.rb']
|
56
|
-
t.verbose = true
|
57
|
-
end
|
58
47
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
48
|
+
namespace :test do
|
49
|
+
|
50
|
+
desc "Run the unit-tests"
|
51
|
+
Rake::TestTask.new(:unit) do |t|
|
52
|
+
t.libs << "test"
|
53
|
+
t.test_files = FileList['test/unit_tests.rb']
|
54
|
+
t.verbose = true
|
55
|
+
puts "Running UNIT TESTS"
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "Run the live integration tests"
|
59
|
+
Rake::TestTask.new(:live) do |t|
|
60
|
+
t.libs << "test"
|
61
|
+
t.test_files = FileList['test/live_test.rb'] << FileList['test/live_summary_test.rb'] << FileList['test/live_results.rb']
|
62
|
+
t.verbose = false
|
63
|
+
puts "Running LIVE INTEGRATION TESTS"
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Run all tests"
|
67
|
+
task :all => [:unit, :live]
|
65
68
|
end
|
66
69
|
|
70
|
+
desc "Run the default test-suite"
|
71
|
+
task :test => ["test:all"]
|
72
|
+
|
73
|
+
#Rake::RDocTask.new do |t|
|
74
|
+
# t.title = 'InterMine Webservice Client Documentation'
|
75
|
+
# t.rdoc_files.include 'README.rdoc'
|
76
|
+
# t.rdoc_files.include 'lib/**/*rb'
|
77
|
+
# t.main = 'README.rdoc'
|
78
|
+
# t.options += ['-SHN', '-f', 'darkfish']
|
79
|
+
#end
|
80
|
+
|
67
81
|
|
data/lib/intermine/lists.rb
CHANGED
@@ -312,6 +312,54 @@ module InterMine::Lists
|
|
312
312
|
@tags = @manager.tags_for(self)
|
313
313
|
end
|
314
314
|
|
315
|
+
ENRICHMENT_DEFAULTS = {:correction => "Holm-Bonferroni", :maxp => 0.05}
|
316
|
+
|
317
|
+
# Retrieve the results of an enrichment calculation
|
318
|
+
#
|
319
|
+
# Get the results of an enrichment calculate_enrichment with the default parameter values:
|
320
|
+
#
|
321
|
+
# calculate_enrichment(widget)
|
322
|
+
#
|
323
|
+
# Pass optional parameters to the enrichment service:
|
324
|
+
#
|
325
|
+
# calculate_enrichment(widget, :correction => "Benjamini-Hochberg", :maxp => 0.1)
|
326
|
+
#
|
327
|
+
# The optional parameters are: :correction, :maxp, :filter
|
328
|
+
#
|
329
|
+
# Each result returned by the enrichment service is a hash with the following
|
330
|
+
# keys: "p-value", "identifier", "matches", "description". The Hash returned also allows
|
331
|
+
# key access with symbols.
|
332
|
+
#
|
333
|
+
def calculate_enrichment(widget, opts = {})
|
334
|
+
s = @manager.service
|
335
|
+
params = s.params.merge(ENRICHMENT_DEFAULTS).merge(opts).merge(:widget => widget, :list => @name)
|
336
|
+
uri = URI.parse(s.root + Service::LIST_ENRICHMENT_PATH)
|
337
|
+
res = Net::HTTP.post_form(uri, params)
|
338
|
+
return case res
|
339
|
+
when Net::HTTPSuccess
|
340
|
+
JSON.parse(res.body)["results"].map {|row| SymbolAcceptingHash[row] }
|
341
|
+
else
|
342
|
+
begin
|
343
|
+
container = JSON.parse(res.body)
|
344
|
+
raise ServiceError, container["error"]
|
345
|
+
rescue
|
346
|
+
res.error!
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
class SymbolAcceptingHash < Hash
|
352
|
+
|
353
|
+
def [](key)
|
354
|
+
return case key
|
355
|
+
when Symbol
|
356
|
+
return super(key.to_s.gsub(/[_]/, '-'))
|
357
|
+
else
|
358
|
+
return super(key)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
315
363
|
private
|
316
364
|
|
317
365
|
# Used to interpret arguments to add and remove
|
@@ -675,10 +723,13 @@ module InterMine::Lists
|
|
675
723
|
def make_list_names(objs)
|
676
724
|
current_names = list_names
|
677
725
|
return objs.map do |x|
|
678
|
-
case
|
679
|
-
when
|
680
|
-
|
681
|
-
when
|
726
|
+
case x
|
727
|
+
when List
|
728
|
+
x.name
|
729
|
+
when x.respond_to?(:list_upload_uri)
|
730
|
+
create_list(x).name
|
731
|
+
when current_names.include?(x.to_s)
|
732
|
+
x.to_s
|
682
733
|
else
|
683
734
|
raise ArgumentError, "#{x} is not a list you can access"
|
684
735
|
end
|
@@ -708,17 +759,15 @@ module InterMine::Lists
|
|
708
759
|
else
|
709
760
|
begin
|
710
761
|
container = JSON.parse(response.body)
|
711
|
-
|
762
|
+
raise ServiceError, container["error"]
|
712
763
|
rescue
|
713
764
|
response.error!
|
714
765
|
end
|
715
|
-
raise ServiceError, container["error"]
|
716
766
|
end
|
717
767
|
end
|
718
768
|
|
719
769
|
# Routine for creating a list from a PathQuery::Query
|
720
770
|
def create_list_from_query(query, tags=[], name=nil, description=nil)
|
721
|
-
query = get_listable_query(query)
|
722
771
|
uri = query.list_upload_uri
|
723
772
|
list_params = {
|
724
773
|
"listName" => name,
|
@@ -730,19 +779,6 @@ module InterMine::Lists
|
|
730
779
|
return Net::HTTP.post_form(URI.parse(uri), params)
|
731
780
|
end
|
732
781
|
|
733
|
-
def get_listable_query(query)
|
734
|
-
clone = query.clone()
|
735
|
-
views = clone.views
|
736
|
-
selected_classes = views.map {|x| x.prefix}.uniq {|p| p.to_s}
|
737
|
-
if selected_classes.size == 1
|
738
|
-
return clone.select(selected_classes.first.append("id"))
|
739
|
-
elsif selected_classes.size == 0
|
740
|
-
return clone.select("#{clone.root.name}.id")
|
741
|
-
end
|
742
|
-
# Bound to fail, but let the service provide the message.
|
743
|
-
return clone
|
744
|
-
end
|
745
|
-
|
746
782
|
# Routine for creating a List in a webservice from a list of Ids.
|
747
783
|
def create_list_from_ids(ids, type, tags=[], name=nil, description=nil)
|
748
784
|
if @service.model.get_cd(type).nil?
|
data/lib/intermine/model.rb
CHANGED
@@ -402,46 +402,6 @@ module Metadata
|
|
402
402
|
return q
|
403
403
|
end
|
404
404
|
|
405
|
-
# call-seq:
|
406
|
-
# find(*attributes) => Enumerable[InterMineObject]
|
407
|
-
#
|
408
|
-
# Get the items in the database matching the identifiers.
|
409
|
-
#
|
410
|
-
# zen = model.table("Gene").find("zen")
|
411
|
-
# puts zen.length, zen.organism.name
|
412
|
-
#
|
413
|
-
# find may retrun multiple results:
|
414
|
-
#
|
415
|
-
# genes = model.table("Gene").find("zen", "eve", "r", "h")
|
416
|
-
#
|
417
|
-
# The search mechanism used is a "lookup" constraint, so extra-values
|
418
|
-
# may be provided to distinguish search terms by passing key-value pairs:
|
419
|
-
#
|
420
|
-
# starting_with_c = model.table("Gene").find("c*" => "D. melanogaster")
|
421
|
-
#
|
422
|
-
def find(*attrs)
|
423
|
-
q = new_query
|
424
|
-
q.select("*")
|
425
|
-
attrs.each do |attr|
|
426
|
-
if attr.is_a? Hash
|
427
|
-
attr.each do |term, extra|
|
428
|
-
q.or(@root, "LOOKUP", term, extra)
|
429
|
-
end
|
430
|
-
else
|
431
|
-
q.or(@root, "LOOKUP", attr)
|
432
|
-
end
|
433
|
-
end
|
434
|
-
|
435
|
-
c = q.count()
|
436
|
-
if c < 1
|
437
|
-
raise ItemNotFoundError
|
438
|
-
elsif c == 1
|
439
|
-
return q.results.first
|
440
|
-
else
|
441
|
-
return q.results
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
405
|
# call-seq:
|
446
406
|
# where(*constraints) => PathQuery::Query
|
447
407
|
#
|
@@ -487,8 +447,13 @@ module Metadata
|
|
487
447
|
# attributes (ie. columns that can hold values, rather than references to
|
488
448
|
# other tables.)
|
489
449
|
#
|
450
|
+
# The array returned will be sorted in alphabetical order by field-name.
|
451
|
+
#
|
490
452
|
def attributes
|
491
|
-
return @fields.
|
453
|
+
return @fields.
|
454
|
+
select {|_, v| v.is_a?(AttributeDescriptor)}.
|
455
|
+
sort {|(k0, _), (k1, _)| k0 <=> k1}.
|
456
|
+
map {|(_, v)| v}
|
492
457
|
end
|
493
458
|
|
494
459
|
# Returns a human readable string
|
@@ -580,11 +545,8 @@ module Metadata
|
|
580
545
|
klass.class_eval do
|
581
546
|
define_method(fd.name) do
|
582
547
|
if instance_variable_get("@" + fd.name).nil?
|
583
|
-
q = __cd__.select(
|
584
|
-
instance_var = q.results.first
|
585
|
-
if fd.is_a?(CollectionDescriptor) and instance_var.nil?
|
586
|
-
instance_var = []
|
587
|
-
end
|
548
|
+
q = __cd__.select(fd.name + ".*").where(:id => objectId)
|
549
|
+
instance_var = q.results.first[fd.name]
|
588
550
|
instance_variable_set("@" + fd.name, instance_var)
|
589
551
|
end
|
590
552
|
return instance_variable_get("@" + fd.name)
|
@@ -614,16 +576,14 @@ module Metadata
|
|
614
576
|
type = fd.referencedType
|
615
577
|
if fd.is_a?(CollectionDescriptor)
|
616
578
|
instance_var = []
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
item = type.model.make_new(type.name, item)
|
621
|
-
end
|
622
|
-
if !item.is_a?(type)
|
623
|
-
raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
|
624
|
-
end
|
625
|
-
instance_var << item
|
579
|
+
val.each do |item|
|
580
|
+
if item.is_a?(Hash)
|
581
|
+
item = type.model.make_new(type.name, item)
|
626
582
|
end
|
583
|
+
if !item.is_a?(type)
|
584
|
+
raise ArgumentError, "Arguments to #{fd.name} in #{@name} must be #{type.name}s"
|
585
|
+
end
|
586
|
+
instance_var << item
|
627
587
|
end
|
628
588
|
instance_variable_set("@" + fd.name, instance_var)
|
629
589
|
else
|
@@ -794,55 +754,11 @@ module Metadata
|
|
794
754
|
end
|
795
755
|
end
|
796
756
|
|
797
|
-
# call-seq:
|
798
|
-
# end => ClassDescriptor | ReferenceDescriptor | AttributeDescriptor
|
799
|
-
#
|
800
|
-
# Return the last element of this path
|
801
|
-
#
|
802
|
-
def end
|
803
|
-
return @elements.last
|
804
|
-
end
|
805
|
-
|
806
|
-
# call-seq:
|
807
|
-
# prefix => Path
|
808
|
-
#
|
809
|
-
# Return the Path one above this.
|
810
|
-
def prefix
|
811
|
-
if @elements.size == 1
|
812
|
-
raise PathException, "Root paths do not have a prefix"
|
813
|
-
end
|
814
|
-
new_str = @elements[0, @elements.size - 1].map {|x| x.name}.join(".")
|
815
|
-
return Path.new(new_str, @model, @subclasses)
|
816
|
-
end
|
817
|
-
|
818
|
-
# call-seq:
|
819
|
-
# append(part, ...) => Path
|
820
|
-
#
|
821
|
-
# Return a new path by adding elements to this path.
|
822
|
-
#
|
823
|
-
def append(*parts)
|
824
|
-
new_str = self.to_s + "." + parts.join(".")
|
825
|
-
return Path.new(new_str, @model, @subclasses)
|
826
|
-
end
|
827
|
-
|
828
757
|
# Two paths can be said to be equal when they stringify to the same representation.
|
829
758
|
def ==(other)
|
830
759
|
return self.to_s == other.to_s
|
831
760
|
end
|
832
761
|
|
833
|
-
# Two paths are identical when they have the same everything.
|
834
|
-
def eql?(other)
|
835
|
-
begin
|
836
|
-
return (self == other) && @model.eql?(other.model) && @subclasses.eql?(other.subclasses)
|
837
|
-
rescue
|
838
|
-
return false
|
839
|
-
end
|
840
|
-
end
|
841
|
-
|
842
|
-
def hash
|
843
|
-
return 17 * @model.hash * 11 * @subclasses.hash * 3 * to_s.hash
|
844
|
-
end
|
845
|
-
|
846
762
|
# Get the number of elements in the path
|
847
763
|
def length
|
848
764
|
return @elements.length
|
@@ -969,9 +885,6 @@ module Metadata
|
|
969
885
|
end
|
970
886
|
end
|
971
887
|
end
|
972
|
-
|
973
|
-
class ItemNotFoundError < RuntimeError
|
974
|
-
end
|
975
888
|
end
|
976
889
|
end
|
977
890
|
|
data/lib/intermine/query.rb
CHANGED
@@ -616,10 +616,7 @@ module InterMine::PathQuery
|
|
616
616
|
if y.end_with?("*")
|
617
617
|
prefix = y.chomp(".*")
|
618
618
|
path = make_path(prefix)
|
619
|
-
|
620
|
-
prefix + "." + x.name
|
621
|
-
}
|
622
|
-
add_views(attrs)
|
619
|
+
add_views(path.end_cd.attributes.map {|x| prefix + "." + x.name})
|
623
620
|
else
|
624
621
|
path = make_path(y)
|
625
622
|
path = make_path(y.to_s + ".id") unless path.is_attribute?
|
@@ -723,11 +720,8 @@ module InterMine::PathQuery
|
|
723
720
|
#
|
724
721
|
def add_sort_order(path, direction="ASC")
|
725
722
|
p = self.path(path)
|
726
|
-
|
727
|
-
|
728
|
-
selected.uniq!
|
729
|
-
if !selected.include? p.prefix
|
730
|
-
raise ArgumentError, "Sort order (#{p}) not on a selected class (#{selected.map {|v| v.to_s}.inspect} in #{self.name || 'unnamed query'})"
|
723
|
+
if !@views.include? p
|
724
|
+
raise ArgumentError, "Sort order (#{p}) not in view (#{@views.map {|v| v.to_s}.inspect} in #{self.name || 'unnamed query'})"
|
731
725
|
end
|
732
726
|
@sort_order << SortOrder.new(p, direction)
|
733
727
|
return self
|
@@ -765,32 +759,6 @@ module InterMine::PathQuery
|
|
765
759
|
@constraints << con
|
766
760
|
return con
|
767
761
|
end
|
768
|
-
|
769
|
-
def or(*parameters)
|
770
|
-
logic = @logic
|
771
|
-
new_con = add_constraint(*parameters)
|
772
|
-
|
773
|
-
if logic
|
774
|
-
set_logic(LogicGroup.new(logic, "OR", new_con))
|
775
|
-
elsif @constraints.size > 1
|
776
|
-
set_logic(@constraints.map {|c| c.code }.join(" or "))
|
777
|
-
end
|
778
|
-
|
779
|
-
return self
|
780
|
-
end
|
781
|
-
|
782
|
-
def and(*parameters)
|
783
|
-
logic = @logic
|
784
|
-
new_con = add_constraint(*parameters)
|
785
|
-
|
786
|
-
if logic
|
787
|
-
set_logic(LogicGroup.new(logic, "AND", new_con))
|
788
|
-
elsif @constraints.size > 1
|
789
|
-
set_logic(@constraints.map {|c| c.code }.join(" and "))
|
790
|
-
end
|
791
|
-
|
792
|
-
return self
|
793
|
-
end
|
794
762
|
|
795
763
|
# Returns a Path object constructed from the given path-string,
|
796
764
|
# taking the current state of the query into account (its data-model
|
@@ -855,7 +823,7 @@ module InterMine::PathQuery
|
|
855
823
|
end
|
856
824
|
parameters[:values] = subv.to_a
|
857
825
|
elsif subv.is_a?(Lists::List)
|
858
|
-
if subk == "="
|
826
|
+
if subk == "="
|
859
827
|
parameters[:op] = "IN"
|
860
828
|
elsif subk == "!="
|
861
829
|
parameters[:op] = "NOT IN"
|
@@ -863,19 +831,6 @@ module InterMine::PathQuery
|
|
863
831
|
parameters[:op] = normalised_k
|
864
832
|
end
|
865
833
|
parameters[:value] = subv.name
|
866
|
-
elsif subv.is_a? Query
|
867
|
-
if subk == "=" or subk == "<" or subk == "<="
|
868
|
-
parameters[:op] = "IN"
|
869
|
-
elsif subk == "!="
|
870
|
-
parameters[:op] = "NOT IN"
|
871
|
-
else
|
872
|
-
parameters[:op] = normalised_k
|
873
|
-
end
|
874
|
-
s = subv.service
|
875
|
-
l = s.create_list(subv)
|
876
|
-
|
877
|
-
parameters[:value] = l.name
|
878
|
-
|
879
834
|
else
|
880
835
|
parameters[:op] = normalised_k
|
881
836
|
parameters[:value] = subv
|
@@ -988,7 +943,7 @@ module InterMine::PathQuery
|
|
988
943
|
@classes = [
|
989
944
|
SingleValueConstraint,
|
990
945
|
SubClassConstraint,
|
991
|
-
LookupConstraint, MultiValueConstraint,
|
946
|
+
LookupConstraint, MultiValueConstraint, RangeConstraint,
|
992
947
|
UnaryConstraint, LoopConstraint, ListConstraint]
|
993
948
|
|
994
949
|
@query = query
|
@@ -1014,14 +969,9 @@ module InterMine::PathQuery
|
|
1014
969
|
|
1015
970
|
attr_keys = parameters.keys
|
1016
971
|
suitable_classes = @classes.select { |cls|
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
if key.to_s == "op"
|
1021
|
-
is_suitable = is_suitable && cls.valid_ops.include?(parameters[key])
|
1022
|
-
end
|
1023
|
-
}
|
1024
|
-
is_suitable
|
972
|
+
attr_keys.reduce(true) do |suitable, k|
|
973
|
+
suitable && cls.method_defined?(k) && (k.to_s != "op" or cls.valid_ops.include?(parameters[k]))
|
974
|
+
end
|
1025
975
|
}
|
1026
976
|
if suitable_classes.size > 1
|
1027
977
|
raise ArgumentError, "More than one class found for #{parameters.inspect}"
|
@@ -1402,10 +1352,31 @@ module InterMine::PathQuery
|
|
1402
1352
|
end
|
1403
1353
|
end
|
1404
1354
|
|
1355
|
+
class RangeConstraint < MultiValueConstraint
|
1356
|
+
|
1357
|
+
VALID_OPS = [
|
1358
|
+
"WITHIN", "OUTSIDE",
|
1359
|
+
"CONTAINS", "DOES NOT CONTAIN",
|
1360
|
+
"OVERLAPS", "DOES NOT OVERLAP"
|
1361
|
+
]
|
1362
|
+
|
1363
|
+
def self.valid_ops
|
1364
|
+
return VALID_OPS
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
def validate
|
1368
|
+
# no-op
|
1369
|
+
end
|
1370
|
+
end
|
1371
|
+
|
1405
1372
|
class TemplateMultiValueConstraint < MultiValueConstraint
|
1406
1373
|
include TemplateConstraint
|
1407
1374
|
end
|
1408
1375
|
|
1376
|
+
class TemplateRangeConstraint < RangeConstraint
|
1377
|
+
include TemplateConstraint
|
1378
|
+
end
|
1379
|
+
|
1409
1380
|
class SortOrder
|
1410
1381
|
include PathFeature
|
1411
1382
|
attr_accessor :direction
|
data/lib/intermine/results.rb
CHANGED
@@ -85,12 +85,12 @@ module InterMine::Results
|
|
85
85
|
def [](arg, length=nil)
|
86
86
|
unless length.nil?
|
87
87
|
raise ArgumentError, "when providing a length, the first argument must be an Integer" unless arg.is_a? Integer
|
88
|
-
return @results[arg, length].map {|x|
|
88
|
+
return @results[arg, length].map {|x| x["value"]}
|
89
89
|
end
|
90
90
|
|
91
91
|
case arg
|
92
92
|
when Range
|
93
|
-
return @results[arg].map {|x|
|
93
|
+
return @results[arg].map {|x| x["value"]}
|
94
94
|
when Integer
|
95
95
|
idx = arg
|
96
96
|
else
|
@@ -101,19 +101,19 @@ module InterMine::Results
|
|
101
101
|
|
102
102
|
cell = @results[idx]
|
103
103
|
|
104
|
-
raise IndexError, "Argument out of range" if
|
104
|
+
raise IndexError, "Argument out of range" if cell.nil?
|
105
105
|
|
106
|
-
return
|
106
|
+
return cell["value"]
|
107
107
|
end
|
108
108
|
|
109
109
|
# Returns the first value in this row
|
110
110
|
def first
|
111
|
-
return
|
111
|
+
return @results[0]["value"]
|
112
112
|
end
|
113
113
|
|
114
114
|
# Returns the last value in this row
|
115
115
|
def last
|
116
|
-
return
|
116
|
+
return @results.last["value"]
|
117
117
|
end
|
118
118
|
|
119
119
|
# Iterate over the values in this row in the
|
@@ -134,11 +134,9 @@ module InterMine::Results
|
|
134
134
|
def each(&block)
|
135
135
|
if block
|
136
136
|
if block.arity == 1
|
137
|
-
@results.each {|x| block.call(
|
137
|
+
@results.each {|x| block.call(x["value"])}
|
138
138
|
else block.arity == 2
|
139
|
-
(0 ... @results.size).to_a.each {|i|
|
140
|
-
block.call(@columns[i], value_of(@results[i]))
|
141
|
-
}
|
139
|
+
(0 ... @results.size).to_a.each {|i| block.call(@columns[i], @results[i]["value"])}
|
142
140
|
end
|
143
141
|
end
|
144
142
|
return self
|
@@ -156,7 +154,7 @@ module InterMine::Results
|
|
156
154
|
|
157
155
|
# Return an Array version of the row.
|
158
156
|
def to_a
|
159
|
-
return @results.map {|x|
|
157
|
+
return @results.map {|x| x["value"]}
|
160
158
|
end
|
161
159
|
|
162
160
|
# Return a Hash version of the row. All keys in this
|
@@ -187,15 +185,11 @@ module InterMine::Results
|
|
187
185
|
# CSV or TSV file. The optional separator argument will be used to delimit
|
188
186
|
# columns
|
189
187
|
def to_csv(sep="\t")
|
190
|
-
return @results.map {|x|
|
188
|
+
return @results.map {|x| x["value"].inspect}.join(sep)
|
191
189
|
end
|
192
190
|
|
193
191
|
private
|
194
192
|
|
195
|
-
def value_of(cell)
|
196
|
-
return cell["value"]
|
197
|
-
end
|
198
|
-
|
199
193
|
# Return the index for a string or symbol key.
|
200
194
|
def index_for(key)
|
201
195
|
if @indexes.nil?
|
@@ -215,13 +209,6 @@ module InterMine::Results
|
|
215
209
|
end
|
216
210
|
end
|
217
211
|
|
218
|
-
class NewResultRow < ResultsRow
|
219
|
-
|
220
|
-
def value_of(cell)
|
221
|
-
return cell
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
212
|
# The class responsible for retrieving results and processing them
|
226
213
|
#
|
227
214
|
# query.each_row do |row|
|
@@ -263,13 +250,11 @@ module InterMine::Results
|
|
263
250
|
|
264
251
|
# Iterate over the result set one ResultsRow at a time
|
265
252
|
def each_row
|
266
|
-
cls = @query.service.version >= 8 ? NewResultRow : ResultsRow
|
267
|
-
format = @query.service.version >= 8 ? "json" : "jsonrows"
|
268
253
|
processor = lambda {|line|
|
269
254
|
x = line.chomp.chomp(",")
|
270
|
-
x.empty? ? nil :
|
255
|
+
x.empty? ? nil : ResultsRow.new(x, @query.views)
|
271
256
|
}
|
272
|
-
read_result_set(params(
|
257
|
+
read_result_set(params("jsonrows"), processor) {|x|
|
273
258
|
yield x
|
274
259
|
}
|
275
260
|
end
|
data/lib/intermine/service.rb
CHANGED
@@ -109,6 +109,7 @@ module InterMine
|
|
109
109
|
LIST_INTERSECTION_PATH = "/lists/intersect/json"
|
110
110
|
LIST_SUBTRACTION_PATH = "/lists/subtract/json"
|
111
111
|
LIST_TAG_PATH = "/list/tags/json"
|
112
|
+
LIST_ENRICHMENT_PATH = "/list/enrichment"
|
112
113
|
|
113
114
|
# The webservice version. An integer that
|
114
115
|
# supplies information about what features are supported.
|
data/lib/intermine/version.rb
CHANGED
@@ -3,6 +3,9 @@ module Intermine
|
|
3
3
|
# Webservice Client Version number
|
4
4
|
#
|
5
5
|
# Changes:
|
6
|
+
# 1.00.00 - Up to make use of new features of the InterMine 1.0 API
|
7
|
+
# * Enrichment queries
|
8
|
+
# * Range constraints
|
6
9
|
# 0.98.11 - * InterMineObjects now lazily fetch their references
|
7
10
|
# if nil. Note that while extremely convenient,
|
8
11
|
# explicit prefetching will be much more efficient
|
@@ -12,10 +15,5 @@ module Intermine
|
|
12
15
|
# 0.98.10 - Added status property to lists
|
13
16
|
# 0.98.09 - Major changes to results - now with thorough-going Enumerable support
|
14
17
|
# 0.98.08 - Added column summary support
|
15
|
-
|
16
|
-
# - Added support for "json" format (performance) improvement
|
17
|
-
# 0.99.01 - Added support for sort-orders on selected classes which are not in the view
|
18
|
-
# 0.99.02 - Fixed bug with null values in new result rows (resulting commonly from outer joins)
|
19
|
-
# 0.99.03 - Fixed handling of null references and empty collections in lazy reference fetching.
|
20
|
-
VERSION = "0.99.03"
|
18
|
+
VERSION = "1.00.00"
|
21
19
|
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/test_helper.rb"
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
require "intermine/service"
|
5
|
+
require "intermine/results"
|
6
|
+
|
7
|
+
class LiveResultsTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@service = Service.new("http://localhost/intermine-test")
|
11
|
+
@max = 50
|
12
|
+
@q = @service.query("Employee").select("*", "department.*").where(:age => {:lt => @max})
|
13
|
+
@empty = @service.query("Employee").where(:name => "some-non-existant-value")
|
14
|
+
@exp_count = 82
|
15
|
+
@expected_last = "Didier Legu\303\251lec"
|
16
|
+
@expected_last_summary = "Vincent"
|
17
|
+
@expected_last_obj = "Both Quotes '\""
|
18
|
+
@expected_target = 37.02439
|
19
|
+
@expected_two_vowels = 31
|
20
|
+
@exp_trideps = 5
|
21
|
+
@exp_s_deps = 29
|
22
|
+
@exp_row_size = 7
|
23
|
+
@rows_args = []
|
24
|
+
@results_args = []
|
25
|
+
@summary_args = []
|
26
|
+
@count_args = []
|
27
|
+
@dep_size = 3
|
28
|
+
end
|
29
|
+
|
30
|
+
def testRowIteration
|
31
|
+
count = 0
|
32
|
+
@q.rows(*@rows_args).each do |row|
|
33
|
+
assert_equal(@exp_row_size, row.size)
|
34
|
+
assert(row["age"].is_a? Fixnum)
|
35
|
+
assert(row["age"] < @max)
|
36
|
+
assert(row["name"].is_a? String)
|
37
|
+
count += 1
|
38
|
+
end
|
39
|
+
assert_equal(@exp_count, count)
|
40
|
+
end
|
41
|
+
|
42
|
+
def testEmptyRows
|
43
|
+
count = 0
|
44
|
+
@empty.rows.each do
|
45
|
+
count += 1
|
46
|
+
end
|
47
|
+
assert_equal(0, count)
|
48
|
+
end
|
49
|
+
|
50
|
+
def testRowMapping
|
51
|
+
names = @q.rows(*@rows_args).map {|r| r["name"]}
|
52
|
+
assert_equal(@exp_count, names.length)
|
53
|
+
assert_equal(@expected_last, names.last)
|
54
|
+
end
|
55
|
+
|
56
|
+
def testRowFolding
|
57
|
+
average = @q.rows(*@rows_args).reduce(0.0) {|m, i| m + i["age"]} / @q.count(*@count_args)
|
58
|
+
target = @expected_target
|
59
|
+
assert(average > target * 0.999999)
|
60
|
+
assert(average < target * 1.000001)
|
61
|
+
end
|
62
|
+
|
63
|
+
def testRowFiltering
|
64
|
+
two_vowels = @q.rows(*@rows_args).select {|r| r["name"].match(/[aeiou]{2}/) }
|
65
|
+
assert_equal(@expected_two_vowels, two_vowels.length)
|
66
|
+
end
|
67
|
+
|
68
|
+
def testObjectIteration
|
69
|
+
count = 0
|
70
|
+
@q.results(*@results_args).each do |emp|
|
71
|
+
assert(emp.is_a? @q.model.table("Employee"))
|
72
|
+
assert(emp.age.is_a? Fixnum)
|
73
|
+
assert(emp.age < @max)
|
74
|
+
assert(emp.name.is_a? String)
|
75
|
+
count += 1
|
76
|
+
end
|
77
|
+
assert_equal(@exp_count, count)
|
78
|
+
end
|
79
|
+
|
80
|
+
def testEmptyObjects
|
81
|
+
count = 0
|
82
|
+
@empty.results.each do
|
83
|
+
count += 1
|
84
|
+
end
|
85
|
+
assert_equal(0, count)
|
86
|
+
end
|
87
|
+
|
88
|
+
def testObjectMapping
|
89
|
+
names = @q.results(*@results_args).map {|r| r.name}
|
90
|
+
assert_equal(@exp_count, names.length)
|
91
|
+
assert_equal(@expected_last_obj, names.last)
|
92
|
+
end
|
93
|
+
|
94
|
+
def testObjectFolding
|
95
|
+
average = @q.results(*@results_args).reduce(0.0) {|m, i| m + i.age} / @q.count(*@count_args)
|
96
|
+
target = @expected_target
|
97
|
+
assert(average > target * 0.999999, "Checking lower bound on #{average}")
|
98
|
+
assert(average < target * 1.000001, "Checking upper bound on #{average}")
|
99
|
+
end
|
100
|
+
|
101
|
+
def testObjectFiltering
|
102
|
+
emps_in_s_deps = @q.results(*@results_args).select {|o| o.department.name.start_with? "S"}
|
103
|
+
assert_equal(@exp_s_deps, emps_in_s_deps.length)
|
104
|
+
end
|
105
|
+
|
106
|
+
def testSummaryIteration
|
107
|
+
count = 0
|
108
|
+
@q.summaries("name", *@summary_args).each do |summary|
|
109
|
+
assert_equal(1, summary["count"])
|
110
|
+
count += 1
|
111
|
+
end
|
112
|
+
assert_equal(@exp_count, count)
|
113
|
+
end
|
114
|
+
|
115
|
+
def testEmptySummaries
|
116
|
+
count = 0
|
117
|
+
@empty.summaries("name").each do
|
118
|
+
count += 1
|
119
|
+
end
|
120
|
+
assert_equal(0, count)
|
121
|
+
end
|
122
|
+
|
123
|
+
def testSummaryMapping
|
124
|
+
names = @q.summaries("name", *@summary_args).map {|s| s["item"]}
|
125
|
+
assert_equal(@exp_count, names.length)
|
126
|
+
assert_equal(@expected_last_summary, names.last)
|
127
|
+
end
|
128
|
+
|
129
|
+
def testSummaryFolding
|
130
|
+
sum = @q.summaries("name", *@summary_args).reduce(0) {|m, i| m + i["count"]}
|
131
|
+
assert_equal(@q.count(*@count_args), sum)
|
132
|
+
end
|
133
|
+
|
134
|
+
def testSummaryFiltering
|
135
|
+
trideps = @q.summaries("department.name", *@summary_args).select {|s| s["count"] == @dep_size}
|
136
|
+
assert_equal(@exp_trideps, trideps.length)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class LiveTemplateResultsTest < LiveResultsTest
|
141
|
+
|
142
|
+
def setup
|
143
|
+
@service = Service.new("http://localhost/intermine-test")
|
144
|
+
@q = @service.template("employeesOverACertainAgeFromDepartmentA")
|
145
|
+
@empty = @q
|
146
|
+
@exp_count = 18
|
147
|
+
@expected_last = "Tim Canterbury"
|
148
|
+
@expected_last_summary = "Tim Canterbury"
|
149
|
+
@expected_last_obj = "Fatou"
|
150
|
+
@expected_target = 47.277778
|
151
|
+
@expected_two_vowels = 4
|
152
|
+
@dep_size = 18
|
153
|
+
@exp_trideps = 1
|
154
|
+
@exp_s_deps = 18
|
155
|
+
@max = 69
|
156
|
+
@rows_args = [{"B" => "Sales"}]
|
157
|
+
@results_args = [{"B" => "Sales"}]
|
158
|
+
@summary_args = [{"B" => "Sales"}]
|
159
|
+
@count_args = [{"B" => "Sales"}]
|
160
|
+
@exp_row_size = 3
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/test_helper.rb"
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
require "intermine/service"
|
5
|
+
|
6
|
+
class LiveSummaryTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@service = Service.new("http://localhost/intermine-test")
|
10
|
+
@query = @service.query("Employee").where(:age => {:lt => 50})
|
11
|
+
end
|
12
|
+
|
13
|
+
def testIteration
|
14
|
+
@query.summaries("age").each {|summary|
|
15
|
+
assert_equal("37.0243902439024390", summary["average"])
|
16
|
+
assert(summary["max"] < 50)
|
17
|
+
}
|
18
|
+
|
19
|
+
count = 0
|
20
|
+
@query.summaries("name").each {|summary|
|
21
|
+
assert_equal(1, summary["count"])
|
22
|
+
count += 1
|
23
|
+
}
|
24
|
+
assert_equal(count, @query.count)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def testNumericSummary
|
29
|
+
summary = @query.summarise("age")
|
30
|
+
assert(summary["max"] < 50)
|
31
|
+
# Work around float comparison errors, grrr
|
32
|
+
assert(summary["average"] > 37.024)
|
33
|
+
assert(summary["average"] < 37.025)
|
34
|
+
end
|
35
|
+
|
36
|
+
def testNonNumericSummary
|
37
|
+
summary = @query.summarise("name")
|
38
|
+
assert_equal(1, summary["Tim Canterbury"])
|
39
|
+
end
|
40
|
+
|
41
|
+
def testTop
|
42
|
+
summary = @query.summaries("department.name")
|
43
|
+
top = summary.first
|
44
|
+
assert_equal("Warehouse", top["item"])
|
45
|
+
assert_equal(12, top["count"])
|
46
|
+
end
|
47
|
+
|
48
|
+
def testTemplateSummary
|
49
|
+
template = @service.template("CEO_Rivals")
|
50
|
+
template_params = {"A" => {"!=" => "Charles Miner"}}
|
51
|
+
|
52
|
+
summary = template.summarise("salary", template_params)
|
53
|
+
assert_equal(529119.4, summary["average"])
|
54
|
+
|
55
|
+
summary = template.summarise("company.name", template_params)
|
56
|
+
assert_equal(1, summary["Gogirep"])
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/test/live_test.rb
CHANGED
@@ -6,7 +6,7 @@ require "intermine/service"
|
|
6
6
|
class LiveDemoTest < Test::Unit::TestCase
|
7
7
|
|
8
8
|
def setup
|
9
|
-
@service = Service.new("localhost/intermine-test", "test-user-token")
|
9
|
+
@service = Service.new("http://localhost/intermine-test", "test-user-token")
|
10
10
|
@temp_lists = []
|
11
11
|
end
|
12
12
|
|
@@ -48,10 +48,10 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
48
48
|
def testListEnumerability
|
49
49
|
list = @service.list("My-Favourite-Employees")
|
50
50
|
names = list.map {|emp| emp.name }
|
51
|
-
exp = ["David Brent", "Neil Godwin", "Bernd Stromberg", "Timo Becker"]
|
51
|
+
exp = [ "David Brent", "Neil Godwin", "Bernd Stromberg", "Timo Becker"]
|
52
52
|
assert_equal(exp, names)
|
53
53
|
|
54
|
-
old = list.select {|emp| emp.age >
|
54
|
+
old = list.select {|emp| emp.age > 43}
|
55
55
|
assert_equal(1, old.size)
|
56
56
|
assert_equal("Neil Godwin", old.first.name)
|
57
57
|
|
@@ -63,23 +63,23 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
63
63
|
list = @service.list("My-Favourite-Employees")
|
64
64
|
|
65
65
|
deps = list.map {|emp| emp.department.name }
|
66
|
-
exp = ["Sales", "Human Resources",
|
67
|
-
"Schadensregulierung M-Z", "Schadensregulierung"]
|
66
|
+
exp = ["Sales", "Human Resources", "Schadensregulierung M-Z", "Schadensregulierung"]
|
68
67
|
assert_equal(exp, deps)
|
69
68
|
|
70
69
|
comps = list.map {|emp| emp.department.company.name }
|
71
|
-
exp = [
|
72
|
-
"Capitol Versicherung AG", "Capitol Versicherung AG"]
|
70
|
+
exp = ["Wernham-Hogg", "Wernham-Hogg", "Capitol Versicherung AG", "Capitol Versicherung AG"]
|
73
71
|
assert_equal(exp, comps)
|
74
72
|
end
|
75
73
|
|
76
74
|
def testLazyCollectionFetching
|
77
75
|
list = @service.list("My-Favourite-Employees")
|
78
76
|
emps = list.map {|manager| manager.department.employees.map {|employee| employee.age} }
|
79
|
-
exp = [
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
exp = [
|
78
|
+
[34, 36, 41, 55, 61, 61],
|
79
|
+
[44, 49, 62],
|
80
|
+
[30, 37, 45, 46, 58, 64],
|
81
|
+
[36, 37, 39, 49, 57, 59]
|
82
|
+
]
|
83
83
|
assert_equal(exp, emps)
|
84
84
|
|
85
85
|
sum = list.reduce(0) {|m, manager| m + manager.department.employees.reduce(0) {|n, emp| n + emp.age}}
|
@@ -130,15 +130,10 @@ class LiveDemoTest < Test::Unit::TestCase
|
|
130
130
|
assert_equal(tags.sort, new_list.tags.sort)
|
131
131
|
end
|
132
132
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
assert_equal(2, @service.query("Bank").where("Bank" => {:not_in => q2}).count)
|
138
|
-
|
139
|
-
l = @service.subtract([q1], [q2])
|
140
|
-
@temp_lists << l
|
141
|
-
assert_equal(2, l.size)
|
133
|
+
def testEnrichment
|
134
|
+
l = @service.list("My-Favourite-Employees")
|
135
|
+
contractors = l.calculate_enrichment :contractor_enrichment, :maxp => 1.0
|
136
|
+
assert_equal("Vikram", contractors.first[:identifier])
|
142
137
|
end
|
143
138
|
|
144
139
|
end
|
data/test/test_query.rb
CHANGED
@@ -640,6 +640,20 @@ class TestQuery < Test::Unit::TestCase
|
|
640
640
|
assert_equal(conA.values, %w{Sales Marketing Janitorial})
|
641
641
|
end
|
642
642
|
|
643
|
+
def test_range_constraints
|
644
|
+
query = InterMine::PathQuery::Query.new(@model, "Employee")
|
645
|
+
query.add_constraint({
|
646
|
+
:path => "age",
|
647
|
+
:op => "WITHIN",
|
648
|
+
:values => %w{1..10 30..35}
|
649
|
+
})
|
650
|
+
|
651
|
+
conA = query.constraints.first
|
652
|
+
assert_equal(conA.path.to_s, "Employee.age")
|
653
|
+
assert_equal(conA.op, "WITHIN")
|
654
|
+
assert_equal(conA.values, ["1..10", "30..35"])
|
655
|
+
end
|
656
|
+
|
643
657
|
def test_bad_multi_constraint
|
644
658
|
query = InterMine::PathQuery::Query.new(@model, "Employee")
|
645
659
|
assert_raise ArgumentError do
|
@@ -848,12 +862,6 @@ class TestQuery < Test::Unit::TestCase
|
|
848
862
|
|
849
863
|
assert_equal(query.sort_order.last.path, "Employee.name")
|
850
864
|
assert_equal(query.sort_order.last.direction, "DESC")
|
851
|
-
|
852
|
-
query.add_sort_order("fullTime")
|
853
|
-
|
854
|
-
assert_equal(query.sort_order.last.path, "Employee.fullTime")
|
855
|
-
assert_equal(query.sort_order.last.direction, "ASC")
|
856
|
-
|
857
865
|
end
|
858
866
|
|
859
867
|
def test_subclassed_sort_order
|
@@ -981,6 +989,11 @@ class TestQuery < Test::Unit::TestCase
|
|
981
989
|
:value => "zop",
|
982
990
|
:extra_value => "zip"
|
983
991
|
})
|
992
|
+
query.add_constraint({
|
993
|
+
:path => "age",
|
994
|
+
:op => "WITHIN",
|
995
|
+
:values => %w{1..10 30..35}
|
996
|
+
})
|
984
997
|
query.add_constraint({
|
985
998
|
:path => "Employee",
|
986
999
|
:sub_class => "Manager"
|
@@ -998,6 +1011,9 @@ class TestQuery < Test::Unit::TestCase
|
|
998
1011
|
"<constraint loopPath='Employee.department.manager' op='=' code='E' path='Employee'/>" +
|
999
1012
|
"<constraint op='LOOKUP' code='F' value='quux' path='Employee'/>" +
|
1000
1013
|
"<constraint extraValue='zip' op='LOOKUP' code='G' value='zop' path='Employee'/>" +
|
1014
|
+
"<constraint op='WITHIN' code='H' path='Employee.age'>" +
|
1015
|
+
"<value>1..10</value><value>30..35</value>" +
|
1016
|
+
"</constraint>" +
|
1001
1017
|
"</query>"
|
1002
1018
|
|
1003
1019
|
compare_xml(expected, query.to_xml.to_s)
|
data/test/test_result_row.rb
CHANGED
@@ -12,14 +12,9 @@ class TestResults < Test::Unit::TestCase
|
|
12
12
|
super
|
13
13
|
file = File.new(
|
14
14
|
File.dirname(__FILE__) + "/data/resultrow.json", "r")
|
15
|
-
file2 = File.new(
|
16
|
-
File.dirname(__FILE__) + "/data/resultrow_new.json", "r")
|
17
15
|
@data = file.read
|
18
|
-
@data2 = file2.read
|
19
16
|
@json = JSON.parse(@data)
|
20
|
-
@json2 = JSON.parse(@data2)
|
21
17
|
@view = ["Company.departments.name","Company.departments.manager.name", "Company.departments.manager.age"]
|
22
|
-
@view2 = ["Company.departments.name","Company.departments.manager.name", "Company.departments.manager.age", "Company.address.address"]
|
23
18
|
@bad_view = ["Company.departments.name","Company.departments.manager.name"]
|
24
19
|
end
|
25
20
|
|
@@ -47,31 +42,6 @@ class TestResults < Test::Unit::TestCase
|
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
50
|
-
def test_array_access2
|
51
|
-
|
52
|
-
rr = NewResultRow.new(@data2, @view2)
|
53
|
-
|
54
|
-
assert_equal(rr[0], "DepartmentA1")
|
55
|
-
assert_equal(rr[1], "EmployeeA1")
|
56
|
-
|
57
|
-
rr = NewResultRow.new(@json2, @view2)
|
58
|
-
|
59
|
-
assert_equal(rr[0], "DepartmentA1")
|
60
|
-
assert_equal(rr[1], "EmployeeA1")
|
61
|
-
|
62
|
-
assert_equal(rr[1..2], ["EmployeeA1", 33])
|
63
|
-
assert_equal(rr[0, 2], ["DepartmentA1", "EmployeeA1"])
|
64
|
-
|
65
|
-
assert_equal(rr.first, "DepartmentA1")
|
66
|
-
assert_equal(rr[3], nil)
|
67
|
-
assert_equal(rr.last, nil)
|
68
|
-
|
69
|
-
assert_raise IndexError do
|
70
|
-
rr[4]
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
45
|
def test_array_access
|
76
46
|
|
77
47
|
rr = ResultsRow.new(@data, @view)
|
data/test/test_sugar.rb
CHANGED
@@ -32,13 +32,14 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
32
32
|
|
33
33
|
def test_view_expansion
|
34
34
|
q = @model.table("Employee").select("*", "department.*")
|
35
|
-
expected = [
|
35
|
+
expected = [
|
36
|
+
"Employee.age",
|
36
37
|
"Employee.end",
|
37
|
-
"Employee.id",
|
38
38
|
"Employee.fullTime",
|
39
|
-
"Employee.
|
40
|
-
"Employee.
|
41
|
-
"Employee.department.id"
|
39
|
+
"Employee.id",
|
40
|
+
"Employee.name",
|
41
|
+
"Employee.department.id",
|
42
|
+
"Employee.department.name"]
|
42
43
|
|
43
44
|
assert_equal(expected, q.views.map {|x| x.to_s})
|
44
45
|
end
|
@@ -50,7 +51,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
50
51
|
where(:name => {"=" => nil}).
|
51
52
|
where(:fullTime => {"!=" => nil})
|
52
53
|
|
53
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
54
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
54
55
|
"<constraint op='IS NULL' code='A' path='Employee.age'/>" +
|
55
56
|
"<constraint op='IS NULL' code='B' path='Employee.name'/>" +
|
56
57
|
"<constraint op='IS NOT NULL' code='C' path='Employee.fullTime'/>" +
|
@@ -68,7 +69,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
68
69
|
where("department.name" => {:contains => "foo"}).
|
69
70
|
where(:name => {"!=" => "bar"})
|
70
71
|
|
71
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
72
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
72
73
|
"<constraint op='=' code='A' value='foo' path='Employee.name'/>" +
|
73
74
|
"<constraint op='=' code='B' value='10' path='Employee.age'/>" +
|
74
75
|
"<constraint op='<' code='C' value='200' path='Employee.end'/>" +
|
@@ -90,7 +91,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
90
91
|
where(:name => {:ne => "bar"}).
|
91
92
|
where(:name => {:== => "zop"})
|
92
93
|
|
93
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
94
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
94
95
|
"<constraint op='<' code='A' value='100' path='Employee.age'/>" +
|
95
96
|
"<constraint op='>' code='B' value='200' path='Employee.age'/>" +
|
96
97
|
"<constraint op='<=' code='C' value='300' path='Employee.age'/>" +
|
@@ -110,7 +111,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
110
111
|
where(:department => {:lookup => "foo"}).
|
111
112
|
where("department.company" => {:lookup => "foo", :with => "extra"})
|
112
113
|
|
113
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
114
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
114
115
|
"<constraint op='LOOKUP' code='A' value='foo' path='Employee.department'/>" +
|
115
116
|
"<constraint extraValue='extra' op='LOOKUP' code='B' value='foo' path='Employee.department.company'/>" +
|
116
117
|
"</query>"
|
@@ -127,7 +128,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
127
128
|
where("Employee.department" => {:in => "a list"}).
|
128
129
|
where("Employee.department.company" => {:not_in => "a list"})
|
129
130
|
|
130
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
131
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
131
132
|
"<constraint op='IN' code='A' value='test-list' path='Employee'/>" +
|
132
133
|
"<constraint op='IN' code='B' value='test-list' path='Employee.department.manager'/>" +
|
133
134
|
"<constraint op='NOT IN' code='C' value='test-list' path='Employee.department.manager'/>" +
|
@@ -152,7 +153,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
152
153
|
where("department.manager.age" => {:none_of => [46, 47]}).
|
153
154
|
where("department.manager.end" => {:one_of => [56, 57]})
|
154
155
|
|
155
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
156
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
156
157
|
"<constraint op='ONE OF' code='A' path='Employee.age'>" +
|
157
158
|
"<value>30</value><value>31</value><value>32</value><value>33</value><value>34</value><value>35</value>" +
|
158
159
|
"</constraint>" +
|
@@ -194,7 +195,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
194
195
|
where("department.company.CEO" => {:is => "department.manager"}).
|
195
196
|
where("department.company.CEO" => {:is_not => "department.employees"})
|
196
197
|
|
197
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
198
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
198
199
|
"<constraint op='=' loopPath='Employee.department.manager' code='A' path='Employee.department.company.CEO'/>" +
|
199
200
|
"<constraint op='!=' loopPath='Employee.department.employees' code='B' path='Employee.department.company.CEO'/>" +
|
200
201
|
"</query>"
|
@@ -209,7 +210,7 @@ class TestQuerySugar < Test::Unit::TestCase
|
|
209
210
|
where("department.employees" => manager).
|
210
211
|
where("department.employees" => {:sub_class => "CEO"})
|
211
212
|
|
212
|
-
expected = "<query model='testmodel' sortOrder='Employee.
|
213
|
+
expected = "<query model='testmodel' sortOrder='Employee.age ASC' view='Employee.age Employee.end Employee.fullTime Employee.id Employee.name'>" +
|
213
214
|
"<constraint type='Manager' path='Employee.department.employees'/>" +
|
214
215
|
"<constraint type='CEO' path='Employee.department.employees'/>" +
|
215
216
|
"</query>"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: intermine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.99.03
|
9
|
+
- 0
|
10
|
+
version: 1.00.00
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alex Kalderimis
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-10-08 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json
|
@@ -133,6 +133,8 @@ files:
|
|
133
133
|
- test/data/resultrow.json
|
134
134
|
- test/data/resultset.json
|
135
135
|
- test/data/testmodel_model.xml
|
136
|
+
- test/live_results.rb
|
137
|
+
- test/live_summary_test.rb
|
136
138
|
- test/live_test.rb
|
137
139
|
- test/test.rb
|
138
140
|
- test/test_helper.rb
|
@@ -148,7 +150,6 @@ files:
|
|
148
150
|
- LICENCE
|
149
151
|
- Rakefile
|
150
152
|
- README.rdoc
|
151
|
-
- TODO
|
152
153
|
- Gemfile
|
153
154
|
- contact_header.rdoc
|
154
155
|
homepage: http://www.intermine.org
|
@@ -184,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
185
|
requirements: []
|
185
186
|
|
186
187
|
rubyforge_project: intermine
|
187
|
-
rubygems_version: 1.
|
188
|
+
rubygems_version: 1.8.15
|
188
189
|
signing_key:
|
189
190
|
specification_version: 3
|
190
191
|
summary: Webservice Client Library for InterMine Data-Warehouses
|