caruby-core 1.4.7 → 1.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/History.txt +11 -0
  2. data/README.md +1 -1
  3. data/lib/caruby/cli/command.rb +27 -3
  4. data/lib/caruby/csv/csv_mapper.rb +2 -0
  5. data/lib/caruby/csv/csvio.rb +187 -169
  6. data/lib/caruby/database.rb +33 -16
  7. data/lib/caruby/database/lazy_loader.rb +23 -23
  8. data/lib/caruby/database/persistable.rb +32 -18
  9. data/lib/caruby/database/persistence_service.rb +20 -7
  10. data/lib/caruby/database/reader.rb +22 -21
  11. data/lib/caruby/database/search_template_builder.rb +7 -9
  12. data/lib/caruby/database/sql_executor.rb +52 -27
  13. data/lib/caruby/database/store_template_builder.rb +18 -13
  14. data/lib/caruby/database/writer.rb +107 -44
  15. data/lib/caruby/domain/attribute_metadata.rb +35 -25
  16. data/lib/caruby/domain/java_attribute_metadata.rb +43 -20
  17. data/lib/caruby/domain/merge.rb +9 -5
  18. data/lib/caruby/domain/reference_visitor.rb +4 -3
  19. data/lib/caruby/domain/resource_attributes.rb +52 -12
  20. data/lib/caruby/domain/resource_dependency.rb +129 -42
  21. data/lib/caruby/domain/resource_introspection.rb +1 -1
  22. data/lib/caruby/domain/resource_inverse.rb +20 -3
  23. data/lib/caruby/domain/resource_metadata.rb +20 -4
  24. data/lib/caruby/domain/resource_module.rb +190 -124
  25. data/lib/caruby/import/java.rb +39 -19
  26. data/lib/caruby/migration/migratable.rb +31 -6
  27. data/lib/caruby/migration/migrator.rb +126 -40
  28. data/lib/caruby/migration/uniquify.rb +0 -1
  29. data/lib/caruby/resource.rb +28 -5
  30. data/lib/caruby/util/attribute_path.rb +0 -2
  31. data/lib/caruby/util/class.rb +8 -5
  32. data/lib/caruby/util/collection.rb +5 -3
  33. data/lib/caruby/util/domain_extent.rb +0 -3
  34. data/lib/caruby/util/options.rb +10 -9
  35. data/lib/caruby/util/person.rb +41 -12
  36. data/lib/caruby/util/pretty_print.rb +1 -1
  37. data/lib/caruby/util/validation.rb +0 -28
  38. data/lib/caruby/version.rb +1 -1
  39. data/test/lib/caruby/import/java_test.rb +26 -9
  40. data/test/lib/caruby/migration/test_case.rb +103 -0
  41. data/test/lib/caruby/test_case.rb +231 -0
  42. data/test/lib/caruby/util/class_test.rb +2 -2
  43. data/test/lib/caruby/util/visitor_test.rb +3 -2
  44. data/test/lib/examples/galena/clinical_trials/migration/participant_test.rb +28 -0
  45. data/test/lib/examples/galena/clinical_trials/migration/test_case.rb +40 -0
  46. metadata +195 -170
  47. data/lib/caruby/domain/attribute_initializer.rb +0 -16
  48. data/test/lib/caruby/util/validation_test.rb +0 -14
data/History.txt CHANGED
@@ -1,3 +1,6 @@
1
+ This history lists major release themes. See the GitHub source (https://github.com/caruby/core)
2
+ for change details.
3
+
1
4
  === 1.4.1 / 2010-11-23
2
5
 
3
6
  * Initial public release.
@@ -30,4 +33,12 @@
30
33
 
31
34
  * Support annotation migration.
32
35
 
36
+ === 1.4.8 / 2011-05-03
37
+
38
+ * Fix annotation migration error.
39
+
40
+ * Refactor resource import.
41
+
42
+ === 1.4.9 / 2011-05-04
33
43
 
44
+ * Support Oracle driver.
data/README.md CHANGED
@@ -27,7 +27,7 @@ Feature List
27
27
 
28
28
  Installing
29
29
  ----------
30
- caRuby is installed automatically when an application gem, e.g. caruby-tissue,
30
+ caRuby is installed automatically when an application gem, e.g. [caruby-tissue](http://caruby.rubyforge.org/catissue.html),
31
31
  is installed.
32
32
 
33
33
  Usage
@@ -47,8 +47,11 @@ module CaRuby
47
47
  # @yieldparam (see #run)
48
48
  def initialize(specs=[], &executor)
49
49
  @executor = executor
50
+ # Options start with a dash, arguments are whatever is left.
50
51
  @opt_specs, @arg_specs = specs.partition { |spec| spec[1][0, 1] == '-' }
52
+ # Add the default option specifications.
51
53
  @opt_specs.concat(DEF_OPTS)
54
+ # The application name is the command.
52
55
  super($0)
53
56
  end
54
57
 
@@ -70,6 +73,7 @@ module CaRuby
70
73
 
71
74
  private
72
75
 
76
+ # The default options that apply to all commands.
73
77
  DEF_OPTS = [
74
78
  [:help, "-h", "--help", "Display this help message"],
75
79
  [:file, "--file FILE", "Configuration file containing other options"],
@@ -78,6 +82,7 @@ module CaRuby
78
82
  [:quiet, "-q", "--quiet", "Suppress printing messages to stdout"]
79
83
  ]
80
84
 
85
+ # @param [{Symbol => Object}] opts the option => value hash
81
86
  def call_executor(opts)
82
87
  if @executor.nil? then raise CommandError.new("Command #{self} does not have an execution block") end
83
88
  @executor.call(opts)
@@ -87,14 +92,19 @@ module CaRuby
87
92
  #
88
93
  # @return [{Symbol => Object}] the option => value hash
89
94
  def get_opts
95
+ # the options hash
90
96
  opts = {}
91
97
  # the option parser
92
98
  OptionParser.new do |parser|
99
+ # The help argument string is comprised of the argument specification labels.
93
100
  arg_s = @arg_specs.map { |spec| spec[1] }.join(' ')
101
+ # Build the usage message.
94
102
  parser.banner = "Usage: #{parser.program_name} [options] #{arg_s}"
95
103
  parser.separator ""
96
104
  parser.separator "Options:"
105
+ # parse the options
97
106
  opts = parse(parser)
107
+ # grab the usage message
98
108
  @usage = parser.help
99
109
  end
100
110
  opts
@@ -105,22 +115,36 @@ module CaRuby
105
115
  # @return [{Symbol => Object}] the argument => value hash
106
116
  def get_args
107
117
  return Hash::EMPTY_HASH if ARGV.empty?
118
+ if @arg_specs.empty? then too_many_arguments end
119
+ # Collect the arguments from the command line.
108
120
  args = {}
121
+ # The number of command line arguments or all but the last argument specifications,
122
+ # whichever is less. The last argument can have more than one value, indicated by
123
+ # the argument specification form '...', so it is processed separately below.
109
124
  n = [ARGV.size, @arg_specs.size - 1].min
125
+ # the single-valued arguments
110
126
  n.times { |i| args[@arg_specs[i].first] = ARGV[i] }
127
+ # Process the last argument.
111
128
  if n < ARGV.size then
112
129
  arg, form = @arg_specs.last
130
+ # A multi-valued last argument is the residual command argument array.
131
+ # A single-valued last argument is the last value, if there is exactly one.
132
+ # Otherwise, there are too many arguments.
113
133
  if form.index('...') then
114
134
  args[arg] = ARGV[n..-1]
115
135
  elsif @arg_specs.size == ARGV.size then
116
136
  args[arg] = ARGV[n]
117
137
  else
118
- halt("Too many arguments", 1)
138
+ too_many_arguments
119
139
  end
120
140
  end
121
141
  args
122
142
  end
123
143
 
144
+ def too_many_arguments
145
+ halt("Too many arguments - expected #{@arg_specs.size}, found: #{ARGV.join(' ')}.", 1)
146
+ end
147
+
124
148
  # @param [OptionParser] parser the option parser
125
149
  # @return [{Symbol => Object}] the option => value hash
126
150
  def parse(parser)
@@ -167,8 +191,8 @@ module CaRuby
167
191
 
168
192
  # Prints the given message and program usage, then exits with the given status.
169
193
  def halt(message=nil, status=0)
170
- print(message) if message
171
- print(@usage)
194
+ puts(message) if message
195
+ puts(@usage)
172
196
  exit(status)
173
197
  end
174
198
  end
@@ -3,6 +3,8 @@ require 'caruby/util/properties'
3
3
 
4
4
  module CaRuby
5
5
  # Maps a CSV extract to a caBIG application.
6
+ #
7
+ # _Note_: CsvMapper is an experimental class used only by the CaTissue::Extractor.
6
8
  class CsvMapper
7
9
  attr_reader :csvio, :classes
8
10
 
@@ -6,180 +6,198 @@ require 'faster_csv'
6
6
  require 'caruby/util/options'
7
7
  require 'caruby/util/collection'
8
8
 
9
- # CsvIO reads or writes CSV records.
10
- # This class wraps a FasterCSV with the following modifications:
11
- # * relax the date parser to allow dd/mm/yyyy dates
12
- # * don't convert integer text with a leading zero to an octal number
13
- # * allow one custom converter with different semantics: if the converter block
14
- # call returns nil, then continue conversion, otherwise return the converter
15
- # result. This differs from FasterCSV converter semantics which calls converters
16
- # as long the result == the input field value. The CsvIO converter semantics
17
- # supports converters that intend a String result to be the converted result.
18
- #
19
- # CsvIO is Enumerable, but does not implement the complete Ruby IO interface.
20
- class CsvIO
21
- include Enumerable
22
-
23
- # Returns the CSV field access header symbols.
24
- attr_reader :headers
25
-
26
- # Opens the CSV file and calls the given block with this CsvIO as the argument.
9
+ module CaRuby
10
+ # CsvIO reads or writes CSV records.
11
+ # This class wraps a FasterCSV with the following modifications:
12
+ # * relax the date parser to allow dd/mm/yyyy dates
13
+ # * don't convert integer text with a leading zero to an octal number
14
+ # * allow one custom converter with different semantics: if the converter block
15
+ # call returns nil, then continue conversion, otherwise return the converter
16
+ # result. This differs from FasterCSV converter semantics which calls converters
17
+ # as long the result == the input field value. The CsvIO converter semantics
18
+ # supports converters that intend a String result to be the converted result.
27
19
  #
28
- # @see #initialize the supported options
29
- def self.open(file, options=nil) # :yields: csvio
30
- csvio = self.new(file, options)
31
- if block_given? then
32
- yield csvio
33
- csvio.close
20
+ # CsvIO is Enumerable, but does not implement the complete Ruby IO interface.
21
+ class CsvIO
22
+ include Enumerable
23
+
24
+ # Returns the CSV field access header symbols.
25
+ attr_reader :headers
26
+
27
+ # Opens the CSV file and calls the given block with this CsvIO as the argument.
28
+ #
29
+ # @param (see #initialize)
30
+ # @option (see #initialize)
31
+ # @yield [csvio] the optional block to execute
32
+ # @yieldparam [CsvIO] csvio the open CSVIO instance
33
+ def self.open(file, opts=nil)
34
+ csvio = new(file, opts)
35
+ if block_given? then
36
+ yield csvio
37
+ csvio.close
38
+ end
34
39
  end
35
- end
36
-
37
- # #open the given CSV file and options, and call {#each} with the given block.
38
- def self.foreach(file, options=nil, &block) # :yields: record
39
- self.open(file, options=nil) { |csvio| csvio.each(&block) }
40
- end
41
-
42
- # Creates a new CsvIO for the specified source file.
43
- # If a converter block is given, then it is added to the CSV converters list.
44
- def initialize(file, options=nil, &converter)
45
- # the CSV file open mode
46
- mode = Options.get(:mode, options, "r")
47
- # the CSV headers option; can be boolean or array
48
- hdr_opt = Options.get(:headers, options)
49
- # there is a header record by default for an input CSV file
50
- hdr_opt ||= true if mode =~ /^r/
51
- # make parent directories if necessary for an output CSV file
52
- File.makedirs(File.dirname(file)) if mode =~ /^w/
53
- # if headers aren't given, then convert the input CSV header record names to underscore symbols
54
- hdr_cvtr = :symbol unless Enumerable === hdr_opt
55
- # make a custom converter
56
- custom = Proc.new { |f, info| convert(f, info, &converter) }
57
- # open the CSV file
58
- @csv = FasterCSV.open(file, mode, :headers => hdr_opt, :header_converters => hdr_cvtr, :return_headers => true, :write_headers => true, :converters => custom)
59
- # the header => field name hash:
60
- # if the header option is set to true, then read the input header line.
61
- # otherwise, parse an empty string which mimics an input header line.
62
- hdr_row = case hdr_opt
63
- when true then
40
+
41
+ # {#open}s the given CSV file and calls {#each} with the given block.
42
+ #
43
+ # @param (see #initialize)
44
+ # @option (see #initialize)
45
+ # @yield [row] the block to execute on the row
46
+ # @yieldparam [{Symbol => Object}] row the field symbol => value hash
47
+ def self.foreach(file, opts=nil, &block)
48
+ open(file, opts) { |csvio| csvio.each(&block) }
49
+ end
50
+
51
+ # Creates a new CsvIO for the specified source file.
52
+ # If a converter block is given, then it is added to the CSV converters list.
53
+ #
54
+ # @param [String] file the input CSV file to open
55
+ # @param [Hash] opts the open options
56
+ # @option opts [String] :mode the input mode (default +r+)
57
+ # @option opts [String] :headers the input field headers
58
+ # @yield [value, info] converts the input value
59
+ # @yieldparam [String] value the input value
60
+ # @yieldparam info the current field's FasterCSV FieldInfo metadata
61
+ def initialize(file, opts=nil, &converter)
62
+ # the CSV file open mode
63
+ mode = Options.get(:mode, opts, 'r')
64
+ # the CSV headers option; can be boolean or array
65
+ hdr_opt = Options.get(:headers, opts)
66
+ # there is a header record by default for an input CSV file
67
+ hdr_opt ||= true if mode =~ /^r/
68
+ # make parent directories if necessary for an output CSV file
69
+ File.makedirs(File.dirname(file)) if mode =~ /^w/
70
+ # if headers aren't given, then convert the input CSV header record names to underscore symbols
71
+ hdr_cvtr = :symbol unless Enumerable === hdr_opt
72
+ # make a custom converter
73
+ custom = Proc.new { |value, info| convert(value, info, &converter) }
74
+ # open the CSV file
75
+ @csv = FasterCSV.open(file, mode, :headers => hdr_opt, :header_converters => hdr_cvtr, :return_headers => true, :write_headers => true, :converters => custom)
76
+ # the header => field name hash:
77
+ # if the header option is set to true, then read the input header line.
78
+ # otherwise, parse an empty string which mimics an input header line.
79
+ hdr_row = case hdr_opt
80
+ when true then
81
+ @csv.shift
82
+ when Enumerable then
83
+ ''.parse_csv(:headers => hdr_opt, :header_converters => :symbol, :return_headers => true)
84
+ else
85
+ raise ArgumentError.new("CSV headers option value not supported: #{hdr_opt}")
86
+ end
87
+ # the header row headers
88
+ @headers = hdr_row.headers
89
+ # the header name => symbol map
90
+ @hdr_sym_hash = hdr_row.to_hash.invert
91
+ end
92
+
93
+ # Closes the CSV file and trash file if necessary.
94
+ def close
95
+ @csv.close
96
+ @trash.close if @trash
97
+ end
98
+
99
+ # Returns the header accessor method for the given input header name.
100
+ def accessor(header)
101
+ @hdr_sym_hash[header]
102
+ end
103
+
104
+ # Sets the trash output file. This creates a separate CSV output file distinct from the input CSV file.
105
+ # This is useful for writing rejected rows from the input. The output file has a header row.
106
+ def trash=(file)
107
+ @trash = FasterCSV.open(file, 'w', :headers => true, :header_converters => :symbol, :write_headers => true)
108
+ end
109
+
110
+ # Writes the row to the trash file if the trash file is set.
111
+ #
112
+ #@param [{Symbol => Object}] row the rejected input row
113
+ def reject(row)
114
+ @trash << row if @trash
115
+ end
116
+
117
+ # Iterates over each CSV row, yielding a row for each iteration.
118
+ # This method closes the CSV file after the iteration completes.
119
+ def each
120
+ begin
121
+ # parse each line
122
+ @csv.each { |row| yield row }
123
+ ensure
124
+ close
125
+ end
126
+ end
127
+
128
+ # @return the next CSV row
129
+ # @see #each
130
+ def read
64
131
  @csv.shift
65
- when Enumerable then
66
- ''.parse_csv(:headers => hdr_opt, :header_converters => :symbol, :return_headers => true)
67
- else
68
- raise ArgumentError.new("CSV headers option value not supported: #{hdr_opt}")
69
132
  end
70
- # the header row headers
71
- @headers = hdr_row.headers
72
- # the header name => symbol map
73
- @hdr_sym_hash = hdr_row.to_hash.invert
74
- end
75
-
76
- # Closes the CSV file and trash file if necessary.
77
- def close
78
- @csv.close
79
- @trash.close if @trash
80
- end
81
-
82
- # Returns the header accessor method for the given input header name.
83
- def accessor(header)
84
- @hdr_sym_hash[header]
85
- end
86
-
87
- # Sets the trash output file. This creates a separate CSV output file distinct from the input CSV file.
88
- # This is useful for writing rejected rows from the input. The output file has a header row.
89
- def trash=(file)
90
- @trash = FasterCSV.open(file, 'w', :headers => true, :header_converters => :symbol, :write_headers => true)
91
- end
92
-
93
- # Writes the row to the trash file if the trash file is set.
94
- #
95
- #@param [{Symbol => Object}] row the rejected input row
96
- def reject(row)
97
- @trash << row if @trash
98
- end
99
-
100
- # Iterates over each CSV row, yielding a row for each iteration.
101
- # This method closes the CSV file after the iteration completes.
102
- def each
103
- begin
104
- # parse each line
105
- @csv.each { |row| yield row }
106
- ensure
107
- close
133
+
134
+ alias :shift :read
135
+
136
+ # Writes the given row to the CSV file.
137
+ #
138
+ #@param [{Symbol => Object}] row the input row
139
+ def write(row)
140
+ @csv << row
108
141
  end
109
- end
110
-
111
- # @return the next CSV row
112
- # @see #each
113
- def read
114
- @csv.shift
115
- end
116
-
117
- alias :shift :read
118
-
119
- # Writes the given row to the CSV file.
120
- #
121
- #@param [{Symbol => Object}] row the input row
122
- def write(row)
123
- @csv << row
124
- end
125
-
126
- alias :<< :write
127
-
128
- private
129
-
130
- # 3-letter months => month sequence hash.
131
- MMM_MM_MAP = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'].to_compact_hash_with_index do |mmm, index|
132
- index < 9 ? ('0' + index.succ.to_s) : index.succ.to_s
133
- end
134
-
135
- # DateMatcher relaxes the FasterCSV DateMatcher to allow dd/mm/yyyy dates.
136
- DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | \d{1,2}-\w{3}-\d{2,4} | \d{4}[-\/]\d{1,2}[-\/]\d{1,2} | \d{1,2}[-\/]\d{1,2}[-\/]\d{2,4} )\z /x
137
-
138
- # @param f the input field value to convert
139
- # @param info the CSV field info
140
- # @return the converted value
141
- def convert(f, info)
142
- return if f.nil?
143
- # the block has precedence
144
- value = yield(f, info) if block_given?
145
- # integer conversion
146
- value ||= Integer(f) if f =~ /^[1-9]\d*$/
147
- # date conversion
148
- value ||= convert_date(f) if f =~ CsvIO::DateMatcher
149
- # float conversion
150
- value ||= (Float(f) rescue f) if f =~ /^\d+\.\d*$/ or f =~ /^\d*\.\d+$/
151
- # return converted value or the input field if there was no conversion
152
- value || f
153
- end
154
-
155
- # @param [String] the input field value
156
- # @return [Date] the converted date
157
- def convert_date(f)
158
- # If input value is in dd-mmm-yy format, then reformat.
159
- # Otherwise, parse as a Date if possible.
160
- if f =~ /^\d{1,2}-\w{3}-\d{2,4}$/ then
161
- ddmmyy = reformat_dd_mmm_yy_date(f) || return
162
- convert_date(ddmmyy)
163
- # elsif f =~ /^\w{3} \d{1,2}, \d{4}$/ then
164
- # ddmmyy = reformat_mmm_dd_yyyy_date(f) || return
165
- # convert_date(ddmmyy)
166
- else
167
- Date.parse(f, true) rescue nil
142
+
143
+ alias :<< :write
144
+
145
+ private
146
+
147
+ # 3-letter months => month sequence hash.
148
+ MMM_MM_MAP = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'].to_compact_hash_with_index do |mmm, index|
149
+ index < 9 ? ('0' + index.succ.to_s) : index.succ.to_s
168
150
  end
151
+
152
+ # DateMatcher relaxes the FasterCSV DateMatcher to allow dd/mm/yyyy dates.
153
+ DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | \d{1,2}-\w{3}-\d{2,4} | \d{4}[-\/]\d{1,2}[-\/]\d{1,2} | \d{1,2}[-\/]\d{1,2}[-\/]\d{2,4} )\z /x
154
+
155
+ # @param f the input field value to convert
156
+ # @param info the CSV field info
157
+ # @return the converted value
158
+ def convert(f, info)
159
+ return if f.nil?
160
+ # the block has precedence
161
+ value = yield(f, info) if block_given?
162
+ # integer conversion
163
+ value ||= Integer(f) if f =~ /^[1-9]\d*$/
164
+ # date conversion
165
+ value ||= convert_date(f) if f =~ CsvIO::DateMatcher
166
+ # float conversion
167
+ value ||= (Float(f) rescue f) if f =~ /^\d+\.\d*$/ or f =~ /^\d*\.\d+$/
168
+ # return converted value or the input field if there was no conversion
169
+ value || f
170
+ end
171
+
172
+ # @param [String] the input field value
173
+ # @return [Date] the converted date
174
+ def convert_date(f)
175
+ # If input value is in dd-mmm-yy format, then reformat.
176
+ # Otherwise, parse as a Date if possible.
177
+ if f =~ /^\d{1,2}-\w{3}-\d{2,4}$/ then
178
+ ddmmyy = reformat_dd_mmm_yy_date(f) || return
179
+ convert_date(ddmmyy)
180
+ # elsif f =~ /^\w{3} \d{1,2}, \d{4}$/ then
181
+ # ddmmyy = reformat_mmm_dd_yyyy_date(f) || return
182
+ # convert_date(ddmmyy)
183
+ else
184
+ Date.parse(f, true) rescue nil
185
+ end
186
+ end
187
+
188
+ # @param [String] the input field value in dd-mmm-yy format
189
+ # @return [String] the reformatted date String in mm/dd/yy format
190
+ def reformat_dd_mmm_yy_date(f)
191
+ all, dd, mmm, yy = /^(\d{1,2})-([[:alpha:]]{3})-(\d{2,4})$/.match(f).to_a
192
+ mm = MMM_MM_MAP[mmm.downcase] || return
193
+ "#{mm}/#{dd}/#{yy}"
194
+ end
195
+ # # @param [String] the input field value in 'mmmd d, yyyy' format
196
+ # # @return [String] the reformatted date String in mm/dd/yyyy format
197
+ # def reformat_mmm_dd_yyyy_date(f)
198
+ # all, mmm, dd, yyyy = /^(\w{3}) (\d{1,2}), (\d{4})$/.match(f).to_a
199
+ # mm = MMM_MM_MAP[mmm.downcase] || return
200
+ # "#{mm}/#{dd}/#{yyyy}"
201
+ # end
169
202
  end
170
-
171
- # @param [String] the input field value in dd-mmm-yy format
172
- # @return [String] the reformatted date String in mm/dd/yy format
173
- def reformat_dd_mmm_yy_date(f)
174
- all, dd, mmm, yy = /^(\d{1,2})-([[:alpha:]]{3})-(\d{2,4})$/.match(f).to_a
175
- mm = MMM_MM_MAP[mmm.downcase] || return
176
- "#{mm}/#{dd}/#{yy}"
177
- end
178
- # # @param [String] the input field value in 'mmmd d, yyyy' format
179
- # # @return [String] the reformatted date String in mm/dd/yyyy format
180
- # def reformat_mmm_dd_yyyy_date(f)
181
- # all, mmm, dd, yyyy = /^(\w{3}) (\d{1,2}), (\d{4})$/.match(f).to_a
182
- # mm = MMM_MM_MAP[mmm.downcase] || return
183
- # "#{mm}/#{dd}/#{yyyy}"
184
- # end
185
203
  end