duty_free 1.0.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.
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module DutyFree
5
+ module Util
6
+ # def self._parse(arel)
7
+ # arel = arel.arel if arel.is_a?(ActiveRecord::Relation)
8
+ # sels = arel.ast.cores.select { |x| x.is_a?(Arel::Nodes::SelectCore) }
9
+ # # source (joinsource) / projections (6) is the most interesting here
10
+ # sels.each_with_index do |sel, idx|
11
+ # puts "#{idx} ============="
12
+ # # Columns:
13
+ # sel.projections.map do |x|
14
+ # case
15
+ # when x.is_a?(Arel::Nodes::SqlLiteral)
16
+ # puts x.to_s
17
+ # else
18
+ # puts "#{x.class} #{x.name}"
19
+ # end
20
+ # end
21
+ # end
22
+ # nil
23
+ # end
24
+
25
+ def self._recurse_arel(piece, prefix = '')
26
+ names = []
27
+ # Our JOINs mashup of nested arrays and hashes
28
+ if piece.is_a?(Array)
29
+ names += piece.inject([]) { |s, v| s + _recurse_arel(v, prefix) }
30
+ elsif piece.is_a?(Hash)
31
+ names += piece.inject([]) do |s, v|
32
+ new_prefix = "#{prefix}#{v.first}_"
33
+ s << new_prefix
34
+ s + _recurse_arel(v.last, new_prefix)
35
+ end
36
+
37
+ # ActiveRecord AREL objects
38
+ elsif piece.is_a?(Arel::Nodes::JoinSource)
39
+ # The left side is the "FROM" table
40
+ # names += _recurse_arel(piece.left)
41
+ # The right side is an array of all JOINs
42
+ names += piece.right.inject([]) { |s, v| s + _recurse_arel(v) }
43
+ elsif piece.is_a?(Arel::Nodes::Join) # INNER or OUTER JOIN
44
+ # The left side is the "JOIN" table
45
+ names += _recurse_arel(piece.left)
46
+ # (The right side of these is the "ON" clause)
47
+ elsif piece.is_a?(Arel::Table) # Table
48
+ names << piece.name
49
+ elsif piece.is_a?(Arel::Nodes::TableAlias) # Alias
50
+ # Can get the real table name from: self._recurse_arel(piece.left)
51
+ names << piece.right.to_s # This is simply a string; the alias name itself
52
+ end
53
+ names
54
+ end
55
+
56
+ def self._prefix_join(prefixes, separator = nil)
57
+ prefixes.reject(&:blank?).join(separator || '.')
58
+ end
59
+
60
+ def self._clean_name(name, import_columns_as)
61
+ return name if name.is_a?(Symbol)
62
+
63
+ # Expand aliases
64
+ (import_columns_as || []).each do |k, v|
65
+ if (k[-1] == ' ' && name.start_with?(k)) || name == k
66
+ name.replace(v + name[k.length..-1])
67
+ break
68
+ end
69
+ end
70
+ name
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module DutyFree
5
+ module VERSION
6
+ MAJOR = 1
7
+ MINOR = 0
8
+ TINY = 0
9
+
10
+ # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
+ PRE = nil
12
+
13
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.').freeze
14
+
15
+ def self.to_s
16
+ STRING
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Generates (but does not run) a migration to add a versions table.
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/active_record'
5
+
6
+ module DutyFree
7
+ # Installs DutyFree in a rails app.
8
+ class InstallGenerator < ::Rails::Generators::Base
9
+ include ::Rails::Generators::Migration
10
+
11
+ # Class names of MySQL adapters.
12
+ # - `MysqlAdapter` - Used by gems: `mysql`, `activerecord-jdbcmysql-adapter`.
13
+ # - `Mysql2Adapter` - Used by `mysql2` gem.
14
+ MYSQL_ADAPTERS = [
15
+ 'ActiveRecord::ConnectionAdapters::MysqlAdapter',
16
+ 'ActiveRecord::ConnectionAdapters::Mysql2Adapter'
17
+ ].freeze
18
+
19
+ source_root File.expand_path('templates', __dir__)
20
+ class_option(
21
+ :with_changes,
22
+ type: :boolean,
23
+ default: false,
24
+ desc: 'Store changeset (diff) with each version'
25
+ )
26
+
27
+ desc 'Generates (but does not run) a migration to add a versions table.' \
28
+ ' Also generates an initializer file for configuring DutyFree'
29
+
30
+ def create_migration_file
31
+ add_duty_free_migration('create_versions')
32
+ add_duty_free_migration('add_object_changes_to_versions') if options.with_changes?
33
+ end
34
+
35
+ def self.next_migration_number(dirname)
36
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
37
+ end
38
+
39
+ protected
40
+
41
+ def add_duty_free_migration(template)
42
+ migration_dir = File.expand_path('db/migrate')
43
+ if self.class.migration_exists?(migration_dir, template)
44
+ ::Kernel.warn "Migration already exists: #{template}"
45
+ else
46
+ migration_template(
47
+ "#{template}.rb.erb",
48
+ "db/migrate/#{template}.rb",
49
+ item_type_options: item_type_options,
50
+ migration_version: migration_version,
51
+ versions_table_options: versions_table_options
52
+ )
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # MySQL 5.6 utf8mb4 limit is 191 chars for keys used in indexes.
59
+ def item_type_options
60
+ opt = { null: false }
61
+ opt[:limit] = 191 if mysql?
62
+ ", #{opt}"
63
+ end
64
+
65
+ def migration_version
66
+ return unless (major = ActiveRecord::VERSION::MAJOR) >= 5
67
+
68
+ "[#{major}.#{ActiveRecord::VERSION::MINOR}]"
69
+ end
70
+
71
+ def mysql?
72
+ MYSQL_ADAPTERS.include?(ActiveRecord::Base.connection.class.name)
73
+ end
74
+
75
+ # Even modern versions of MySQL still use `latin1` as the default character
76
+ # encoding. Many users are not aware of this, and run into trouble when they
77
+ # try to use DutyFree in apps that otherwise tend to use UTF-8. Postgres, by
78
+ # comparison, uses UTF-8 except in the unusual case where the OS is configured
79
+ # with a custom locale.
80
+ #
81
+ # - https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html
82
+ # - http://www.postgresql.org/docs/9.4/static/multibyte.html
83
+ #
84
+ # Furthermore, MySQL's original implementation of UTF-8 was flawed, and had
85
+ # to be fixed later by introducing a new charset, `utf8mb4`.
86
+ #
87
+ # - https://mathiasbynens.be/notes/mysql-utf8mb4
88
+ # - https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
89
+ #
90
+ def versions_table_options
91
+ if mysql?
92
+ ', { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" }'
93
+ else
94
+ ''
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,12 @@
1
+ # This migration adds the optional `object_changes` column, in which DutyFree
2
+ # will store the `changes` diff for each update event. See the readme for
3
+ # details.
4
+ class AddObjectChangesToVersions < ActiveRecord::Migration<%= migration_version %>
5
+ # The largest text column available in all supported RDBMS.
6
+ # See `create_versions.rb` for details.
7
+ TEXT_BYTES = 1_073_741_823
8
+
9
+ def change
10
+ add_column :versions, :object_changes, :text, limit: TEXT_BYTES
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ # This migration creates the `versions` table, the only schema PT requires.
2
+ # All other migrations PT provides are optional.
3
+ class CreateVersions < ActiveRecord::Migration<%= migration_version %>
4
+
5
+ # The largest text column available in all supported RDBMS is
6
+ # 1024^3 - 1 bytes, roughly one gibibyte. We specify a size
7
+ # so that MySQL will use `longtext` instead of `text`. Otherwise,
8
+ # when serializing very large objects, `text` might not be big enough.
9
+ TEXT_BYTES = 1_073_741_823
10
+
11
+ def change
12
+ create_table :versions<%= versions_table_options %> do |t|
13
+ t.string :item_type<%= item_type_options %>
14
+ t.integer :item_id, null: false
15
+ t.string :event, null: false
16
+ t.string :whodunnit
17
+ t.text :object, limit: TEXT_BYTES
18
+
19
+ # Known issue in MySQL: fractional second precision
20
+ # -------------------------------------------------
21
+ #
22
+ # MySQL timestamp columns do not support fractional seconds unless
23
+ # defined with "fractional seconds precision". MySQL users should manually
24
+ # add fractional seconds precision to this migration, specifically, to
25
+ # the `created_at` column.
26
+ # (https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html)
27
+ #
28
+ # MySQL users should also upgrade to rails 4.2, which is the first
29
+ # version of ActiveRecord with support for fractional seconds in MySQL.
30
+ # (https://github.com/rails/rails/pull/14359)
31
+ #
32
+ t.datetime :created_at
33
+ end
34
+ add_index :versions, %i(item_type item_id)
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,257 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duty_free
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Lorin Thwaits
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: appraisal
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: byebug
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: ffaker
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.11'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.11'
75
+ - !ruby/object:Gem::Dependency
76
+ name: generator_spec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.9.4
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.9.4
89
+ - !ruby/object:Gem::Dependency
90
+ name: memory_profiler
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 0.9.14
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 0.9.14
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '13.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '13.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec-rails
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '4.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '4.0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.89.1
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 0.89.1
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop-rspec
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: 1.42.0
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: 1.42.0
159
+ - !ruby/object:Gem::Dependency
160
+ name: mysql2
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '0.5'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '0.5'
173
+ - !ruby/object:Gem::Dependency
174
+ name: pg
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0.18'
180
+ - - "<"
181
+ - !ruby/object:Gem::Version
182
+ version: '2.0'
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0.18'
190
+ - - "<"
191
+ - !ruby/object:Gem::Version
192
+ version: '2.0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: sqlite3
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: '1.4'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: '1.4'
207
+ description: |
208
+ An ActiveRecord extension that simplifies importing and exporting of data
209
+ stored in one or more models. Source and destination can be CSV, XLS,
210
+ XLSX, ODT, HTML tables, or simple Ruby arrays.
211
+ email: lorint@gmail.com
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - lib/duty_free.rb
217
+ - lib/duty_free/column.rb
218
+ - lib/duty_free/config.rb
219
+ - lib/duty_free/extensions.rb
220
+ - lib/duty_free/frameworks/cucumber.rb
221
+ - lib/duty_free/frameworks/rails.rb
222
+ - lib/duty_free/frameworks/rails/controller.rb
223
+ - lib/duty_free/frameworks/rails/engine.rb
224
+ - lib/duty_free/frameworks/rspec.rb
225
+ - lib/duty_free/serializers/json.rb
226
+ - lib/duty_free/serializers/yaml.rb
227
+ - lib/duty_free/suggest_template.rb
228
+ - lib/duty_free/util.rb
229
+ - lib/duty_free/version_number.rb
230
+ - lib/generators/duty_free/USAGE
231
+ - lib/generators/duty_free/install_generator.rb
232
+ - lib/generators/duty_free/templates/add_object_changes_to_versions.rb.erb
233
+ - lib/generators/duty_free/templates/create_versions.rb.erb
234
+ homepage: https://github.com/lorint/duty_free
235
+ licenses:
236
+ - MIT
237
+ metadata: {}
238
+ post_install_message:
239
+ rdoc_options: []
240
+ require_paths:
241
+ - lib
242
+ required_ruby_version: !ruby/object:Gem::Requirement
243
+ requirements:
244
+ - - ">="
245
+ - !ruby/object:Gem::Version
246
+ version: 2.4.0
247
+ required_rubygems_version: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: 1.3.6
252
+ requirements: []
253
+ rubygems_version: 3.0.8
254
+ signing_key:
255
+ specification_version: 4
256
+ summary: Import and Export Data
257
+ test_files: []