mongify 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.yardopts +3 -0
- data/CHANGELOG.rdoc +5 -0
- data/Gemfile.lock +52 -6
- data/LICENSE +1 -1
- data/README.rdoc +29 -11
- data/Rakefile +37 -9
- data/features/options.feature +2 -0
- data/features/print.feature +1 -1
- data/features/process.feature +10 -1
- data/features/step_definitions/process_steps.rb +11 -1
- data/features/support/env.rb +1 -1
- data/lib/mongify/cli/application.rb +7 -7
- data/lib/mongify/cli/command/worker.rb +18 -14
- data/lib/mongify/cli/options.rb +2 -1
- data/lib/mongify/configuration.rb +5 -5
- data/lib/mongify/database/base_connection.rb +6 -6
- data/lib/mongify/database/column.rb +40 -40
- data/lib/mongify/database/data_row.rb +9 -9
- data/lib/mongify/database/no_sql_connection.rb +61 -35
- data/lib/mongify/database/sql_connection.rb +44 -15
- data/lib/mongify/database/table.rb +62 -46
- data/lib/mongify/exceptions.rb +5 -5
- data/lib/mongify/progressbar.rb +15 -15
- data/lib/mongify/status.rb +8 -8
- data/lib/mongify/translation.rb +19 -17
- data/lib/mongify/translation/process.rb +16 -123
- data/lib/mongify/translation/processor_common.rb +132 -0
- data/lib/mongify/translation/sync.rb +112 -0
- data/lib/mongify/ui.rb +9 -9
- data/lib/mongify/version.rb +1 -1
- data/mongify.gemspec +4 -2
- data/spec/files/deleting_fields_from_embedding_parent_translation.rb +19 -0
- data/spec/files/embedded_parent_translation.rb +1 -1
- data/spec/mongify/cli/application_spec.rb +1 -1
- data/spec/mongify/cli/options_spec.rb +1 -1
- data/spec/mongify/cli/worker_command_spec.rb +46 -17
- data/spec/mongify/database/column_spec.rb +21 -21
- data/spec/mongify/database/data_row_spec.rb +11 -11
- data/spec/mongify/database/no_sql_connection_spec.rb +61 -27
- data/spec/mongify/database/sql_connection_spec.rb +62 -2
- data/spec/mongify/database/table_spec.rb +53 -29
- data/spec/mongify/translation/printer_spec.rb +2 -2
- data/spec/mongify/translation/process_spec.rb +50 -34
- data/spec/mongify/translation/sync_spec.rb +184 -0
- data/spec/mongify/translation_spec.rb +8 -8
- data/spec/mongify/ui_spec.rb +12 -12
- data/spec/mongify_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -1
- data/spec/support/config_reader.rb +2 -2
- data/spec/support/database_generator.rb +68 -25
- data/spec/support/database_output.txt +17 -0
- metadata +41 -6
data/lib/mongify/cli/options.rb
CHANGED
@@ -28,6 +28,7 @@ Examples:
|
|
28
28
|
#{progname} check database.config
|
29
29
|
#{progname} translation datbase.config > database_translation.rb
|
30
30
|
#{progname} process database.config database_translation.rb
|
31
|
+
#{progname} sync database.config database_translation.rb
|
31
32
|
|
32
33
|
See http://github.com/anlek/mongify for more details
|
33
34
|
|
@@ -85,4 +86,4 @@ EOB
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
end
|
88
|
-
end
|
89
|
+
end
|
@@ -6,7 +6,7 @@ module Mongify
|
|
6
6
|
class Configuration
|
7
7
|
class << self
|
8
8
|
attr_accessor :in_stream, :out_stream
|
9
|
-
|
9
|
+
|
10
10
|
# Parses a external configuration file and evaluates it and returns a instence of a configuration class
|
11
11
|
def parse(file_name)
|
12
12
|
raise Mongify::ConfigurationFileNotFound, "File #{file_name} is missing" unless File.exists?(file_name)
|
@@ -16,7 +16,7 @@ module Mongify
|
|
16
16
|
end
|
17
17
|
|
18
18
|
end #self
|
19
|
-
|
19
|
+
|
20
20
|
# Returns a no_sql_connection which is bound to a mongodb adapter
|
21
21
|
# or builds a new no_sql_connection if block is given
|
22
22
|
def mongodb_connection(options={}, &block)
|
@@ -25,7 +25,7 @@ module Mongify
|
|
25
25
|
options['adapter'] ||= 'mongodb'
|
26
26
|
@mongodb_connection = no_sql_connection(options, &block)
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# Returns a sql_connection
|
30
30
|
# If a block is given, it will be executed on the connection
|
31
31
|
# For more information, see {Mongify::Database::SqlConnection}
|
@@ -34,7 +34,7 @@ module Mongify
|
|
34
34
|
@sql_connection.instance_exec(&block) if block_given?
|
35
35
|
@sql_connection
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Returns a sql_connection
|
39
39
|
# If a block is given, it will be executed on the connection
|
40
40
|
# For more information, see {Mongify::Database::NoSqlConnection}
|
@@ -43,6 +43,6 @@ module Mongify
|
|
43
43
|
@no_sql_connection.instance_exec(&block) if block_given?
|
44
44
|
@no_sql_connection
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
end
|
48
48
|
end
|
@@ -8,10 +8,10 @@ module Mongify
|
|
8
8
|
# List of required fields to make a valid base connection
|
9
9
|
REQUIRED_FIELDS = %w{host}
|
10
10
|
# List of all the available fields to make up a connection
|
11
|
-
AVAILABLE_FIELDS = %w{adapter host username password database socket port encoding}
|
11
|
+
AVAILABLE_FIELDS = %w{adapter host username password database socket port encoding batch_size}
|
12
12
|
# List of all fields that should be forced to a string
|
13
13
|
STRING_FIELDS = %w{adapter}
|
14
|
-
|
14
|
+
|
15
15
|
def initialize(options=nil)
|
16
16
|
if options
|
17
17
|
options.stringify_keys!
|
@@ -20,7 +20,7 @@ module Mongify
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Returns all settings as a hash, this is used mainly in building ActiveRecord::Base.establish_connection
|
25
25
|
def to_hash
|
26
26
|
hash = {}
|
@@ -53,15 +53,15 @@ module Mongify
|
|
53
53
|
|
54
54
|
|
55
55
|
# Returns true if we are trying to respond_to AVAILABLE_FIELDS functions
|
56
|
-
def respond_to?(method, *args)
|
56
|
+
def respond_to?(method, *args)
|
57
57
|
return true if AVAILABLE_FIELDS.include?(method.to_s)
|
58
58
|
super(method)
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
# Building set and/or return functions for AVAILABLE_FIELDS.
|
62
62
|
# STRING_FIELDS are forced into string.
|
63
63
|
# Example:
|
64
|
-
#
|
64
|
+
#
|
65
65
|
# def host(value=nil)
|
66
66
|
# @host = value.to_s unless value.nil?
|
67
67
|
# @host
|
@@ -4,17 +4,17 @@ module Mongify
|
|
4
4
|
#
|
5
5
|
# A column that is used to access sql data and transform it into the no sql database
|
6
6
|
#
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# ==== Structure
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Structure for defining a column is as follows:
|
11
11
|
# column "name", :type, {options}
|
12
12
|
# <em>Columns with no type given will be set to <tt>:string</tt></em>
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# ==== Notes
|
15
15
|
# Leaving a column out when defining a table will result in a copy of the information (as a string).
|
16
16
|
# ==== Types
|
17
|
-
#
|
17
|
+
#
|
18
18
|
# Types of columns are supported:
|
19
19
|
# :key # Columns that are primary keys need to be marked as :key type. You can provide an :as if your :key is not an integer column
|
20
20
|
# :integer # Will be converted to a integer
|
@@ -28,42 +28,42 @@ module Mongify
|
|
28
28
|
# :time # Will be converted to a Time format (the date portion of the Time object will be 2000-01-01)
|
29
29
|
# :binary # Will be converted to a string
|
30
30
|
# :boolean # Will be converted to a true or false values
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# ==== Options
|
33
|
-
#
|
33
|
+
#
|
34
34
|
# column "post_id", :integer, :references => :posts # Referenced columns need to be marked as such, this will mean that they will be updated
|
35
35
|
# # with the new BSON::ObjectID.
|
36
36
|
# <b>NOTE: if you rename the table 'posts', you should set the :references to the new name</b>
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# column "name", :string, :ignore => true # Ignoring a column will make the column NOT copy over to the new database
|
39
|
-
#
|
39
|
+
#
|
40
40
|
# column "surname", :string, :rename_to => 'last_name'# Rename_to allows you to rename the column
|
41
41
|
#
|
42
42
|
# column "post_id", :integer, :auto_detect => true # Will run auto detect and make this column a :references => 'posts', :on => 'post_id' for you
|
43
43
|
# # More used when reading a sql database, NOT recommended for use during processing of translation
|
44
|
-
#
|
44
|
+
#
|
45
45
|
# <em>For decimal columns you can specify a few options:</em>
|
46
46
|
# column "total", # This is a default conversion setting.
|
47
47
|
# :decimal,
|
48
|
-
# :as => 'string'
|
49
|
-
#
|
48
|
+
# :as => 'string'
|
49
|
+
#
|
50
50
|
# column "total", # You can specify to convert your decimal to integer
|
51
51
|
# :decimal, # specifying scale will define how many decimal places to keep
|
52
52
|
# :as => 'integer', # Example: :scale => 2 will convert 123.4567 to 12346 in to mongodb
|
53
53
|
# :scale => 2
|
54
54
|
# ==== Decimal Storage
|
55
|
-
#
|
55
|
+
#
|
56
56
|
# Unfortunately MongoDB Ruby Drivers doesn't support BigDecimal, so to ensure all data is stored correctly (without losing information)
|
57
57
|
# I've chosen to store as String, however you can overwrite this functionality in one of two ways:
|
58
58
|
# <em>The reason you would want to do this, is to make this searchable via a query.</em>
|
59
|
-
#
|
59
|
+
#
|
60
60
|
# <b>1) You can specify :as => 'integer', :scale => 2</b>
|
61
61
|
# column "total", :decimal, :as => 'integer', :scale => 2
|
62
|
-
#
|
62
|
+
#
|
63
63
|
# #It would take a value of 123.456 and store it as an integer of value 12346
|
64
|
-
#
|
64
|
+
#
|
65
65
|
# <b>2) You can specify your own custom conversion by doing a {Mongify::Database::Table#before_save}
|
66
|
-
#
|
66
|
+
#
|
67
67
|
# Example:
|
68
68
|
# table "invoice" do
|
69
69
|
# column "name", :string
|
@@ -72,16 +72,16 @@ module Mongify
|
|
72
72
|
# row.total = (BigDecimal.new(row.total) * 1000).round
|
73
73
|
# end
|
74
74
|
# end
|
75
|
-
#
|
75
|
+
#
|
76
76
|
# This would take 123.456789 in the total column and convert it to an interger of value 123457 (and in your app you can convert it back to a decimal)
|
77
|
-
#
|
77
|
+
#
|
78
78
|
# *REMEMBER* there is a limit on how big of an integer you can store in BSON/MongoDB (http://bsonspec.org/#/specification)
|
79
79
|
class Column
|
80
80
|
attr_reader :sql_name, :type, :options
|
81
|
-
|
81
|
+
|
82
82
|
#List of available options for a column
|
83
83
|
AVAILABLE_OPTIONS = ['references', 'ignore', 'rename_to', 'as', 'scale']
|
84
|
-
|
84
|
+
|
85
85
|
# Auto detects if a column is an :key column or is a reference column
|
86
86
|
def self.auto_detect(column)
|
87
87
|
case column.sql_name.downcase
|
@@ -92,7 +92,7 @@ module Mongify
|
|
92
92
|
column.references = $1.to_s.pluralize unless column.referenced?
|
93
93
|
end
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
def initialize(sql_name, type=:string, options={})
|
97
97
|
@sql_name = sql_name
|
98
98
|
options, type = type, nil if type.is_a?(Hash)
|
@@ -100,21 +100,21 @@ module Mongify
|
|
100
100
|
@options = options.stringify_keys
|
101
101
|
@auto_detect = @options.delete('auto_detect')
|
102
102
|
run_auto_detect!
|
103
|
-
|
103
|
+
|
104
104
|
self
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
# Allows you to set a type
|
108
108
|
def type=(value=:string)
|
109
109
|
value = :string if value.nil?
|
110
110
|
@type = value.is_a?(Symbol) ? value : value.to_sym
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
# Returns the no_sql record name
|
114
114
|
def name
|
115
115
|
@name ||= rename_to || sql_name
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
# Returns a translated hash from a given value
|
119
119
|
# Example:
|
120
120
|
# @column = Column.new("surname", :string, :rename_to => 'last_name')
|
@@ -128,12 +128,12 @@ module Mongify
|
|
128
128
|
{"#{self.name}" => type_cast(value)}
|
129
129
|
end
|
130
130
|
end
|
131
|
-
|
131
|
+
|
132
132
|
# Returns a string representation of the column as it would show in a translation file.
|
133
133
|
# Mainly used during print out of translation file
|
134
134
|
def to_print
|
135
135
|
"column \"#{sql_name}\", :#{type}".tap do |output|
|
136
|
-
output_options = options.map do |k, v|
|
136
|
+
output_options = options.map do |k, v|
|
137
137
|
next if v.nil?
|
138
138
|
":#{k} => #{v.is_a?(Symbol) ? ":#{v}" : %Q["#{v}"] }"
|
139
139
|
end.compact
|
@@ -141,7 +141,7 @@ module Mongify
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
alias :to_s :to_print
|
144
|
-
|
144
|
+
|
145
145
|
# Sets up a accessor method for an option
|
146
146
|
#
|
147
147
|
# def rename_to=(value)
|
@@ -172,32 +172,32 @@ module Mongify
|
|
172
172
|
super(meth, *args, &blk)
|
173
173
|
end
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
# Returns true if the column is a reference column
|
177
177
|
def referenced?
|
178
178
|
!self.options['references'].nil?
|
179
179
|
end
|
180
|
-
|
180
|
+
|
181
181
|
# Returns true if column is being renamed
|
182
182
|
def renamed?
|
183
183
|
self.name != self.sql_name
|
184
184
|
end
|
185
|
-
|
185
|
+
|
186
186
|
# Returns true if column is a :key type column
|
187
187
|
def key?
|
188
188
|
self.type == :key
|
189
189
|
end
|
190
|
-
|
190
|
+
|
191
191
|
# Returns true if column should be auto_detected (passed via options)
|
192
192
|
def auto_detect?
|
193
193
|
!!@auto_detect
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
# Returns true if column is ignored
|
197
197
|
def ignored?
|
198
198
|
!!self.ignore
|
199
199
|
end
|
200
|
-
|
200
|
+
|
201
201
|
# Used when trying to figure out how to convert a decimal value
|
202
202
|
# @return [String] passed option['as'] or defaults to 'string'
|
203
203
|
def as
|
@@ -213,7 +213,7 @@ module Mongify
|
|
213
213
|
def as_integer?
|
214
214
|
self.as == :integer
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
# Get the scale option for decimal to integer conversion
|
218
218
|
# column 'total', :decimal, :as => 'integer', :scale => 3
|
219
219
|
# @return [integer] passed option['scale'] or 0
|
@@ -229,7 +229,7 @@ module Mongify
|
|
229
229
|
#######
|
230
230
|
private
|
231
231
|
#######
|
232
|
-
|
232
|
+
|
233
233
|
# Casts the value to a given type
|
234
234
|
def type_cast(value)
|
235
235
|
return nil if value.nil?
|
@@ -243,7 +243,7 @@ module Mongify
|
|
243
243
|
value = ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value)
|
244
244
|
if as_integer?
|
245
245
|
(value * (10 ** self.scale)).round.to_i
|
246
|
-
else
|
246
|
+
else
|
247
247
|
value.to_s
|
248
248
|
end
|
249
249
|
when :datetime then ActiveRecord::ConnectionAdapters::Column.string_to_time(value)
|
@@ -256,14 +256,14 @@ module Mongify
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
|
-
|
259
|
+
|
260
260
|
|
261
261
|
# runs auto detect (see {Mongify::Database::Column.auto_detect})
|
262
262
|
def run_auto_detect!
|
263
263
|
self.class.auto_detect(self) if auto_detect?
|
264
264
|
end
|
265
|
-
|
266
|
-
|
265
|
+
|
266
|
+
|
267
267
|
end
|
268
268
|
end
|
269
269
|
end
|
@@ -6,28 +6,28 @@ module Mongify
|
|
6
6
|
hash = {} if hash.nil?
|
7
7
|
@hash = hash.dup.stringify_keys!
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
# See if a given key is included
|
11
11
|
def include?(key)
|
12
12
|
@hash.has_key?(key)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Deletes a given key from the object
|
16
16
|
def delete(key)
|
17
17
|
@hash.delete(key)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# Returns a list of available keys
|
21
21
|
def keys
|
22
22
|
@hash.keys
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# Outputs an hash
|
26
26
|
# This is used to write into the no sql database
|
27
27
|
def to_hash
|
28
28
|
@hash
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# Used to manually read an attribute
|
32
32
|
def read_attribute(key)
|
33
33
|
@hash[key.to_s]
|
@@ -36,18 +36,18 @@ module Mongify
|
|
36
36
|
def write_attribute(key, value)
|
37
37
|
@hash[key.to_s] = value
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# Passes Inspect onto the internal hash
|
41
41
|
def inspect
|
42
42
|
@hash.inspect
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Updated respond_to to return true if it's a key the hash
|
46
46
|
def respond_to?(method)
|
47
47
|
return true if @hash.has_key?(method.gsub('=', ''))
|
48
48
|
super(method)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
# Added the ability to read and write attributes in the hash
|
52
52
|
def method_missing(meth, *args, &blk)
|
53
53
|
match = meth.to_s.match(/^([a-zA-Z\_]+)(=|$)$/)
|
@@ -62,7 +62,7 @@ module Mongify
|
|
62
62
|
super(meth, *args, &blk)
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -3,15 +3,15 @@ module Mongify
|
|
3
3
|
module Database
|
4
4
|
#
|
5
5
|
# No Sql Connection configuration
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# Basic format should look something like this:
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# no_sql_connection {options} do
|
10
10
|
# adapter "mongodb"
|
11
11
|
# host "localhost"
|
12
12
|
# database "my_database"
|
13
13
|
# end
|
14
|
-
#
|
14
|
+
#
|
15
15
|
# Possible attributes:
|
16
16
|
# adapter
|
17
17
|
# host
|
@@ -19,106 +19,132 @@ module Mongify
|
|
19
19
|
# username
|
20
20
|
# password
|
21
21
|
# port
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# Options:
|
24
|
-
# :force => true # This will force a database drop before processing
|
24
|
+
# :force => true # This will force a database drop before processing
|
25
25
|
# <em>You're also able to set attributes via the options</em>
|
26
26
|
#
|
27
27
|
class NoSqlConnection < Mongify::Database::BaseConnection
|
28
28
|
include Mongo
|
29
|
-
|
30
|
-
|
29
|
+
|
30
|
+
|
31
31
|
#Required fields for a no sql connection
|
32
|
-
REQUIRED_FIELDS = %w{host database}
|
33
|
-
|
32
|
+
REQUIRED_FIELDS = %w{host database}
|
33
|
+
|
34
34
|
def initialize(options={})
|
35
35
|
super options
|
36
36
|
@options = options
|
37
|
-
adapter 'mongodb' if adapter.nil? || adapter ==
|
37
|
+
adapter 'mongodb' if adapter.nil? || adapter.downcase == "mongo"
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# Sets and/or returns a adapter
|
41
41
|
# It takes care of renaming adapter('mongo') to 'mongodb'
|
42
42
|
def adapter(name=nil)
|
43
|
-
name = 'mongodb' if name && name.to_s.downcase == 'mongo'
|
44
43
|
super(name)
|
45
44
|
end
|
46
|
-
|
45
|
+
|
47
46
|
# Returns a connection string that can be used to build a Mongo Connection
|
48
47
|
# (Currently this isn't used due to some issue early on in development)
|
49
48
|
def connection_string
|
50
49
|
"#{@adapter}://#{@host}#{":#{@port}" if @port}"
|
51
50
|
end
|
52
|
-
|
53
|
-
# Returns true or false depending if the given attributes are present and valid to make up a
|
51
|
+
|
52
|
+
# Returns true or false depending if the given attributes are present and valid to make up a
|
54
53
|
# connection to a mongo server
|
55
54
|
def valid?
|
56
55
|
super && @database.present?
|
57
56
|
end
|
58
|
-
|
57
|
+
|
59
58
|
# Returns true if :force was set to true
|
60
59
|
# This will force a drop of the database upon connection
|
61
60
|
def forced?
|
62
61
|
!!@options['force']
|
63
62
|
end
|
64
|
-
|
63
|
+
|
65
64
|
# Sets up a connection to the database
|
66
65
|
def setup_connection_adapter
|
67
66
|
connection = Connection.new(host, port)
|
68
67
|
connection.add_auth(database, username, password) if username && password
|
69
68
|
connection
|
70
69
|
end
|
71
|
-
|
70
|
+
|
72
71
|
# Returns a mongo connection
|
73
72
|
# NOTE: If forced? is true, the first time a connection is made, it will ask to drop the
|
74
|
-
# database before continuing
|
73
|
+
# database before continuing
|
75
74
|
def connection
|
76
75
|
return @connection if @connection
|
77
76
|
@connection = setup_connection_adapter
|
78
77
|
@connection
|
79
78
|
end
|
80
|
-
|
79
|
+
|
81
80
|
# Returns true or false depending if we have a connection to a mongo server
|
82
81
|
def has_connection?
|
83
82
|
connection.connected?
|
84
83
|
end
|
85
|
-
|
84
|
+
|
86
85
|
# Returns the database from the connection
|
87
86
|
def db
|
88
87
|
@db ||= connection[database]
|
89
88
|
end
|
90
|
-
|
89
|
+
|
91
90
|
# Returns a hash of all the rows from the database of a given collection
|
92
91
|
def select_rows(collection)
|
93
92
|
db[collection].find
|
94
93
|
end
|
95
|
-
|
94
|
+
|
95
|
+
def select_by_query(collection, query)
|
96
|
+
db[collection].find(query)
|
97
|
+
end
|
98
|
+
|
96
99
|
# Inserts into the collection a given row
|
97
100
|
def insert_into(colleciton_name, row)
|
98
101
|
db[colleciton_name].insert(row)
|
99
102
|
end
|
100
|
-
|
103
|
+
|
101
104
|
# Updates a collection item with a given ID with the given attributes
|
102
105
|
def update(colleciton_name, id, attributes)
|
103
106
|
db[colleciton_name].update({"_id" => id}, attributes)
|
104
107
|
end
|
105
|
-
|
108
|
+
|
109
|
+
# Upserts into the collection a given row
|
110
|
+
def upsert(collection_name, row)
|
111
|
+
# We can't use the save method of the Mongo collection
|
112
|
+
# The reason is that it detects duplicates using _id
|
113
|
+
# but we should detect it using pre_mongified_id instead
|
114
|
+
# because in the case of sync, same rows are identified by their original sql ids
|
115
|
+
#
|
116
|
+
# db[collection_name].save(row)
|
117
|
+
|
118
|
+
if row.has_key?(:pre_mongified_id) || row.has_key?('pre_mongified_id')
|
119
|
+
id = row[:pre_mongified_id] || row['pre_mongified_id']
|
120
|
+
duplicate = find_one(collection_name, {"pre_mongified_id" => id})
|
121
|
+
if duplicate
|
122
|
+
update(collection_name, duplicate[:_id] || duplicate["_id"], row)
|
123
|
+
else
|
124
|
+
insert_into(collection_name, row)
|
125
|
+
end
|
126
|
+
else
|
127
|
+
# no pre_mongified_id, fallback to the upsert method of Mongo
|
128
|
+
db[collection_name].save(row)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
106
132
|
# Finds one item from a collection with the given query
|
107
133
|
def find_one(collection_name, query)
|
108
134
|
db[collection_name].find_one(query)
|
109
135
|
end
|
110
|
-
|
136
|
+
|
111
137
|
# Returns a row of a item from a given collection with a given pre_mongified_id
|
112
138
|
def get_id_using_pre_mongified_id(colleciton_name, pre_mongified_id)
|
113
139
|
db[colleciton_name].find_one('pre_mongified_id' => pre_mongified_id).try(:[], '_id')
|
114
140
|
end
|
115
|
-
|
141
|
+
|
116
142
|
# Removes pre_mongified_id from all records in a given collection
|
117
143
|
def remove_pre_mongified_ids(collection_name)
|
118
144
|
drop_mongified_index(collection_name)
|
119
145
|
db[collection_name].update({}, { '$unset' => { 'pre_mongified_id' => 1} }, :multi => true)
|
120
146
|
end
|
121
|
-
|
147
|
+
|
122
148
|
# Removes pre_mongified_id from collection
|
123
149
|
# @param [String] collection_name name of collection to remove the index from
|
124
150
|
# @return True if successful
|
@@ -126,13 +152,13 @@ module Mongify
|
|
126
152
|
def drop_mongified_index(collection_name)
|
127
153
|
db[collection_name].drop_index('pre_mongified_id_1') if db[collection_name].index_information.keys.include?("pre_mongified_id_1")
|
128
154
|
end
|
129
|
-
|
155
|
+
|
130
156
|
# Creates a pre_mongified_id index to ensure
|
131
157
|
# speedy lookup for collections via the pre_mongified_id
|
132
158
|
def create_pre_mongified_id_index(collection_name)
|
133
159
|
db[collection_name].create_index([['pre_mongified_id', Mongo::ASCENDING]])
|
134
160
|
end
|
135
|
-
|
161
|
+
|
136
162
|
# Asks user permission to drop the database
|
137
163
|
# @return true or false depending on user's response
|
138
164
|
def ask_to_drop_database
|
@@ -140,18 +166,18 @@ module Mongify
|
|
140
166
|
drop_database
|
141
167
|
end
|
142
168
|
end
|
143
|
-
|
169
|
+
|
144
170
|
#######
|
145
171
|
private
|
146
172
|
#######
|
147
|
-
|
173
|
+
|
148
174
|
# Drops the mongodb database
|
149
175
|
def drop_database
|
150
176
|
connection.drop_database(database)
|
151
177
|
end
|
152
|
-
|
153
178
|
|
154
|
-
|
179
|
+
|
180
|
+
|
155
181
|
end
|
156
182
|
end
|
157
|
-
end
|
183
|
+
end
|