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.
- checksums.yaml +4 -4
- data/README.md +19 -5
- data/bin/rocketjob_batch_perf +1 -1
- data/bin/rocketjob_perf +1 -1
- data/lib/rocket_job/batch.rb +3 -0
- data/lib/rocket_job/batch/categories.rb +338 -0
- data/lib/rocket_job/batch/io.rb +132 -69
- data/lib/rocket_job/batch/model.rb +20 -68
- data/lib/rocket_job/batch/performance.rb +20 -8
- data/lib/rocket_job/batch/statistics.rb +35 -13
- data/lib/rocket_job/batch/tabular.rb +2 -0
- data/lib/rocket_job/batch/tabular/input.rb +8 -6
- data/lib/rocket_job/batch/tabular/output.rb +4 -2
- data/lib/rocket_job/batch/throttle_running_workers.rb +8 -17
- data/lib/rocket_job/batch/worker.rb +27 -24
- data/lib/rocket_job/category/base.rb +78 -0
- data/lib/rocket_job/category/input.rb +110 -0
- data/lib/rocket_job/category/output.rb +25 -0
- data/lib/rocket_job/cli.rb +24 -16
- data/lib/rocket_job/dirmon_entry.rb +22 -12
- data/lib/rocket_job/event.rb +1 -1
- data/lib/rocket_job/extensions/iostreams/path.rb +32 -0
- data/lib/rocket_job/extensions/mongoid/factory.rb +4 -12
- data/lib/rocket_job/extensions/mongoid/stringified_symbol.rb +50 -0
- data/lib/rocket_job/extensions/psych/yaml_tree.rb +8 -0
- data/lib/rocket_job/jobs/dirmon_job.rb +1 -1
- data/lib/rocket_job/jobs/housekeeping_job.rb +7 -7
- data/lib/rocket_job/jobs/on_demand_batch_job.rb +15 -6
- data/lib/rocket_job/jobs/on_demand_job.rb +1 -2
- data/lib/rocket_job/jobs/performance_job.rb +3 -1
- data/lib/rocket_job/jobs/re_encrypt/relational_job.rb +5 -4
- data/lib/rocket_job/jobs/upload_file_job.rb +47 -10
- data/lib/rocket_job/lookup_collection.rb +68 -0
- data/lib/rocket_job/plugins/job/model.rb +25 -50
- data/lib/rocket_job/plugins/job/throttle_running_jobs.rb +12 -4
- data/lib/rocket_job/plugins/job/worker.rb +2 -7
- data/lib/rocket_job/plugins/restart.rb +12 -5
- data/lib/rocket_job/plugins/state_machine.rb +2 -1
- data/lib/rocket_job/ractor_worker.rb +42 -0
- data/lib/rocket_job/server/model.rb +1 -1
- data/lib/rocket_job/sliced.rb +36 -0
- data/lib/rocket_job/sliced/bzip2_output_slice.rb +43 -0
- data/lib/rocket_job/sliced/input.rb +4 -4
- data/lib/rocket_job/sliced/slice.rb +11 -13
- data/lib/rocket_job/sliced/slices.rb +20 -2
- data/lib/rocket_job/sliced/writer/output.rb +33 -44
- data/lib/rocket_job/subscribers/server.rb +1 -1
- data/lib/rocket_job/thread_worker.rb +46 -0
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +21 -55
- data/lib/rocket_job/worker_pool.rb +5 -7
- data/lib/rocketjob.rb +52 -59
- metadata +43 -33
- data/lib/rocket_job/extensions/mongoid/remove_warnings.rb +0 -12
- 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
|
data/lib/rocket_job/cli.rb
CHANGED
@@ -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",
|
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("-
|
247
|
-
|
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",
|
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",
|
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",
|
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]",
|
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]",
|
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]",
|
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]",
|
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]",
|
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]",
|
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]",
|
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:
|
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
|
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
|
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
|
-
|
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
|
data/lib/rocket_job/event.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|