caruby-core 1.5.5 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/Gemfile +9 -0
  2. data/History.md +5 -1
  3. data/lib/caruby.rb +3 -5
  4. data/lib/caruby/caruby-src.tar.gz +0 -0
  5. data/lib/caruby/database.rb +53 -69
  6. data/lib/caruby/database/application_service.rb +25 -0
  7. data/lib/caruby/database/cache.rb +60 -0
  8. data/lib/caruby/database/fetched_matcher.rb +52 -38
  9. data/lib/caruby/database/lazy_loader.rb +4 -4
  10. data/lib/caruby/database/operation.rb +34 -0
  11. data/lib/caruby/database/persistable.rb +171 -86
  12. data/lib/caruby/database/persistence_service.rb +32 -34
  13. data/lib/caruby/database/persistifier.rb +100 -43
  14. data/lib/caruby/database/reader.rb +107 -85
  15. data/lib/caruby/database/reader_template_builder.rb +60 -0
  16. data/lib/caruby/database/saved_matcher.rb +3 -3
  17. data/lib/caruby/database/sql_executor.rb +88 -17
  18. data/lib/caruby/database/writer.rb +213 -177
  19. data/lib/caruby/database/writer_template_builder.rb +334 -0
  20. data/lib/caruby/{util → helpers}/controlled_value.rb +0 -0
  21. data/lib/caruby/{util → helpers}/coordinate.rb +4 -4
  22. data/lib/caruby/{util → helpers}/person.rb +3 -3
  23. data/lib/caruby/{util → helpers}/properties.rb +7 -9
  24. data/lib/caruby/{util → helpers}/roman.rb +2 -2
  25. data/lib/caruby/{util → helpers}/version.rb +1 -1
  26. data/lib/caruby/json/deserializer.rb +2 -2
  27. data/lib/caruby/json/serializer.rb +49 -7
  28. data/lib/caruby/metadata.rb +30 -0
  29. data/lib/caruby/metadata/java_property.rb +21 -0
  30. data/lib/caruby/metadata/propertied.rb +191 -0
  31. data/lib/caruby/metadata/property.rb +22 -0
  32. data/lib/caruby/metadata/property_characteristics.rb +201 -0
  33. data/lib/caruby/migration/migratable.rb +11 -182
  34. data/lib/caruby/rdbi/driver/jdbc.rb +446 -0
  35. data/lib/caruby/resource.rb +20 -823
  36. data/lib/caruby/version.rb +1 -1
  37. data/test/lib/caruby/database/cache_test.rb +54 -0
  38. data/test/lib/caruby/{util → helpers}/controlled_value_test.rb +3 -5
  39. data/test/lib/caruby/{util → helpers}/person_test.rb +4 -6
  40. data/test/lib/caruby/helpers/properties_test.rb +34 -0
  41. data/test/lib/caruby/{util → helpers}/roman_test.rb +2 -3
  42. data/test/lib/caruby/{util → helpers}/version_test.rb +2 -3
  43. data/test/lib/helper.rb +7 -0
  44. metadata +161 -214
  45. data/lib/caruby/cli/application.rb +0 -36
  46. data/lib/caruby/cli/command.rb +0 -202
  47. data/lib/caruby/csv/csv_mapper.rb +0 -159
  48. data/lib/caruby/csv/csvio.rb +0 -203
  49. data/lib/caruby/database/search_template_builder.rb +0 -56
  50. data/lib/caruby/database/store_template_builder.rb +0 -278
  51. data/lib/caruby/domain.rb +0 -193
  52. data/lib/caruby/domain/attribute.rb +0 -584
  53. data/lib/caruby/domain/attributes.rb +0 -628
  54. data/lib/caruby/domain/dependency.rb +0 -225
  55. data/lib/caruby/domain/id_alias.rb +0 -22
  56. data/lib/caruby/domain/importer.rb +0 -183
  57. data/lib/caruby/domain/introspection.rb +0 -176
  58. data/lib/caruby/domain/inverse.rb +0 -172
  59. data/lib/caruby/domain/inversible.rb +0 -90
  60. data/lib/caruby/domain/java_attribute.rb +0 -173
  61. data/lib/caruby/domain/merge.rb +0 -185
  62. data/lib/caruby/domain/metadata.rb +0 -142
  63. data/lib/caruby/domain/mixin.rb +0 -35
  64. data/lib/caruby/domain/properties.rb +0 -95
  65. data/lib/caruby/domain/reference_visitor.rb +0 -428
  66. data/lib/caruby/domain/uniquify.rb +0 -50
  67. data/lib/caruby/import/java.rb +0 -387
  68. data/lib/caruby/migration/migrator.rb +0 -918
  69. data/lib/caruby/migration/resource_module.rb +0 -9
  70. data/lib/caruby/migration/uniquify.rb +0 -17
  71. data/lib/caruby/util/attribute_path.rb +0 -44
  72. data/lib/caruby/util/cache.rb +0 -56
  73. data/lib/caruby/util/class.rb +0 -149
  74. data/lib/caruby/util/collection.rb +0 -1152
  75. data/lib/caruby/util/domain_extent.rb +0 -46
  76. data/lib/caruby/util/file_separator.rb +0 -65
  77. data/lib/caruby/util/inflector.rb +0 -27
  78. data/lib/caruby/util/log.rb +0 -95
  79. data/lib/caruby/util/math.rb +0 -12
  80. data/lib/caruby/util/merge.rb +0 -59
  81. data/lib/caruby/util/module.rb +0 -18
  82. data/lib/caruby/util/options.rb +0 -97
  83. data/lib/caruby/util/partial_order.rb +0 -35
  84. data/lib/caruby/util/pretty_print.rb +0 -204
  85. data/lib/caruby/util/stopwatch.rb +0 -74
  86. data/lib/caruby/util/topological_sync_enumerator.rb +0 -62
  87. data/lib/caruby/util/transitive_closure.rb +0 -55
  88. data/lib/caruby/util/tree.rb +0 -48
  89. data/lib/caruby/util/trie.rb +0 -37
  90. data/lib/caruby/util/uniquifier.rb +0 -30
  91. data/lib/caruby/util/validation.rb +0 -20
  92. data/lib/caruby/util/visitor.rb +0 -365
  93. data/lib/caruby/util/weak_hash.rb +0 -36
  94. data/test/lib/caruby/csv/csv_mapper_test.rb +0 -40
  95. data/test/lib/caruby/csv/csvio_test.rb +0 -69
  96. data/test/lib/caruby/database/persistable_test.rb +0 -92
  97. data/test/lib/caruby/domain/domain_test.rb +0 -112
  98. data/test/lib/caruby/domain/inversible_test.rb +0 -99
  99. data/test/lib/caruby/domain/reference_visitor_test.rb +0 -130
  100. data/test/lib/caruby/import/java_test.rb +0 -80
  101. data/test/lib/caruby/import/mixed_case_test.rb +0 -14
  102. data/test/lib/caruby/migration/test_case.rb +0 -102
  103. data/test/lib/caruby/test_case.rb +0 -230
  104. data/test/lib/caruby/util/cache_test.rb +0 -23
  105. data/test/lib/caruby/util/class_test.rb +0 -61
  106. data/test/lib/caruby/util/collection_test.rb +0 -398
  107. data/test/lib/caruby/util/command_test.rb +0 -55
  108. data/test/lib/caruby/util/domain_extent_test.rb +0 -60
  109. data/test/lib/caruby/util/file_separator_test.rb +0 -30
  110. data/test/lib/caruby/util/inflector_test.rb +0 -12
  111. data/test/lib/caruby/util/lazy_hash_test.rb +0 -34
  112. data/test/lib/caruby/util/merge_test.rb +0 -83
  113. data/test/lib/caruby/util/module_test.rb +0 -25
  114. data/test/lib/caruby/util/options_test.rb +0 -59
  115. data/test/lib/caruby/util/partial_order_test.rb +0 -42
  116. data/test/lib/caruby/util/pretty_print_test.rb +0 -85
  117. data/test/lib/caruby/util/properties_test.rb +0 -50
  118. data/test/lib/caruby/util/stopwatch_test.rb +0 -18
  119. data/test/lib/caruby/util/topological_sync_enumerator_test.rb +0 -69
  120. data/test/lib/caruby/util/transitive_closure_test.rb +0 -67
  121. data/test/lib/caruby/util/tree_test.rb +0 -23
  122. data/test/lib/caruby/util/trie_test.rb +0 -14
  123. data/test/lib/caruby/util/visitor_test.rb +0 -278
  124. data/test/lib/caruby/util/weak_hash_test.rb +0 -45
  125. data/test/lib/examples/clinical_trials/migration/migration_test.rb +0 -58
  126. data/test/lib/examples/clinical_trials/migration/test_case.rb +0 -38
@@ -1,46 +0,0 @@
1
- require 'caruby/util/collection'
2
- require 'caruby/util/validation'
3
-
4
- # A DomainExtent contains class-specific key => object associations.
5
- # The objects are created on demand and accessed by the get method.
6
- #
7
- # @example
8
- # DomainExtent.new { |klass, key| key.to_s + klass.name }.get(String, 'a') #=> aString
9
- class DomainExtent < LazyHash
10
- # Creates a new DomainExtent. The block passed to the constructor
11
- # is a factory to create an object on demand, with arguments
12
- # the target class and the target key. The default block is empty.
13
- def initialize
14
- return initialize {} unless block_given?
15
- super { |klass| LazyHash.new { |key| yield klass, key } }
16
- end
17
-
18
- # Sets the factory used to create an instance of the specified class.
19
- # The factory is called to create a new instance when a get operation
20
- # does not yet have a key => instance association.
21
- #
22
- # The factory accepts a single argument, the instance key, e.g.
23
- # set_factory(MyClass) { |key| MyClass.new(key) }
24
- def set_factory(klass, &factory)
25
- # the current instances, if any
26
- instances = fetch(klass) if has_key?(klass)
27
- # make the key => instance class extent map
28
- # the instance creation factory is
29
- class_extent = LazyHash.new { |key| yield key }
30
- # copy existing instances if necessary
31
- class_extent.merge!(instances) if instances
32
- # add the class => class extent association
33
- self[klass] = class_extent
34
- end
35
-
36
- # Returns the domain instance of the given class for the given key.
37
- # If there is nois no entry for key and the factory is set for the class,
38
- # then a new object is created on demand.
39
- def get(klass, key)
40
- raise RuntimeError.new("Invalid target class: #{klass}") unless klass.is_a?(Class)
41
- raise RuntimeError.new("Missing target key value") if key.nil?
42
- # the class extent hash is created on demand if necessary.
43
- # the instance is created on demand if there is a factory for the class.
44
- self[klass][key]
45
- end
46
- end
@@ -1,65 +0,0 @@
1
- require 'caruby/util/class'
2
-
3
- class File
4
- [:gets, :readline, :readlines].each do |attr|
5
- # Overrides the standard method to infer a line separator from the input
6
- # if the separator argument is the default.
7
- redefine_method(attr) do |original|
8
- lambda do |*params|
9
- sep = params.first || default_line_separator
10
- send(original, sep)
11
- end
12
- end
13
-
14
- # Overrides the standard {#each} method to infer a line separator from the input
15
- # if the separator argument is not given.
16
- def each(separator=nil)
17
- while (line = gets(separator)) do
18
- yield line
19
- end
20
- end
21
- end
22
-
23
- private
24
-
25
- # Returns the default line separator. The logic is borrowed from the FasterCVS gem.
26
- def default_line_separator
27
- @def_line_sep ||= infer_line_separator
28
- end
29
-
30
- def infer_line_separator
31
- type_line_separator or content_line_separator or $/
32
- end
33
-
34
- def type_line_separator
35
- if [ARGF, STDIN, STDOUT, STDERR].include?(self) or
36
- (defined?(Zlib) and self.class == Zlib::GzipWriter) then
37
- return $/
38
- end
39
- end
40
-
41
- def content_line_separator
42
- begin
43
- saved_pos = pos # remember where we were
44
- # read a chunk until a separator is discovered
45
- sep = discover_line_separator
46
- # tricky seek() clone to work around GzipReader's lack of seek()
47
- rewind
48
- # reset back to the remembered position
49
- chunks, residual = saved_pos.divmod(1024)
50
- chunks.times { read(1024) }
51
- read(residual)
52
- rescue IOError # stream not opened for reading
53
- end
54
- sep
55
- end
56
-
57
- def discover_line_separator
58
- # read a chunk until a separator is discovered
59
- while (sample = read(1024)) do
60
- sample += read(1) if sample[-1, 1] == "\r" and not eof?
61
- # try to find a standard separator
62
- return $& if sample =~ /\r\n?|\n/
63
- end
64
- end
65
- end
@@ -1,27 +0,0 @@
1
- require 'caruby/active_support/inflector'
2
-
3
- class String
4
- # @param [Numeric] quantity the amount qualifier
5
- # @return this String qualified by a plural if the quantity is not 1
6
- # @example
7
- # "rose".quantify(3) #=> "roses"
8
- # "rose".quantify(1 #=> "rose"
9
- def quantify(quantity)
10
- raise ArgumentError.new("Missing quantity argument") if quantity.nil?
11
- "#{quantity} #{quantity == 1 ? self : pluralize}"
12
- end
13
-
14
- # @return this String with the first letter capitalized and other letters preserved.
15
- # @example
16
- # "rosesAreRed".capitalize_first #=> "RosesAreRed"
17
- def capitalize_first
18
- sub(/(?:^)(.)/) { $1.upcase }
19
- end
20
-
21
- # @return this String with the first letter decapitalized and other letters preserved.
22
- # @example
23
- # "RosesAreRed".decapitalize #=> "rosesAreRed"
24
- def decapitalize
25
- sub(/(?:^)(.)/) { $1.downcase }
26
- end
27
- end
@@ -1,95 +0,0 @@
1
- require 'logger'
2
- require 'singleton'
3
- require 'ftools'
4
- require 'caruby/util/collection'
5
-
6
- # @return [CaRuby::Logger] the global logger
7
- def logger
8
- CaRuby::Log.instance.logger
9
- end
10
-
11
- module CaRuby
12
- # Extends the standard Logger to format multi-line messages on separate lines.
13
- class MultilineLogger < Logger
14
- # @see Logger#initialize
15
- def initialize(*args)
16
- super
17
- end
18
-
19
- private
20
-
21
- # Writes msg to the log device. Each line in msg is formatted separately.
22
- #
23
- # @param (see Logger#format_message)
24
- # @return (see Logger#format_message)
25
- def format_message(severity, datetime, progname, msg)
26
- if String === msg then
27
- msg.inject('') { |s, line| s << super(severity, datetime, progname, line.chomp) }
28
- else
29
- super
30
- end
31
- end
32
- end
33
-
34
- # Wraps a standard global Logger.
35
- class Log
36
- include Singleton
37
-
38
- # Opens the log.
39
- #
40
- # @param [String, IO, nil] file_or_dev the log file or device (default STDOUT)
41
- # @param [Hash, nil] the Logger::LogDevice options
42
- # @return [Logger] the logger
43
- def open(file_or_dev=nil, options=nil)
44
- dev = file_or_dev || default_log_file
45
- return @logger if same_file?(dev, @dev)
46
- # close the previous log file, if necessary
47
- @logger.close if @logger
48
- if String === dev then File.makedirs(File.dirname(dev)) end
49
- # default is 4-file rotation @ 16MB each
50
- shift_age = Options.get(:shift_age, options, 4)
51
- shift_size = Options.get(:shift_size, options, 16 * 1048576)
52
- @logger = MultilineLogger.new(dev, shift_age, shift_size)
53
- @logger.level = Options.get(:debug, options, ENV['DEBUG'] == 'true') ? Logger::DEBUG : Logger::INFO
54
- @logger.info('============================================')
55
- @logger.info('Logging started.')
56
- @dev = dev
57
- @logger
58
- end
59
-
60
- def close
61
- @logger.close
62
- @logger = nil
63
- end
64
-
65
- # Returns the logger.
66
- def logger
67
- @logger ||= open
68
- end
69
-
70
- # @return [String, nil] the log file, or nil if the log was opened on an IO rather
71
- # than a String
72
- def file
73
- @dev if String === @dev
74
- end
75
-
76
- private
77
-
78
- def same_file?(f1, f2)
79
- f1 == f2 or (String === f2 and String === f1 and File.expand_path(f1) == File.expand_path(f2))
80
- end
81
-
82
- def default_log_file
83
- log_ndx = ARGV.index("--log") || ARGV.index("-l")
84
- if log_ndx then
85
- ARGV[log_ndx + 1]
86
- elsif ENV.has_key?("LOG") then
87
- ENV["LOG"]
88
- elsif defined?(DEF_LOG_FILE)
89
- DEF_LOG_FILE
90
- else
91
- 'log/caruby.log'
92
- end
93
- end
94
- end
95
- end
@@ -1,12 +0,0 @@
1
- # Extends the Numeric class with max and min methods.
2
- class Numeric
3
- # Returns the minimum of this Numeric and the other Numerics.
4
- def min(*others)
5
- others.inject(self) { |min, other| other < min ? other : min }
6
- end
7
-
8
- # Returns the minimum of this Numeric and the other Numerics.
9
- def max(*others)
10
- others.inject(self) { |max, other| other > max ? other : max }
11
- end
12
- end
@@ -1,59 +0,0 @@
1
- require 'caruby/util/options'
2
- require 'caruby/util/collection'
3
-
4
- class Hash
5
- # Returns a new hash which merges the other hash with this hash.
6
- #
7
- # Supported options include the following:
8
- # * :deep - merge values which match on the key.
9
- # If the :deep option is set, and a key matches both this hash and the other hash
10
- # on hash values, then the other hash's value is recursively merged into this Hash's
11
- # value using the non-destructive {#merge} method with the deep option set.
12
- # If a block is given to this method, then the block is passed to the value merge.
13
- #
14
- # @example
15
- # {:a => [1], :b => [2]}.merge({:b => [3]}, :deep) #=> {:a => [1], :b => [2, 3]}
16
- # {:a => {:b => [1]}}.merge({:a => {:b => [2]}, :c => 3}, :deep) #=> {:a => {:b => [1, 2]}, :c => 3}
17
- def merge(other, options=nil, &block)
18
- dup.merge!(other, options, &block)
19
- end
20
-
21
- alias :base__merge! :merge!
22
- private :base__merge!
23
-
24
- # Merges the other hash into this hash and returns this modified hash.
25
- #
26
- # @see #merge the options and block description
27
- def merge!(other, options=nil, &block)
28
- # use the standard Hash merge unless the :deep option is set
29
- return base__merge!(other, &block) unless Options.get(:deep, options)
30
- # merge the other entries:
31
- # if the hash value is a hash, then call merge on that hash value.
32
- # otherwise, if the hash value understands merge, then call that method.
33
- # otherwise, if there is a block, then call the block.
34
- # otherwise, set the the hash value to the other value.
35
- base__merge!(other) do |key, oldval, newval|
36
- if Hash === oldval then
37
- oldval.merge(newval, options, &block)
38
- elsif oldval.respond_to?(:merge)
39
- oldval.merge(newval, &block)
40
- elsif block_given? then
41
- yield(key, oldval, newval)
42
- else
43
- newval
44
- end
45
- end
46
- end
47
- end
48
-
49
- class Array
50
- # Adds the elements in the other Enumerable which are not already included in this Array.
51
- # Returns this modified Array.
52
- def merge(other)
53
- # incompatible merge argument is allowed but ignored
54
- self unless Enumerable === other
55
- # concatenate the members of other not in self
56
- unique = other.to_a - self
57
- concat(unique)
58
- end
59
- end
@@ -1,18 +0,0 @@
1
- class Module
2
- # Returns the class or module with the given name defined in this module.
3
- # The name can qualified by parent modules, e.g. +MyApp::Person+.
4
- # If name cannot be resolved as a Module, then this method returns nil.
5
- #
6
- # @param [String] the class name
7
- # @return [Module, nil] the class or module defined in this module, or nil if none
8
- def module_with_name(name)
9
- name.split('::').inject(self) { |parent, part| parent.const_get(part) } rescue nil
10
- end
11
-
12
- # @example
13
- # A::B.parent_module #=> A
14
- # @return [Module] this module's definition context
15
- def parent_module
16
- Kernel.module_with_name(name.split('::')[0..-2].join('::'))
17
- end
18
- end
@@ -1,97 +0,0 @@
1
- require 'caruby/util/collection'
2
- require 'caruby/util/validation'
3
- require 'caruby/util/merge'
4
-
5
- # Options is a utility class to support method options.
6
- class Options
7
- # Returns the value of option in options as follows:
8
- # * If options is a hash which contains the option key, then this method returns
9
- # the option value. A non-collection options[option] value is wrapped as a singleton
10
- # collection to conform to a collection default type, as shown in the example below.
11
- # * If options equals the option symbol, then this method returns +true+.
12
- # * If options is an Array of symbols which includes the given option, then this method
13
- # returns +true+.
14
- # * Otherwise, this method returns the default.
15
- #
16
- # If default is nil and a block is given to this method, then the default is determined
17
- # by calling the block with no arguments. The block can also be used to raise a missing
18
- # option exception, e.g.:
19
- # Options.get(:userid, options) { raise RuntimeError.new("Missing required option: userid") }
20
- #
21
- # @example
22
- # Options.get(:create, {:create => true}) #=> true
23
- # Options.get(:create, :create) #=> true
24
- # Options.get(:create, [:create, :compress]) #=> true
25
- # Options.get(:create, nil) #=> nil
26
- # Options.get(:create, nil, :false) #=> false
27
- # Options.get(:create, nil, :true) #=> true
28
- # Options.get(:values, nil, []) #=> []
29
- # Options.get(:values, {:values => :a}, []) #=> [:a]
30
- def self.get(option, options, default=nil, &block)
31
- return default(default, &block) if options.nil?
32
- case options
33
- when Hash then
34
- value = options[option]
35
- if String === value then value.strip! end
36
- value.nil_or_empty? ? default(default, &block) : value
37
- when Enumerable then
38
- options.include?(option) ? true : default(default, &block)
39
- when Symbol then
40
- option == options ? true : default(default, &block)
41
- else
42
- raise ArgumentError.new("Options argument type is not supported; expected Hash or Symbol, found: #{options.class}")
43
- end
44
- end
45
-
46
- # Returns the given argument list as a hash, determined as follows:
47
- # * If the sole argument member is a hash, then that hash is the options.
48
- # * An argument list of option symbols followed by zero, one or more non-option parameters is composed as the option hash.
49
- # * An empty argument list is a new empty option hash.
50
- #
51
- # @example
52
- # Options.to_hash() #=> {}
53
- # Options.to_hash(nil) #=> {}
54
- # Options.to_hash(:a => 1) #=> {:a => 1}
55
- # Options.to_hash(:a) #=> {:a => true}
56
- # Options.to_hash(:a, 1, :b, 2) #=> {:a => 1, :b => 2}
57
- # Options.to_hash(:a, 1, :b, :c, 2, 3) #=> {:a => 1, :b => true, :c => [2, 3]}
58
- # @param [Array] args the option list
59
- # @return [Hash] the option hash
60
- def self.to_hash(*args)
61
- unless Enumerable === args then
62
- raise ArgumentError.new("Expected Enumerable, found #{args.class.qp}")
63
- end
64
- oargs = {}
65
- opt = args.first
66
- return oargs if opt.nil?
67
- return opt if oargs.empty? and Hash === opt
68
- unless Symbol === opt then
69
- raise ArgumentError.new("Expected Symbol as first argument, found #{args.first.class.qp}")
70
- end
71
- args.inject(nil) do |list, item|
72
- Symbol === item ? oargs[item] = Array.new : list << item
73
- end
74
- # convert the value list to true, a single value or leave as an array
75
- oargs.transform do |list|
76
- case list.size
77
- when 0 then true
78
- when 1 then list.first
79
- else list
80
- end
81
- end.to_hash
82
- end
83
-
84
- # @param [Hash, Symbol, nil] opts the options to validate
85
- # @raise [ValidationError] if the given options are not in the given allowable choices
86
- def self.validate(options, choices)
87
- to_hash(options).each_key do |opt|
88
- raise ValidationError.new("Option is not supported: #{opt}") unless choices.include?(opt)
89
- end
90
- end
91
-
92
- private
93
-
94
- def self.default(value)
95
- value.nil? && block_given? ? yield : value
96
- end
97
- end
@@ -1,35 +0,0 @@
1
- # A PartialOrder is a Comparable which restricted scope. Classes wich include PartialOrder
2
- # are required to implement the <=> operator with the following semantics:
3
- # * _a_ <=> _b_ returns -1, 0, or 1 if a and b are comparable, nil otherwise
4
- # A PartialOrder thus relaxes comparison symmetry, e.g.
5
- # a < b
6
- # does not imply
7
- # b >= a.
8
- # Example:
9
- # module Queued
10
- # attr_reader :queue
11
- # def <=>(other)
12
- # queue.index(self) <=> queue.index(other) if queue.equal?(other.queue)
13
- # end
14
- # end
15
- # q1 = [a, b] # a, b are Queued
16
- # q2 = [c] # c is a Queued
17
- # a < b #=> true
18
- # b < c #=> nil
19
- module PartialOrder
20
- include Comparable
21
-
22
- Comparable.instance_methods(false).each do |m|
23
- define_method(m.to_sym) do |other|
24
- self <=> other ? super : nil
25
- end
26
- end
27
-
28
- # @return [Boolean] true if other is an instance of this object's class and other == self,
29
- # false otherwise
30
- def eql?(other)
31
- self.class === other and super
32
- end
33
-
34
- alias :== :eql?
35
- end