rails_data_fix 0.1.1
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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.org +7 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +21 -0
- data/README.org +210 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/data_fix.gemspec +46 -0
- data/lib/data_fix/data_fix.rb +6 -0
- data/lib/data_fix/railtie.rb +7 -0
- data/lib/data_fix/version.rb +5 -0
- data/lib/data_fix.rb +6 -0
- data/lib/tasks/data_fix_tasks.rake +168 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9aecc5561ca42500f7eeac7f0c491994a2ec22bffe93ac3a562ec3b233c09bc0
|
4
|
+
data.tar.gz: 7649eb215c34e313ddda879feb54334f56f0d01d140cf799a06e082d6ea40b0c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b578010033aad671e725ee684ed7619a04c624d2ad39034749a670358e87373de4b402b741d74f26ff48f7cc3d403738116649cb29719824bc4ed0993e014b93
|
7
|
+
data.tar.gz: 5d5a8ec6b185644d1ba2ca2563e4a908fb574804c1c8982fb3af20fff99bec7b747fbee49ec4383e54c8faef93a25ff93fd46b72e126cdce86df8ec0bef4fb16
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.org
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
data_fix (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
diff-lcs (1.4.4)
|
11
|
+
parallel (1.20.1)
|
12
|
+
parser (3.0.2.0)
|
13
|
+
ast (~> 2.4.1)
|
14
|
+
rainbow (3.0.0)
|
15
|
+
rake (13.0.6)
|
16
|
+
regexp_parser (2.1.1)
|
17
|
+
rexml (3.2.5)
|
18
|
+
rspec (3.10.0)
|
19
|
+
rspec-core (~> 3.10.0)
|
20
|
+
rspec-expectations (~> 3.10.0)
|
21
|
+
rspec-mocks (~> 3.10.0)
|
22
|
+
rspec-core (3.10.1)
|
23
|
+
rspec-support (~> 3.10.0)
|
24
|
+
rspec-expectations (3.10.1)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.10.0)
|
27
|
+
rspec-mocks (3.10.2)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.10.0)
|
30
|
+
rspec-support (3.10.2)
|
31
|
+
rubocop (1.18.4)
|
32
|
+
parallel (~> 1.10)
|
33
|
+
parser (>= 3.0.0.0)
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
35
|
+
regexp_parser (>= 1.8, < 3.0)
|
36
|
+
rexml
|
37
|
+
rubocop-ast (>= 1.8.0, < 2.0)
|
38
|
+
ruby-progressbar (~> 1.7)
|
39
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
40
|
+
rubocop-ast (1.8.0)
|
41
|
+
parser (>= 3.0.1.1)
|
42
|
+
ruby-progressbar (1.11.0)
|
43
|
+
unicode-display_width (2.0.0)
|
44
|
+
|
45
|
+
PLATFORMS
|
46
|
+
x86_64-linux
|
47
|
+
|
48
|
+
DEPENDENCIES
|
49
|
+
data_fix!
|
50
|
+
rake (~> 13.0)
|
51
|
+
rspec (~> 3.0)
|
52
|
+
rubocop (~> 1.7)
|
53
|
+
|
54
|
+
BUNDLED WITH
|
55
|
+
2.2.19
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Adolfo Villafiorita
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.org
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#+TITLE: DataFix - Data Maintenance Tasks Manager
|
2
|
+
#+AUTHOR: Adolfo Villafiorita
|
3
|
+
|
4
|
+
Manage your data maintenance tasks like migrations.
|
5
|
+
|
6
|
+
* Introduction
|
7
|
+
|
8
|
+
This Rails gem provides a set of tasks to manage DB data maintenance
|
9
|
+
tasks like they were migrations.
|
10
|
+
|
11
|
+
Data maintenance tasks include anything which does not fit in a schema
|
12
|
+
migration, such as, for instance, adding new records in production,
|
13
|
+
fixing errors in existing records, migrating data to a new
|
14
|
+
schema, ...
|
15
|
+
|
16
|
+
Before we wrote =data_fix= we would create a rake tasks or a script
|
17
|
+
with the migration code, test the script in development and finally
|
18
|
+
run it in production. The process was highly manual, with no
|
19
|
+
information about which migrations were run and when. Although these
|
20
|
+
scripts are usually one-offs and lose their value once run, we were
|
21
|
+
not quite ok with the approach.
|
22
|
+
|
23
|
+
=data_fix= helps by enforcing standards and keeping track of the data
|
24
|
+
fix run.
|
25
|
+
|
26
|
+
Similar to Rails schema migrations, thus, =data_fix= provides:
|
27
|
+
|
28
|
+
- Tasks for generating time-stamped scripts, where you will put the
|
29
|
+
code you need to run on your data.=
|
30
|
+
- A table in your DBs to keep track of which scripts have been already
|
31
|
+
run
|
32
|
+
- Tasks to manage execution of the scripts and of the table of the
|
33
|
+
tasks run
|
34
|
+
- Automatic backup of your data before running the scripts
|
35
|
+
|
36
|
+
Different from schema migrations data_fix does **not** provide a
|
37
|
+
mechanism for data rollbacks. In fact writing reversible maintenance
|
38
|
+
scripts on data not only is complex, but also, in many cases,
|
39
|
+
pointless: why should you write the code to fix a typo in a record and
|
40
|
+
also that to reintroduce the typo you are fixing? It is also an
|
41
|
+
overkill, since it is much simpler rolling back to a previous version
|
42
|
+
using a backup.
|
43
|
+
|
44
|
+
We now use it at [[https://shair.tech][Shair.Tech]] to perform data cleaning and data updates
|
45
|
+
of our Rails apps.
|
46
|
+
|
47
|
+
* Installation
|
48
|
+
|
49
|
+
Add this line to your application's Gemfile:
|
50
|
+
|
51
|
+
#+begin_example ruby
|
52
|
+
gem 'rails_data_fix'
|
53
|
+
#+end_example
|
54
|
+
|
55
|
+
And then execute:
|
56
|
+
|
57
|
+
#+begin_example
|
58
|
+
$ bundle install
|
59
|
+
#+end_example
|
60
|
+
|
61
|
+
Or install it yourself as:
|
62
|
+
|
63
|
+
#+begin_example
|
64
|
+
$ gem install rails_data_fix
|
65
|
+
#+end_example
|
66
|
+
|
67
|
+
Than *for each environment and DB in which you want to use
|
68
|
+
=data_fix=* run the following command:
|
69
|
+
|
70
|
+
#+begin_example
|
71
|
+
rails data_fix:init
|
72
|
+
#+end_example
|
73
|
+
|
74
|
+
*This means that you need to run =RAILS_ENV=production rake
|
75
|
+
data_fix:init= in your production environment, if you want to use it
|
76
|
+
there.*
|
77
|
+
|
78
|
+
* Usage
|
79
|
+
|
80
|
+
First create a file and write the script:
|
81
|
+
|
82
|
+
#+begin_example sh
|
83
|
+
rails data_fix:create[data_fix_name]
|
84
|
+
[... write the script in the generated file ...]
|
85
|
+
#+end_example
|
86
|
+
|
87
|
+
Then, for each environment in which you need to run the script:
|
88
|
+
|
89
|
+
#+begin_example sh
|
90
|
+
rails data_fix:run
|
91
|
+
#+end_example
|
92
|
+
|
93
|
+
=data_fix= scripts are not atomic: if you interrupt a script, the DB
|
94
|
+
will be left in status which depends on the code you wrote and when
|
95
|
+
you interrupted the script. In a typical scenario only part your
|
96
|
+
record will have been updated/fixed.
|
97
|
+
|
98
|
+
* Testing
|
99
|
+
|
100
|
+
It is a good idea to test your scripts in development before running
|
101
|
+
them on the actual data.
|
102
|
+
|
103
|
+
You can run the same script multiple times on the DB either by
|
104
|
+
restoring the status from a backup or by using the =rollback= task,
|
105
|
+
which declares one or more migrations as not run.
|
106
|
+
|
107
|
+
For instance:
|
108
|
+
|
109
|
+
#+begin_example
|
110
|
+
rake db:run
|
111
|
+
[... ERROR! ... ]
|
112
|
+
[... FIX SCRIPT ...]
|
113
|
+
rake db:rollback
|
114
|
+
rake db:run
|
115
|
+
[... REPEAT ...]
|
116
|
+
#+end_example
|
117
|
+
|
118
|
+
* Example
|
119
|
+
|
120
|
+
A typical usage scenario is the following.
|
121
|
+
|
122
|
+
0. You realize you have been inconsistent in storing color names in
|
123
|
+
the =color= field of a table of your DB: some of your records use
|
124
|
+
the word =gray= while others use the British spelling =grey=.
|
125
|
+
|
126
|
+
1. You use =data_fix:create= to generate a file in =db/migrate-data=.
|
127
|
+
(The file will contain your data migration/maintenance script):
|
128
|
+
|
129
|
+
#+begin_example sh
|
130
|
+
rails data_fix:create[prefer_british_spelling]
|
131
|
+
#+end_example
|
132
|
+
|
133
|
+
The script generates a file whose name is along the lines of:
|
134
|
+
=db/migrate-data/20210730135129_prefer_british_over_american.rb=
|
135
|
+
|
136
|
+
2. You now write the code to fix your data in the file just created. For
|
137
|
+
instance something along the lines of:
|
138
|
+
|
139
|
+
#+begin_example sh
|
140
|
+
cat > db/migrate-data/20210730135129_prefer_british_over_american.rb
|
141
|
+
Color.where(name: "gray").each do |record|
|
142
|
+
record.color = "grey"
|
143
|
+
record.save
|
144
|
+
end
|
145
|
+
^D
|
146
|
+
#+end_example
|
147
|
+
|
148
|
+
3. You can test your script in development by running:
|
149
|
+
|
150
|
+
#+begin_example sh
|
151
|
+
rails data_fix:run
|
152
|
+
#+end_example
|
153
|
+
|
154
|
+
4. If you are unhappy, you can declare the data_fix as not run, fix
|
155
|
+
you script, and run it again:
|
156
|
+
|
157
|
+
#+begin_example sh
|
158
|
+
rails data_fix:rollback
|
159
|
+
#+end_example
|
160
|
+
|
161
|
+
#+begin_example sh
|
162
|
+
cat > db/migrate-data/20210730135129_prefer_british_over_american.rb
|
163
|
+
puts "I prefer a brute-force approach"
|
164
|
+
Color.all.each do |record|
|
165
|
+
record.color = "grey"
|
166
|
+
record.save
|
167
|
+
end
|
168
|
+
^D
|
169
|
+
#+end_example
|
170
|
+
|
171
|
+
#+begin_example sh
|
172
|
+
rails data_fix:run
|
173
|
+
#+end_example
|
174
|
+
|
175
|
+
#+begin_quote
|
176
|
+
Despite the name of the task, =data_fix:rollback= does not roll
|
177
|
+
back data: for that you need to reload from a DB. The
|
178
|
+
=data_fix:rollback= task updates the table in the DB declaring
|
179
|
+
the the latest =data_fix= has not yet been run.
|
180
|
+
#+end_quote
|
181
|
+
|
182
|
+
You repeat the steps above for any other data fix you need. When you
|
183
|
+
are ready, you can run all the migrations at once in production, with
|
184
|
+
the following command:
|
185
|
+
|
186
|
+
#+begin_example
|
187
|
+
RAILS_ENV=production rails data_fix:run
|
188
|
+
#+end_example
|
189
|
+
|
190
|
+
=data_fix= keeps track of the scripts it has already run ensuring the
|
191
|
+
script is not run twice.
|
192
|
+
|
193
|
+
|
194
|
+
* Development
|
195
|
+
|
196
|
+
To install this gem onto your local machine, run `bundle exec rake
|
197
|
+
install`. To release a new version, update the version number in
|
198
|
+
`version.rb`, and then run `bundle exec rake release`, which will
|
199
|
+
create a git tag for the version, push git commits and the created
|
200
|
+
tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
201
|
+
|
202
|
+
* Contributing
|
203
|
+
|
204
|
+
Bug reports and pull requests are welcome on GitHub at
|
205
|
+
https://github.com/shair.tech/data_fix.
|
206
|
+
|
207
|
+
* License
|
208
|
+
|
209
|
+
The gem is available as open source under the terms of the
|
210
|
+
[[https://opensource.org/licenses/MIT][MIT License]].
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "data_fix"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/data_fix.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/data_fix/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rails_data_fix"
|
7
|
+
spec.version = DataFix::VERSION
|
8
|
+
spec.authors = ["Adolfo Villafiorita"]
|
9
|
+
spec.email = ["adolfo@shair.tech"]
|
10
|
+
|
11
|
+
spec.summary = "Manage your data maintenance tasks like they were migrations"
|
12
|
+
spec.description = <<-EOS
|
13
|
+
This gem provides a set of commands to manage data maintenance scripts of a Rails application like migrations.
|
14
|
+
|
15
|
+
Each script has a timestamped name; a table in the DBs keeps track of
|
16
|
+
the scripts which have been run. Similar to migrations you can run
|
17
|
+
multiple scripts in the same session. DataFix keeps track of which
|
18
|
+
scripts have already run.
|
19
|
+
|
20
|
+
We use it at Shair.Tech to simplify testing of migration scripts.
|
21
|
+
EOS
|
22
|
+
spec.homepage = "https://ict4g.net/gitea/haoyun/data_fix.git"
|
23
|
+
spec.license = "MIT"
|
24
|
+
spec.required_ruby_version = ">= 2.4.0"
|
25
|
+
|
26
|
+
spec.metadata["allowed_push_host"] = "https://www.rubygems.org"
|
27
|
+
|
28
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
29
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
30
|
+
spec.metadata["changelog_uri"] = File.join spec.homepage, "CHANGELOG.org"
|
31
|
+
|
32
|
+
# Specify which files should be added to the gem when it is released.
|
33
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
34
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
35
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
36
|
+
end
|
37
|
+
spec.bindir = "exe"
|
38
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
# Uncomment to register a new dependency of your gem
|
42
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
43
|
+
|
44
|
+
# For more information and examples about making a new gem, checkout our
|
45
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
46
|
+
end
|
data/lib/data_fix.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
namespace :data_fix do
|
3
|
+
DATAFIX_DIR = File.join("db", "migrate-data")
|
4
|
+
|
5
|
+
def puts_and_log message, level = :info
|
6
|
+
puts "** #{message}"
|
7
|
+
logger = Rails.logger
|
8
|
+
logger.send(level) { |msg| "data_fix: #{message}" }
|
9
|
+
end
|
10
|
+
|
11
|
+
# strip characters and whitespace to create valid filenames, also lowercase
|
12
|
+
def sanitize_filename(name)
|
13
|
+
if(name.is_a? Integer)
|
14
|
+
return name.to_s
|
15
|
+
end
|
16
|
+
return name.tr(
|
17
|
+
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÑñÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
|
18
|
+
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
|
19
|
+
).downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '')
|
20
|
+
end
|
21
|
+
|
22
|
+
def exit_if_not_installed
|
23
|
+
if not ActiveRecord::Base.connection.table_exists? :data_fixes
|
24
|
+
puts_and_log "ERROR: it seems like data_fix:init has not been run yet", :error
|
25
|
+
exit(1)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Add a :data_fixes table to the DB (run the first time only)'
|
30
|
+
task :init => :environment do
|
31
|
+
unless ActiveRecord::Base.connection.table_exists? :data_fixes
|
32
|
+
ActiveRecord::Base.connection.create_table :data_fixes do |t|
|
33
|
+
t.string :name
|
34
|
+
t.timestamps
|
35
|
+
end
|
36
|
+
end
|
37
|
+
Dir.mkdir DATAFIX_DIR if not Dir.exists? DATAFIX_DIR
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Create a new data fix'
|
41
|
+
task :create, [:name] => :environment do |_, args|
|
42
|
+
exit_if_not_installed
|
43
|
+
|
44
|
+
time = DateTime.now.strftime("%Y%m%d%H%M%S")
|
45
|
+
f = File.new(File.join(DATAFIX_DIR, sanitize_filename("#{time}_#{args.name}.rb")), "w")
|
46
|
+
f.write("")
|
47
|
+
f.close
|
48
|
+
end
|
49
|
+
|
50
|
+
def backup_database dry_run
|
51
|
+
config = Rails.configuration.database_configuration[Rails.env]
|
52
|
+
|
53
|
+
puts_and_log "Backing up #{Rails.env} database"
|
54
|
+
case config["adapter"]
|
55
|
+
when "sqlite3"
|
56
|
+
db_name = config["database"]
|
57
|
+
backup_db_name = db_name.gsub(/\.sqlite3$/, "-#{Date.today.strftime('%Y-%m-%d')}.sqlite3")
|
58
|
+
cmd = "cp \"#{db_name}\" \"#{backup_db_name}\""
|
59
|
+
when "mysql2"
|
60
|
+
db_host = config["host"]
|
61
|
+
db_name = config["database"]
|
62
|
+
db_username = config["username"]
|
63
|
+
db_password = config["password"]
|
64
|
+
backup_db_name = "db/#{db_name}-#{Rails.env}-#{Date.today.strftime('%Y-%m-%d')}.sql"
|
65
|
+
cmd = "mysqldump -u #{db_name} -p #{db_password} #{db_name} > \"#{backup_db_name}\""
|
66
|
+
end
|
67
|
+
if dry_run
|
68
|
+
puts_and_log "WOULD RUN: #{cmd}"
|
69
|
+
else
|
70
|
+
system cmd
|
71
|
+
end
|
72
|
+
puts_and_log "backup performed and available as #{backup_db_name}."
|
73
|
+
end
|
74
|
+
|
75
|
+
def df_status
|
76
|
+
files = Dir.glob("*.rb", base: DATAFIX_DIR).sort
|
77
|
+
|
78
|
+
puts "** data_fix status"
|
79
|
+
printf "%3s %-60s %-10s\n", "run", "file in #{DATAFIX_DIR}", "when"
|
80
|
+
files.each do |file|
|
81
|
+
run = DataFix::DataFix.find_by(name: file)
|
82
|
+
printf "%-3s %-60s %-10s\n", run ? "Y" : "N", file, run ? run.created_at : ""
|
83
|
+
end
|
84
|
+
puts ""
|
85
|
+
end
|
86
|
+
|
87
|
+
def df_run dry_run = true, steps = nil, no_backup = false
|
88
|
+
df_status
|
89
|
+
|
90
|
+
files = Dir.glob("*.rb", base: DATAFIX_DIR).sort
|
91
|
+
already_run = DataFix::DataFix.all.map { |x| x.name }.sort
|
92
|
+
|
93
|
+
to_run = steps ? (files - already_run)[0..(steps.to_i - 1)] : (files - already_run)
|
94
|
+
puts_and_log "data fix to run: #{to_run.join(", ")}"
|
95
|
+
|
96
|
+
# if we are doing things for real, backup the DB, unless
|
97
|
+
# explicitly asked not to do it
|
98
|
+
backup_database(dry_run) unless no_backup
|
99
|
+
|
100
|
+
# sort filenames by date (same as sorting alphabetically, since
|
101
|
+
# the date is in the name
|
102
|
+
to_run.sort.each do |file|
|
103
|
+
puts_and_log "starting data migration '#{file}'"
|
104
|
+
if dry_run
|
105
|
+
puts_and_log "WOULD RUN: ${File.join(DATAFIX_DIR, file)}"
|
106
|
+
else
|
107
|
+
load File.join(DATAFIX_DIR, file)
|
108
|
+
DataFix::DataFix.create(name: file)
|
109
|
+
end
|
110
|
+
puts_and_log "done!"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc 'Dry run the required data fixes (STEP= to specify the optional number of steps)'
|
115
|
+
task dry_run: :environment do
|
116
|
+
exit_if_not_installed
|
117
|
+
df_run true, ENV["STEP"]
|
118
|
+
end
|
119
|
+
|
120
|
+
desc 'Run the required data fixes (STEP= to specify the optional number of steps)'
|
121
|
+
task run: :environment do
|
122
|
+
exit_if_not_installed
|
123
|
+
df_run false, ENV["STEP"]
|
124
|
+
end
|
125
|
+
|
126
|
+
desc 'Status: show which data fixes have been run'
|
127
|
+
task status: :environment do
|
128
|
+
exit_if_not_installed
|
129
|
+
df_status
|
130
|
+
end
|
131
|
+
|
132
|
+
desc 'Reconcile: declare that all data fixes have been run'
|
133
|
+
task reconcile: :environment do
|
134
|
+
exit_if_not_installed
|
135
|
+
|
136
|
+
DataFix::DataFix.destroy_all
|
137
|
+
|
138
|
+
files = Dir.glob("*.rb", base: DATAFIX_DIR).sort
|
139
|
+
files.each do |file|
|
140
|
+
DataFix::DataFix.create(name: file)
|
141
|
+
end
|
142
|
+
puts_and_log "all data fixes have now been *declared* as run"
|
143
|
+
end
|
144
|
+
|
145
|
+
desc 'Reconcile up to: declare that data fixes up to given filename (included) have been run'
|
146
|
+
task :reconcile_up_to, [:filename] => :environment do |task, args|
|
147
|
+
exit_if_not_installed
|
148
|
+
|
149
|
+
stop_file = args[:filename]
|
150
|
+
|
151
|
+
DataFix::DataFix.destroy_all
|
152
|
+
files = Dir.glob("*.rb", base: DATAFIX_DIR).sort
|
153
|
+
files.each do |file|
|
154
|
+
DataFix::DataFix.create(name: file)
|
155
|
+
exit if file == stop_file
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc 'Rollback: declare that the latest STEP data fixes have not been run (default 1)'
|
160
|
+
task rollback: :environment do
|
161
|
+
exit_if_not_installed
|
162
|
+
|
163
|
+
step = ENV["STEP"] || 1
|
164
|
+
step.times do
|
165
|
+
DataFix::DataFix.last.destroy
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_data_fix
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adolfo Villafiorita
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-30 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: " This gem provides a set of commands to manage data maintenance scripts
|
14
|
+
of a Rails application like migrations. \n\nEach script has a timestamped name;
|
15
|
+
a table in the DBs keeps track of\nthe scripts which have been run. Similar to
|
16
|
+
migrations you can run\nmultiple scripts in the same session. DataFix keeps track
|
17
|
+
of which\nscripts have already run.\n\nWe use it at Shair.Tech to simplify testing
|
18
|
+
of migration scripts.\n"
|
19
|
+
email:
|
20
|
+
- adolfo@shair.tech
|
21
|
+
executables: []
|
22
|
+
extensions: []
|
23
|
+
extra_rdoc_files: []
|
24
|
+
files:
|
25
|
+
- ".gitignore"
|
26
|
+
- ".rspec"
|
27
|
+
- ".rubocop.yml"
|
28
|
+
- CHANGELOG.org
|
29
|
+
- Gemfile
|
30
|
+
- Gemfile.lock
|
31
|
+
- LICENSE.txt
|
32
|
+
- README.org
|
33
|
+
- Rakefile
|
34
|
+
- bin/console
|
35
|
+
- bin/setup
|
36
|
+
- data_fix.gemspec
|
37
|
+
- lib/data_fix.rb
|
38
|
+
- lib/data_fix/data_fix.rb
|
39
|
+
- lib/data_fix/railtie.rb
|
40
|
+
- lib/data_fix/version.rb
|
41
|
+
- lib/tasks/data_fix_tasks.rake
|
42
|
+
homepage: https://ict4g.net/gitea/haoyun/data_fix.git
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata:
|
46
|
+
allowed_push_host: https://www.rubygems.org
|
47
|
+
homepage_uri: https://ict4g.net/gitea/haoyun/data_fix.git
|
48
|
+
source_code_uri: https://ict4g.net/gitea/haoyun/data_fix.git
|
49
|
+
changelog_uri: https://ict4g.net/gitea/haoyun/data_fix.git/CHANGELOG.org
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 2.4.0
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubygems_version: 3.0.3
|
66
|
+
signing_key:
|
67
|
+
specification_version: 4
|
68
|
+
summary: Manage your data maintenance tasks like they were migrations
|
69
|
+
test_files: []
|