rocketjob 5.3.3 → 6.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -5
  3. data/bin/rocketjob_batch_perf +1 -1
  4. data/bin/rocketjob_perf +1 -1
  5. data/lib/rocket_job/batch.rb +3 -0
  6. data/lib/rocket_job/batch/categories.rb +338 -0
  7. data/lib/rocket_job/batch/io.rb +132 -69
  8. data/lib/rocket_job/batch/model.rb +20 -68
  9. data/lib/rocket_job/batch/performance.rb +20 -8
  10. data/lib/rocket_job/batch/statistics.rb +35 -13
  11. data/lib/rocket_job/batch/tabular.rb +2 -0
  12. data/lib/rocket_job/batch/tabular/input.rb +8 -6
  13. data/lib/rocket_job/batch/tabular/output.rb +4 -2
  14. data/lib/rocket_job/batch/throttle_running_workers.rb +8 -17
  15. data/lib/rocket_job/batch/worker.rb +27 -24
  16. data/lib/rocket_job/category/base.rb +78 -0
  17. data/lib/rocket_job/category/input.rb +110 -0
  18. data/lib/rocket_job/category/output.rb +25 -0
  19. data/lib/rocket_job/cli.rb +24 -16
  20. data/lib/rocket_job/dirmon_entry.rb +22 -12
  21. data/lib/rocket_job/event.rb +1 -1
  22. data/lib/rocket_job/extensions/iostreams/path.rb +32 -0
  23. data/lib/rocket_job/extensions/mongoid/factory.rb +4 -12
  24. data/lib/rocket_job/extensions/mongoid/stringified_symbol.rb +50 -0
  25. data/lib/rocket_job/extensions/psych/yaml_tree.rb +8 -0
  26. data/lib/rocket_job/jobs/dirmon_job.rb +1 -1
  27. data/lib/rocket_job/jobs/housekeeping_job.rb +7 -7
  28. data/lib/rocket_job/jobs/on_demand_batch_job.rb +15 -6
  29. data/lib/rocket_job/jobs/on_demand_job.rb +1 -2
  30. data/lib/rocket_job/jobs/performance_job.rb +3 -1
  31. data/lib/rocket_job/jobs/re_encrypt/relational_job.rb +5 -4
  32. data/lib/rocket_job/jobs/upload_file_job.rb +47 -10
  33. data/lib/rocket_job/lookup_collection.rb +68 -0
  34. data/lib/rocket_job/plugins/job/model.rb +25 -50
  35. data/lib/rocket_job/plugins/job/throttle_running_jobs.rb +12 -4
  36. data/lib/rocket_job/plugins/job/worker.rb +2 -7
  37. data/lib/rocket_job/plugins/restart.rb +12 -5
  38. data/lib/rocket_job/plugins/state_machine.rb +2 -1
  39. data/lib/rocket_job/ractor_worker.rb +42 -0
  40. data/lib/rocket_job/server/model.rb +1 -1
  41. data/lib/rocket_job/sliced.rb +36 -0
  42. data/lib/rocket_job/sliced/bzip2_output_slice.rb +43 -0
  43. data/lib/rocket_job/sliced/input.rb +4 -4
  44. data/lib/rocket_job/sliced/slice.rb +11 -13
  45. data/lib/rocket_job/sliced/slices.rb +20 -2
  46. data/lib/rocket_job/sliced/writer/output.rb +33 -44
  47. data/lib/rocket_job/subscribers/server.rb +1 -1
  48. data/lib/rocket_job/thread_worker.rb +46 -0
  49. data/lib/rocket_job/version.rb +1 -1
  50. data/lib/rocket_job/worker.rb +21 -55
  51. data/lib/rocket_job/worker_pool.rb +5 -7
  52. data/lib/rocketjob.rb +52 -59
  53. metadata +43 -33
  54. data/lib/rocket_job/extensions/mongoid/remove_warnings.rb +0 -12
  55. data/lib/rocket_job/jobs/on_demand_batch_tabular_job.rb +0 -28
@@ -0,0 +1,78 @@
1
+ require "active_support/concern"
2
+
3
+ module RocketJob
4
+ module Category
5
+ # Define the layout for each category of input or output data
6
+ module Base
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ field :name, type: ::Mongoid::StringifiedSymbol, default: :main
11
+
12
+ # Whether to compress, encrypt, or use the bzip2 serialization for data in this category.
13
+ field :serializer, type: ::Mongoid::StringifiedSymbol, default: :compress
14
+ validates_inclusion_of :serializer, in: [:none, :compress, :encrypt, :bzip2]
15
+
16
+ # The header columns when the file does not include a header row.
17
+ # Note:
18
+ # - All column names must be strings so that it can be serialized into MongoDB.
19
+ field :columns, type: Array
20
+
21
+ # On an input collection `format` specifies the format of the input data so that it can be
22
+ # transformed into a Hash when passed into the `#perform` method.
23
+ #
24
+ # On an output collection `format` specifies the format to transform the output hash into.
25
+ #
26
+ # `:auto` it uses the `file_name` on this category to determine the format.
27
+ # `nil` no transformation is performed on the data returned by the `#perform` method.
28
+ # Any other format supported by IOStreams, for example: csv, :hash, :array, :json, :psv, :fixed
29
+ #
30
+ # Default: `nil`
31
+ field :format, type: ::Mongoid::StringifiedSymbol
32
+ validates_inclusion_of :format, in: [nil, :auto] + IOStreams::Tabular.registered_formats
33
+
34
+ # Any specialized format specific options. For example, `:fixed` format requires a `:layout`.
35
+ field :format_options, type: Hash
36
+
37
+ # When `:format` is not supplied the file name can be used to infer the required format.
38
+ # Optional.
39
+ # Default: nil
40
+ field :file_name, type: IOStreams::Path
41
+ end
42
+
43
+ # Return which slice serializer class to use that matches the current options.
44
+ def serializer_class
45
+ case serializer
46
+ when :none
47
+ Sliced::Slice
48
+ when :compress
49
+ Sliced::CompressedSlice
50
+ when :encrypt
51
+ Sliced::EncryptedSlice
52
+ when :bzip2
53
+ Sliced::BZip2OutputSlice
54
+ else
55
+ raise(ArgumentError, "serialize: #{serializer.inspect} must be :none, :compress, :encrypt, or :bzip2")
56
+ end
57
+ end
58
+
59
+ def tabular
60
+ @tabular ||= IOStreams::Tabular.new(
61
+ columns: columns,
62
+ format: format == :auto ? nil : format,
63
+ format_options: format_options&.deep_symbolize_keys,
64
+ file_name: file_name
65
+ )
66
+ end
67
+
68
+ def reset_tabular
69
+ @tabular = nil
70
+ end
71
+
72
+ # Returns [true|false] whether this category has the attributes defined for tabular to work.
73
+ def tabular?
74
+ format.present?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,110 @@
1
+ module RocketJob
2
+ module Category
3
+ # Define the layout for each category of input or output data
4
+ class Input
5
+ include SemanticLogger::Loggable
6
+ include Plugins::Document
7
+ include Category::Base
8
+
9
+ embedded_in :job, class_name: "RocketJob::Job", inverse_of: :input_categories
10
+
11
+ # Slice size for this input collection
12
+ field :slice_size, type: Integer, default: 100
13
+
14
+ #
15
+ # The fields below only apply if the field `format` has been set:
16
+ #
17
+
18
+ # List of columns to allow.
19
+ # Default: nil ( Allow all columns )
20
+ # Note:
21
+ # When supplied any columns that are rejected will be returned in the cleansed columns
22
+ # as nil so that they can be ignored during processing.
23
+ field :allowed_columns, type: Array
24
+
25
+ # List of columns that must be present, otherwise an Exception is raised.
26
+ field :required_columns, type: Array
27
+
28
+ # Whether to skip unknown columns in the uploaded file.
29
+ # Ignores any column that was not found in the `allowed_columns` list.
30
+ #
31
+ # false:
32
+ # Raises IOStreams::Tabular::InvalidHeader when a column is supplied that is not in `allowed_columns`.
33
+ # true:
34
+ # Ignore additional columns in a file that are not listed in `allowed_columns`
35
+ # Job processing will skip the additional columns entirely as if they were not supplied at all.
36
+ # A warning is logged with the names of the columns that were ignored.
37
+ # The `columns` field will list all skipped columns with a nil value so that downstream workers
38
+ # know to ignore those columns.
39
+ #
40
+ # Notes:
41
+ # - Only applicable when `allowed_columns` has been set.
42
+ # - Recommended to leave as `false` otherwise a misspelled column can result in missed columns.
43
+ field :skip_unknown, type: ::Mongoid::Boolean, default: false
44
+ validates_inclusion_of :skip_unknown, in: [true, false]
45
+
46
+ # When `#upload` is called with a file_name, it uploads the file using any of the following approaches:
47
+ # :line
48
+ # Uploads the file a line (String) at a time for processing by workers.
49
+ # This is the default behavior and is the most performant since it leaves the parsing of each line
50
+ # up to the workers themselves.
51
+ # :array
52
+ # Parses each line from the file as an Array and uploads each array for processing by workers.
53
+ # Every line in the input file is parsed and converted into an array before uploading.
54
+ # This approach ensures that the entire files is valid before starting to process it.
55
+ # Ideal for when files may contain invalid lines.
56
+ # Not recommended for large files since the CSV or other parsing is performed sequentially during the
57
+ # upload process.
58
+ # :hash
59
+ # Parses each line from the file into a Hash and uploads each hash for processing by workers.
60
+ # Similar to :array above in that the entire file is parsed before processing is started.
61
+ # Slightly less efficient than :array since it stores every record as a hash with both the key and value.
62
+ #
63
+ # Recommend using :array when the entire file must be parsed/validated before processing is started, and
64
+ # upload time is not important.
65
+ # See IOStreams#each for more details.
66
+ field :mode, type: ::Mongoid::StringifiedSymbol, default: :line
67
+ validates_inclusion_of :mode, in: %i[line array hash]
68
+
69
+ # When reading tabular input data (e.g. CSV, PSV) the header is automatically cleansed.
70
+ # This removes issues when the input header varies in case and other small ways. See IOStreams::Tabular
71
+ # Currently Supported:
72
+ # :default
73
+ # Each column is cleansed as follows:
74
+ # - Leading and trailing whitespace is stripped.
75
+ # - All characters converted to lower case.
76
+ # - Spaces and '-' are converted to '_'.
77
+ # - All characters except for letters, digits, and '_' are stripped.
78
+ # :none
79
+ # Do not cleanse the columns names supplied in the header row.
80
+ #
81
+ # Note: Submit a ticket if you have other cleansers that you want added.
82
+ field :header_cleanser, type: ::Mongoid::StringifiedSymbol, default: :default
83
+ validates :header_cleanser, inclusion: %i[default none]
84
+
85
+ validates_presence_of :slice_size
86
+
87
+ # Cleanses the header column names when `cleanse_header` is true
88
+ def cleanse_header!
89
+ return unless header_cleanser == :default
90
+
91
+ ignored_columns = tabular.header.cleanse!
92
+ logger.warn("Stripped out invalid columns from custom header", ignored_columns) unless ignored_columns.empty?
93
+
94
+ self.columns = tabular.header.columns
95
+ end
96
+
97
+ def tabular
98
+ @tabular ||= IOStreams::Tabular.new(
99
+ columns: columns,
100
+ format: format == :auto ? nil : format,
101
+ format_options: format_options&.deep_symbolize_keys,
102
+ file_name: file_name,
103
+ allowed_columns: allowed_columns,
104
+ required_columns: required_columns,
105
+ skip_unknown: skip_unknown
106
+ )
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,25 @@
1
+ module RocketJob
2
+ module Category
3
+ # Define the layout for each category of input or output data
4
+ class Output
5
+ include SemanticLogger::Loggable
6
+ include Plugins::Document
7
+ include Category::Base
8
+
9
+ embedded_in :job, class_name: "RocketJob::Job", inverse_of: :output_categories
10
+
11
+ # Whether to skip nil values returned from the `perform` method.
12
+ # true: save nil values to the output categories.
13
+ # false: do not save nil values to the output categories.
14
+ field :nils, type: ::Mongoid::Boolean, default: false
15
+
16
+ # Renders [String] the header line.
17
+ # Returns [nil] if no header is needed.
18
+ def render_header
19
+ return if !tabular? || !tabular.requires_header?
20
+
21
+ tabular.render_header
22
+ end
23
+ end
24
+ end
25
+ end
@@ -240,17 +240,16 @@ module RocketJob
240
240
  o.on("-w", "--workers COUNT", "Number of workers (threads) to start") do |arg|
241
241
  @max_workers = arg.to_i
242
242
  end
243
- o.on("--include REGEXP", 'Limit this server to only those job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
243
+ o.on("--include REGEXP",
244
+ 'Limit this server to only those job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
244
245
  @include_filter = Regexp.new(arg, true)
245
246
  end
246
- o.on("-F", "--filter REGEXP", "DEPRECATED. Use --include") do |arg|
247
- warn "-F and --filter are deprecated, use --include"
248
- @include_filter = Regexp.new(arg, true)
249
- end
250
- o.on("-E", "--exclude REGEXP", 'Prevent this server from working on any job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
247
+ o.on("-E", "--exclude REGEXP",
248
+ 'Prevent this server from working on any job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
251
249
  @exclude_filter = Regexp.new(arg, true)
252
250
  end
253
- o.on("-W", "--where JSON", "Limit this server instance to the supplied mongo query filter. Supply as a string in JSON format. Example: '{\"priority\":{\"$lte\":25}}'") do |arg|
251
+ o.on("-W", "--where JSON",
252
+ "Limit this server instance to the supplied mongo query filter. Supply as a string in JSON format. Example: '{\"priority\":{\"$lte\":25}}'") do |arg|
254
253
  @where_filter = JSON.parse(arg)
255
254
  end
256
255
  o.on("-q", "--quiet", "Do not write to stdout, only to logfile. Necessary when running as a daemon") do
@@ -259,7 +258,8 @@ module RocketJob
259
258
  o.on("-d", "--dir DIR", "Directory containing Rails app, if not current directory") do |arg|
260
259
  @directory = arg
261
260
  end
262
- o.on("-e", "--environment ENVIRONMENT", "The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)") do |arg|
261
+ o.on("-e", "--environment ENVIRONMENT",
262
+ "The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)") do |arg|
263
263
  @environment = arg
264
264
  end
265
265
  o.on("-l", "--log_level trace|debug|info|warn|error|fatal", "The log level to use") do |arg|
@@ -274,38 +274,46 @@ module RocketJob
274
274
  o.on("-m", "--mongo MONGO_CONFIG_FILE_NAME", "Path and filename of config file. Default: config/mongoid.yml") do |arg|
275
275
  @mongo_config = arg
276
276
  end
277
- o.on("-s", "--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME", "Path and filename of Symmetric Encryption config file. Default: config/symmetric-encryption.yml") do |arg|
277
+ o.on("-s", "--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME",
278
+ "Path and filename of Symmetric Encryption config file. Default: config/symmetric-encryption.yml") do |arg|
278
279
  @symmetric_encryption_config = arg
279
280
  end
280
- o.on("--list [FILTER]", "List active servers. Supply either an exact server name or a partial name as a filter.") do |filter|
281
+ o.on("--list [FILTER]",
282
+ "List active servers. Supply either an exact server name or a partial name as a filter.") do |filter|
281
283
  @quiet = true
282
284
  @server = false
283
285
  @list_servers = filter || :all
284
286
  end
285
- o.on("--refresh [SECONDS]", "When listing active servers, update the list by this number of seconds. Defaults to every 1 second.") do |seconds|
287
+ o.on("--refresh [SECONDS]",
288
+ "When listing active servers, update the list by this number of seconds. Defaults to every 1 second.") do |seconds|
286
289
  @refresh = (seconds || 1).to_s.to_f
287
290
  end
288
- o.on("--stop [SERVER_NAME]", "Send event to stop a server once all in-process workers have completed. Optionally supply the complete or partial name of the server(s) to stop. Default: All servers.") do |server_name|
291
+ o.on("--stop [SERVER_NAME]",
292
+ "Send event to stop a server once all in-process workers have completed. Optionally supply the complete or partial name of the server(s) to stop. Default: All servers.") do |server_name|
289
293
  @quiet = true
290
294
  @server = false
291
295
  @stop_server = server_name || :all
292
296
  end
293
- o.on("--kill [SERVER_NAME]", "Send event to hard kill a server. Optionally supply the complete or partial name of the server(s) to kill. Default: All servers.") do |server_name|
297
+ o.on("--kill [SERVER_NAME]",
298
+ "Send event to hard kill a server. Optionally supply the complete or partial name of the server(s) to kill. Default: All servers.") do |server_name|
294
299
  @quiet = true
295
300
  @server = false
296
301
  @kill_server = server_name || :all
297
302
  end
298
- o.on("--pause [SERVER_NAME]", "Send event to pause a server. Optionally supply the complete or partial name of the server(s) to pause. Default: All servers.") do |server_name|
303
+ o.on("--pause [SERVER_NAME]",
304
+ "Send event to pause a server. Optionally supply the complete or partial name of the server(s) to pause. Default: All servers.") do |server_name|
299
305
  @quiet = true
300
306
  @server = false
301
307
  @pause_server = server_name || :all
302
308
  end
303
- o.on("--resume [SERVER_NAME]", "Send event to resume a server. Optionally supply the complete or partial name of the server(s) to resume. Default: All servers.") do |server_name|
309
+ o.on("--resume [SERVER_NAME]",
310
+ "Send event to resume a server. Optionally supply the complete or partial name of the server(s) to resume. Default: All servers.") do |server_name|
304
311
  @quiet = true
305
312
  @server = false
306
313
  @resume_server = server_name || :all
307
314
  end
308
- o.on("--dump [SERVER_NAME]", "Send event for a server to send a worker thread dump to its log file. Optionally supply the complete or partial name of the server(s). Default: All servers.") do |server_name|
315
+ o.on("--dump [SERVER_NAME]",
316
+ "Send event for a server to send a worker thread dump to its log file. Optionally supply the complete or partial name of the server(s). Default: All servers.") do |server_name|
309
317
  @quiet = true
310
318
  @server = false
311
319
  @thread_dump = server_name || :all
@@ -57,20 +57,12 @@ module RocketJob
57
57
  # If this DirmonEntry is in the failed state, exception contains the cause
58
58
  embeds_one :exception, class_name: "RocketJob::JobException"
59
59
 
60
- # The maximum number of files that should ever match during a single poll of the pattern.
61
- #
62
- # Too many files could be as a result of an invalid pattern specification.
63
- # Exceeding this number will result in an exception being logged in a failed Dirmon instance.
64
- # Dirmon processing will continue with new instances.
65
- # TODO: Implement max_hits
66
- # field :max_hits, type: Integer, default: 100
67
-
68
60
  #
69
61
  # Read-only attributes
70
62
  #
71
63
 
72
64
  # Current state, as set by the state machine. Do not modify directly.
73
- field :state, type: Symbol, default: :pending
65
+ field :state, type: Mongoid::StringifiedSymbol, default: :pending
74
66
 
75
67
  # Unique index on pattern to help prevent two entries from scanning the same files
76
68
  index({pattern: 1}, background: true, unique: true)
@@ -240,7 +232,7 @@ module RocketJob
240
232
  job_class_name: job_class_name,
241
233
  properties: properties,
242
234
  description: "#{name}: #{iopath.basename}",
243
- upload_file_name: archive_path.to_s,
235
+ upload_file_name: archive_path,
244
236
  original_file_name: iopath.to_s,
245
237
  job_id: job_id
246
238
  )
@@ -249,7 +241,7 @@ module RocketJob
249
241
  message: "Created RocketJob::Jobs::UploadFileJob",
250
242
  payload: {
251
243
  dirmon_entry_name: name,
252
- upload_file_name: archive_path.to_s,
244
+ upload_file_name: archive_path,
253
245
  original_file_name: iopath.to_s,
254
246
  job_class_name: job_class_name,
255
247
  job_id: job_id.to_s,
@@ -295,7 +287,25 @@ module RocketJob
295
287
  properties.each_pair do |k, _v|
296
288
  next if klass.public_method_defined?("#{k}=".to_sym)
297
289
 
298
- errors.add(:properties, "Unknown Property: Attempted to set a value for #{k.inspect} which is not allowed on the job #{job_class_name}")
290
+ if %i[output_categories input_categories].include?(k)
291
+ category_class = k == :input_categories ? RocketJob::Category::Input : RocketJob::Category::Output
292
+ properties[k].each do |category|
293
+ category.each_pair do |key, _value|
294
+ next if category_class.public_method_defined?("#{key}=".to_sym)
295
+
296
+ errors.add(
297
+ :properties,
298
+ "Unknown Property in #{k}: Attempted to set a value for #{key}.#{k} which is not allowed on the job #{job_class_name}"
299
+ )
300
+ end
301
+ end
302
+ next
303
+ end
304
+
305
+ errors.add(
306
+ :properties,
307
+ "Unknown Property: Attempted to set a value for #{k.inspect} which is not allowed on the job #{job_class_name}"
308
+ )
299
309
  end
300
310
  end
301
311
  end
@@ -35,7 +35,7 @@ module RocketJob
35
35
  # :shutdown
36
36
  # :pause
37
37
  # :updated
38
- field :action, type: Symbol
38
+ field :action, type: Mongoid::StringifiedSymbol
39
39
 
40
40
  # Hash Parameters to be sent with the event (event specific).
41
41
  field :parameters, type: Hash
@@ -0,0 +1,32 @@
1
+ module IOStreams
2
+ class Path
3
+ # Converts an object of this instance into a database friendly value.
4
+ def mongoize
5
+ to_s
6
+ end
7
+
8
+ # Get the object as it was stored in the database, and instantiate
9
+ # this custom class from it.
10
+ def self.demongoize(object)
11
+ return if object.nil?
12
+
13
+ IOStreams.new(object)
14
+ end
15
+
16
+ # Takes any possible object and converts it to how it would be
17
+ # stored in the database.
18
+ def self.mongoize(object)
19
+ return if object.nil?
20
+
21
+ object.to_s
22
+ end
23
+
24
+ # Converts the object that was supplied to a criteria and converts it
25
+ # into a database friendly form.
26
+ def self.evolve(object)
27
+ return if object.nil?
28
+
29
+ object.to_s
30
+ end
31
+ end
32
+ end
@@ -3,18 +3,10 @@ require "mongoid/factory"
3
3
  module RocketJob
4
4
  # Don't convert to Mongoid::Factory since it conflicts with Mongoid use.
5
5
  module MongoidFactory
6
- if Mongoid::VERSION.to_f >= 7.1
7
- def from_db(klass, attributes = nil, criteria = nil, selected_fields = nil)
8
- obj = super(klass, attributes, criteria, selected_fields)
9
- obj.collection_name = criteria.collection_name if criteria
10
- obj
11
- end
12
- else
13
- def from_db(klass, attributes = nil, criteria = nil)
14
- obj = super(klass, attributes, criteria)
15
- obj.collection_name = criteria.collection_name if criteria
16
- obj
17
- end
6
+ def from_db(klass, attributes = nil, criteria = nil, selected_fields = nil)
7
+ obj = super(klass, attributes, criteria, selected_fields)
8
+ obj.collection_name = criteria.collection_name if criteria
9
+ obj
18
10
  end
19
11
  end
20
12
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A class which sends values to the database as Strings but returns them to the user as Symbols.
4
+ module Mongoid
5
+ class StringifiedSymbol
6
+ class << self
7
+ # Convert the object from its mongo friendly ruby type to this type.
8
+ #
9
+ # @example Demongoize the object.
10
+ # Symbol.demongoize(object)
11
+ #
12
+ # @param [ Object ] object The object to demongoize.
13
+ #
14
+ # @return [ Symbol ] The object.
15
+ #
16
+ # @api private
17
+ def demongoize(object)
18
+ if object.nil?
19
+ object
20
+ else
21
+ object.to_s.to_sym
22
+ end
23
+ end
24
+
25
+ # Turn the object from the ruby type we deal with to a Mongo friendly
26
+ # type.
27
+ #
28
+ # @example Mongoize the object.
29
+ # Symbol.mongoize("123.11")
30
+ #
31
+ # @param [ Object ] object The object to mongoize.
32
+ #
33
+ # @return [ Symbol ] The object mongoized.
34
+ #
35
+ # @api private
36
+ def mongoize(object)
37
+ if object.nil?
38
+ object
39
+ else
40
+ object.to_s
41
+ end
42
+ end
43
+
44
+ # @api private
45
+ def evolve(object)
46
+ mongoize(object)
47
+ end
48
+ end
49
+ end
50
+ end