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.
- data/Gemfile +9 -0
- data/History.md +5 -1
- data/lib/caruby.rb +3 -5
- data/lib/caruby/caruby-src.tar.gz +0 -0
- data/lib/caruby/database.rb +53 -69
- data/lib/caruby/database/application_service.rb +25 -0
- data/lib/caruby/database/cache.rb +60 -0
- data/lib/caruby/database/fetched_matcher.rb +52 -38
- data/lib/caruby/database/lazy_loader.rb +4 -4
- data/lib/caruby/database/operation.rb +34 -0
- data/lib/caruby/database/persistable.rb +171 -86
- data/lib/caruby/database/persistence_service.rb +32 -34
- data/lib/caruby/database/persistifier.rb +100 -43
- data/lib/caruby/database/reader.rb +107 -85
- data/lib/caruby/database/reader_template_builder.rb +60 -0
- data/lib/caruby/database/saved_matcher.rb +3 -3
- data/lib/caruby/database/sql_executor.rb +88 -17
- data/lib/caruby/database/writer.rb +213 -177
- data/lib/caruby/database/writer_template_builder.rb +334 -0
- data/lib/caruby/{util → helpers}/controlled_value.rb +0 -0
- data/lib/caruby/{util → helpers}/coordinate.rb +4 -4
- data/lib/caruby/{util → helpers}/person.rb +3 -3
- data/lib/caruby/{util → helpers}/properties.rb +7 -9
- data/lib/caruby/{util → helpers}/roman.rb +2 -2
- data/lib/caruby/{util → helpers}/version.rb +1 -1
- data/lib/caruby/json/deserializer.rb +2 -2
- data/lib/caruby/json/serializer.rb +49 -7
- data/lib/caruby/metadata.rb +30 -0
- data/lib/caruby/metadata/java_property.rb +21 -0
- data/lib/caruby/metadata/propertied.rb +191 -0
- data/lib/caruby/metadata/property.rb +22 -0
- data/lib/caruby/metadata/property_characteristics.rb +201 -0
- data/lib/caruby/migration/migratable.rb +11 -182
- data/lib/caruby/rdbi/driver/jdbc.rb +446 -0
- data/lib/caruby/resource.rb +20 -823
- data/lib/caruby/version.rb +1 -1
- data/test/lib/caruby/database/cache_test.rb +54 -0
- data/test/lib/caruby/{util → helpers}/controlled_value_test.rb +3 -5
- data/test/lib/caruby/{util → helpers}/person_test.rb +4 -6
- data/test/lib/caruby/helpers/properties_test.rb +34 -0
- data/test/lib/caruby/{util → helpers}/roman_test.rb +2 -3
- data/test/lib/caruby/{util → helpers}/version_test.rb +2 -3
- data/test/lib/helper.rb +7 -0
- metadata +161 -214
- data/lib/caruby/cli/application.rb +0 -36
- data/lib/caruby/cli/command.rb +0 -202
- data/lib/caruby/csv/csv_mapper.rb +0 -159
- data/lib/caruby/csv/csvio.rb +0 -203
- data/lib/caruby/database/search_template_builder.rb +0 -56
- data/lib/caruby/database/store_template_builder.rb +0 -278
- data/lib/caruby/domain.rb +0 -193
- data/lib/caruby/domain/attribute.rb +0 -584
- data/lib/caruby/domain/attributes.rb +0 -628
- data/lib/caruby/domain/dependency.rb +0 -225
- data/lib/caruby/domain/id_alias.rb +0 -22
- data/lib/caruby/domain/importer.rb +0 -183
- data/lib/caruby/domain/introspection.rb +0 -176
- data/lib/caruby/domain/inverse.rb +0 -172
- data/lib/caruby/domain/inversible.rb +0 -90
- data/lib/caruby/domain/java_attribute.rb +0 -173
- data/lib/caruby/domain/merge.rb +0 -185
- data/lib/caruby/domain/metadata.rb +0 -142
- data/lib/caruby/domain/mixin.rb +0 -35
- data/lib/caruby/domain/properties.rb +0 -95
- data/lib/caruby/domain/reference_visitor.rb +0 -428
- data/lib/caruby/domain/uniquify.rb +0 -50
- data/lib/caruby/import/java.rb +0 -387
- data/lib/caruby/migration/migrator.rb +0 -918
- data/lib/caruby/migration/resource_module.rb +0 -9
- data/lib/caruby/migration/uniquify.rb +0 -17
- data/lib/caruby/util/attribute_path.rb +0 -44
- data/lib/caruby/util/cache.rb +0 -56
- data/lib/caruby/util/class.rb +0 -149
- data/lib/caruby/util/collection.rb +0 -1152
- data/lib/caruby/util/domain_extent.rb +0 -46
- data/lib/caruby/util/file_separator.rb +0 -65
- data/lib/caruby/util/inflector.rb +0 -27
- data/lib/caruby/util/log.rb +0 -95
- data/lib/caruby/util/math.rb +0 -12
- data/lib/caruby/util/merge.rb +0 -59
- data/lib/caruby/util/module.rb +0 -18
- data/lib/caruby/util/options.rb +0 -97
- data/lib/caruby/util/partial_order.rb +0 -35
- data/lib/caruby/util/pretty_print.rb +0 -204
- data/lib/caruby/util/stopwatch.rb +0 -74
- data/lib/caruby/util/topological_sync_enumerator.rb +0 -62
- data/lib/caruby/util/transitive_closure.rb +0 -55
- data/lib/caruby/util/tree.rb +0 -48
- data/lib/caruby/util/trie.rb +0 -37
- data/lib/caruby/util/uniquifier.rb +0 -30
- data/lib/caruby/util/validation.rb +0 -20
- data/lib/caruby/util/visitor.rb +0 -365
- data/lib/caruby/util/weak_hash.rb +0 -36
- data/test/lib/caruby/csv/csv_mapper_test.rb +0 -40
- data/test/lib/caruby/csv/csvio_test.rb +0 -69
- data/test/lib/caruby/database/persistable_test.rb +0 -92
- data/test/lib/caruby/domain/domain_test.rb +0 -112
- data/test/lib/caruby/domain/inversible_test.rb +0 -99
- data/test/lib/caruby/domain/reference_visitor_test.rb +0 -130
- data/test/lib/caruby/import/java_test.rb +0 -80
- data/test/lib/caruby/import/mixed_case_test.rb +0 -14
- data/test/lib/caruby/migration/test_case.rb +0 -102
- data/test/lib/caruby/test_case.rb +0 -230
- data/test/lib/caruby/util/cache_test.rb +0 -23
- data/test/lib/caruby/util/class_test.rb +0 -61
- data/test/lib/caruby/util/collection_test.rb +0 -398
- data/test/lib/caruby/util/command_test.rb +0 -55
- data/test/lib/caruby/util/domain_extent_test.rb +0 -60
- data/test/lib/caruby/util/file_separator_test.rb +0 -30
- data/test/lib/caruby/util/inflector_test.rb +0 -12
- data/test/lib/caruby/util/lazy_hash_test.rb +0 -34
- data/test/lib/caruby/util/merge_test.rb +0 -83
- data/test/lib/caruby/util/module_test.rb +0 -25
- data/test/lib/caruby/util/options_test.rb +0 -59
- data/test/lib/caruby/util/partial_order_test.rb +0 -42
- data/test/lib/caruby/util/pretty_print_test.rb +0 -85
- data/test/lib/caruby/util/properties_test.rb +0 -50
- data/test/lib/caruby/util/stopwatch_test.rb +0 -18
- data/test/lib/caruby/util/topological_sync_enumerator_test.rb +0 -69
- data/test/lib/caruby/util/transitive_closure_test.rb +0 -67
- data/test/lib/caruby/util/tree_test.rb +0 -23
- data/test/lib/caruby/util/trie_test.rb +0 -14
- data/test/lib/caruby/util/visitor_test.rb +0 -278
- data/test/lib/caruby/util/weak_hash_test.rb +0 -45
- data/test/lib/examples/clinical_trials/migration/migration_test.rb +0 -58
- 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
|
data/lib/caruby/util/log.rb
DELETED
@@ -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
|
data/lib/caruby/util/math.rb
DELETED
@@ -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
|
data/lib/caruby/util/merge.rb
DELETED
@@ -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
|
data/lib/caruby/util/module.rb
DELETED
@@ -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
|
data/lib/caruby/util/options.rb
DELETED
@@ -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
|