brick 0.1.0 → 1.0.2

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.
data/lib/brick.rb ADDED
@@ -0,0 +1,528 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/version'
4
+
5
+ # ActiveRecord before 4.0 didn't have #version
6
+ unless ActiveRecord.respond_to?(:version)
7
+ module ActiveRecord
8
+ def self.version
9
+ ::Gem::Version.new(ActiveRecord::VERSION::STRING)
10
+ end
11
+ end
12
+ end
13
+
14
+ # In ActiveSupport older than 5.0, the duplicable? test tries to new up a BigDecimal,
15
+ # and Ruby 2.6 and later deprecates #new. This removes the warning from BigDecimal.
16
+ require 'bigdecimal'
17
+ if (ruby_version = ::Gem::Version.new(RUBY_VERSION)) >= ::Gem::Version.new('2.6') &&
18
+ ActiveRecord.version < ::Gem::Version.new('5.0')
19
+ def BigDecimal.new(*args, **kwargs)
20
+ BigDecimal(*args, **kwargs)
21
+ end
22
+ end
23
+
24
+ # Allow ActiveRecord 4.0 and 4.1 to work with newer Ruby (>= 2.4) by avoiding a "stack level too deep"
25
+ # error when ActiveSupport tries to smarten up Numeric by messing with Fixnum and Bignum at the end of:
26
+ # activesupport-4.0.13/lib/active_support/core_ext/numeric/conversions.rb
27
+ if ActiveRecord.version < ::Gem::Version.new('4.2') &&
28
+ ActiveRecord.version > ::Gem::Version.new('3.2') &&
29
+ Object.const_defined?('Integer') && Integer.superclass.name == 'Numeric'
30
+ class OurFixnum < Integer; end
31
+ Numeric.const_set('Fixnum', OurFixnum)
32
+ class OurBignum < Integer; end
33
+ Numeric.const_set('Bignum', OurBignum)
34
+ end
35
+
36
+ # Allow ActiveRecord < 3.2 to run with newer versions of Psych gem
37
+ if BigDecimal.respond_to?(:yaml_tag) && !BigDecimal.respond_to?(:yaml_as)
38
+ class BigDecimal
39
+ class <<self
40
+ alias yaml_as yaml_tag
41
+ end
42
+ end
43
+ end
44
+
45
+ require 'brick/util'
46
+
47
+ # Allow ActiveRecord < 3.2 to work with Ruby 2.7 and later
48
+ if ActiveRecord.version < ::Gem::Version.new('3.2') &&
49
+ ruby_version >= ::Gem::Version.new('2.7')
50
+ # Remove circular reference for "now"
51
+ ::Brick::Util._patch_require(
52
+ 'active_support/values/time_zone.rb', '/activesupport',
53
+ ' def parse(str, now=now)',
54
+ ' def parse(str, now=now())'
55
+ )
56
+ # Remove circular reference for "reflection" for ActiveRecord 3.1
57
+ if ActiveRecord.version >= ::Gem::Version.new('3.1')
58
+ ::Brick::Util._patch_require(
59
+ 'active_record/associations/has_many_association.rb', '/activerecord',
60
+ 'reflection = reflection)',
61
+ 'reflection = reflection())',
62
+ :HasManyAssociation # Make sure the path for this guy is available to be autoloaded
63
+ )
64
+ end
65
+ end
66
+
67
+ # puts ::Brick::Util._patch_require(
68
+ # 'cucumber/cli/options.rb', '/cucumber/cli/options', # /cli/options
69
+ # ' def extract_environment_variables',
70
+ # " def extract_environment_variables\n
71
+ # puts 'Patch test!'"
72
+ # ).inspect
73
+
74
+ # An ActiveRecord extension that uses INFORMATION_SCHEMA views to reflect on all
75
+ # tables and views in the database (just once at the time the database connection
76
+ # is first established), and then automatically creates models, controllers, views,
77
+ # and routes based on those available relations.
78
+ require 'brick/config'
79
+ require 'brick/frameworks/rails'
80
+ module Brick
81
+ class << self
82
+ # All tables and views (what Postgres calls "relations" including column and foreign key info)
83
+ def relations
84
+ connections = Brick.instance_variable_get(:@relations) ||
85
+ Brick.instance_variable_set(:@relations, (connections = {}))
86
+ # Key our list of relations for this connection off of the connection pool's object_id
87
+ (connections[ActiveRecord::Base.connection_pool.object_id] ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } })
88
+ end
89
+
90
+ # Switches Brick auto-models on or off, for all threads
91
+ # @api public
92
+ def enable_models=(value)
93
+ Brick.config.enable_models = value
94
+ end
95
+
96
+ # Returns `true` if Brick models are on, `false` otherwise. This affects all
97
+ # threads. Enabled by default.
98
+ # @api public
99
+ def enable_models?
100
+ !!Brick.config.enable_models
101
+ end
102
+
103
+ # Switches Brick auto-controllers on or off, for all threads
104
+ # @api public
105
+ def enable_controllers=(value)
106
+ Brick.config.enable_controllers = value
107
+ end
108
+
109
+ # Returns `true` if Brick controllers are on, `false` otherwise. This affects all
110
+ # threads. Enabled by default.
111
+ # @api public
112
+ def enable_controllers?
113
+ !!Brick.config.enable_controllers
114
+ end
115
+
116
+ # Switches Brick auto-views on or off, for all threads
117
+ # @api public
118
+ def enable_views=(value)
119
+ Brick.config.enable_views = value
120
+ end
121
+
122
+ # Returns `true` if Brick views are on, `false` otherwise. This affects all
123
+ # threads. Enabled by default.
124
+ # @api public
125
+ def enable_views?
126
+ !!Brick.config.enable_views
127
+ end
128
+
129
+ # Switches Brick auto-routes on or off, for all threads
130
+ # @api public
131
+ def enable_routes=(value)
132
+ Brick.config.enable_routes = value
133
+ end
134
+
135
+ # Returns `true` if Brick routes are on, `false` otherwise. This affects all
136
+ # threads. Enabled by default.
137
+ # @api public
138
+ def enable_routes?
139
+ !!Brick.config.enable_routes
140
+ end
141
+
142
+ # @api public
143
+ def skip_database_views=(value)
144
+ Brick.config.skip_database_views = value
145
+ end
146
+
147
+ # @api public
148
+ def exclude_tables=(value)
149
+ Brick.config.exclude_tables = value
150
+ end
151
+
152
+ # @api public
153
+ def metadata_columns=(value)
154
+ Brick.config.metadata_columns = value
155
+ end
156
+
157
+ # Additional table associations to use (Think of these as virtual foreign keys perhaps)
158
+ # @api public
159
+ def additional_references=(value)
160
+ Brick.config.additional_references = value
161
+ end
162
+
163
+
164
+ # Returns Brick's `::Gem::Version`, convenient for comparisons. This is
165
+ # recommended over `::Brick::VERSION::STRING`.
166
+ #
167
+ # @api public
168
+ def gem_version
169
+ ::Gem::Version.new(VERSION::STRING)
170
+ end
171
+
172
+ # Set the Brick serializer. This setting affects all threads.
173
+ # @api public
174
+ def serializer=(value)
175
+ Brick.config.serializer = value
176
+ end
177
+
178
+ # Get the Brick serializer used by all threads.
179
+ # @api public
180
+ def serializer
181
+ Brick.config.serializer
182
+ end
183
+
184
+ # Returns Brick's global configuration object, a singleton. These
185
+ # settings affect all threads.
186
+ # @api private
187
+ def config
188
+ @config ||= Brick::Config.instance
189
+ yield @config if block_given?
190
+ @config
191
+ end
192
+ alias configure config
193
+
194
+ def version
195
+ VERSION::STRING
196
+ end
197
+ end
198
+ end
199
+
200
+ require 'brick/extensions'
201
+ require 'brick/version_number'
202
+ # require 'brick/serializers/json'
203
+ # require 'brick/serializers/yaml'
204
+
205
+ require 'active_record'
206
+ # Major compatibility fixes for ActiveRecord < 4.2
207
+ # ================================================
208
+ ActiveSupport.on_load(:active_record) do
209
+ # rubocop:disable Lint/ConstantDefinitionInBlock
210
+ module ActiveRecord
211
+ class Base
212
+ unless respond_to?(:execute_sql)
213
+ class << self
214
+ def execute_sql(sql, *param_array)
215
+ param_array = param_array.first if param_array.length == 1 && param_array.first.is_a?(Array)
216
+ connection.execute(send(:sanitize_sql_array, [sql] + param_array))
217
+ end
218
+ end
219
+ end
220
+ end
221
+
222
+ # Rails < 4.0 cannot do #find_by, #find_or_create_by, or do #pluck on multiple columns, so here are the patches:
223
+ if version < ::Gem::Version.new('4.0')
224
+ # Normally find_by is in FinderMethods, which older AR doesn't have
225
+ module Calculations
226
+ def find_by(*args)
227
+ where(*args).limit(1).to_a.first
228
+ end
229
+
230
+ def find_or_create_by(attributes, &block)
231
+ find_by(attributes) || create(attributes, &block)
232
+ end
233
+
234
+ def pluck(*column_names)
235
+ column_names.map! do |column_name|
236
+ if column_name.is_a?(Symbol) && self.column_names.include?(column_name.to_s)
237
+ "#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
238
+ else
239
+ column_name
240
+ end
241
+ end
242
+
243
+ # Same as: if has_include?(column_names.first)
244
+ if eager_loading? || (includes_values.present? && (column_names.first || references_eager_loaded_tables?))
245
+ construct_relation_for_association_calculations.pluck(*column_names)
246
+ else
247
+ relation = clone # spawn
248
+ relation.select_values = column_names
249
+ result = if klass.connection.class.name.end_with?('::PostgreSQLAdapter')
250
+ rslt = klass.connection.execute(relation.arel.to_sql)
251
+ rslt.type_map =
252
+ @type_map ||= proc do
253
+ # This aliasing avoids the warning:
254
+ # "no type cast defined for type "numeric" with oid 1700. Please cast this type
255
+ # explicitly to TEXT to be safe for future changes."
256
+ PG::BasicTypeRegistry.alias_type(0, 'numeric', 'text') # oid 1700
257
+ PG::BasicTypeRegistry.alias_type(0, 'time', 'text') # oid 1083
258
+ PG::BasicTypeMapForResults.new(klass.connection.raw_connection)
259
+ end.call
260
+ rslt.to_a
261
+ elsif respond_to?(:bind_values)
262
+ klass.connection.select_all(relation.arel, nil, bind_values)
263
+ else
264
+ klass.connection.select_all(relation.arel.to_sql, nil)
265
+ end
266
+ if result.empty?
267
+ []
268
+ else
269
+ columns = result.first.keys.map do |key|
270
+ # rubocop:disable Style/SingleLineMethods Naming/MethodParameterName
271
+ klass.columns_hash.fetch(key) do
272
+ Class.new { def type_cast(v); v; end }.new
273
+ end
274
+ # rubocop:enable Style/SingleLineMethods Naming/MethodParameterName
275
+ end
276
+
277
+ result = result.map do |attributes|
278
+ values = klass.initialize_attributes(attributes).values
279
+
280
+ columns.zip(values).map do |column, value|
281
+ column.type_cast(value)
282
+ end
283
+ end
284
+ columns.one? ? result.map!(&:first) : result
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ unless Base.is_a?(Calculations)
291
+ class Base
292
+ class << self
293
+ delegate :pluck, :find_by, :find_or_create_by, to: :scoped
294
+ end
295
+ end
296
+ end
297
+
298
+ # ActiveRecord < 3.2 doesn't have initialize_attributes, used by .pluck()
299
+ unless AttributeMethods.const_defined?('Serialization')
300
+ class Base
301
+ class << self
302
+ def initialize_attributes(attributes, options = {}) #:nodoc:
303
+ serialized = (options.delete(:serialized) { true }) ? :serialized : :unserialized
304
+ # super(attributes, options)
305
+
306
+ serialized_attributes.each do |key, coder|
307
+ attributes[key] = Attribute.new(coder, attributes[key], serialized) if attributes.key?(key)
308
+ end
309
+
310
+ attributes
311
+ end
312
+ end
313
+ end
314
+ end
315
+
316
+ # This only gets added for ActiveRecord < 3.2
317
+ module Reflection
318
+ unless AssociationReflection.instance_methods.include?(:foreign_key)
319
+ class AssociationReflection < MacroReflection
320
+ alias foreign_key association_foreign_key
321
+ end
322
+ end
323
+ end
324
+
325
+ # ActiveRecord 3.1 and 3.2 didn't try to bring in &block for the .extending() convenience thing
326
+ # that smartens up scopes, and Ruby 2.7 complained loudly about just doing the magical "Proc.new"
327
+ # that historically would just capture the incoming block.
328
+ module QueryMethods
329
+ unless instance_method(:extending).parameters.include?([:block, :block])
330
+ # These first two lines used to be:
331
+ # def extending(*modules)
332
+ # modules << Module.new(&Proc.new) if block_given?
333
+
334
+ def extending(*modules, &block)
335
+ modules << Module.new(&block) if block_given?
336
+
337
+ return self if modules.empty?
338
+
339
+ relation = clone
340
+ relation.send(:apply_modules, modules.flatten)
341
+ relation
342
+ end
343
+ end
344
+ end
345
+
346
+ # Same kind of thing for ActiveRecord::Scoping::Default#default_scope
347
+ module Scoping
348
+ module Default
349
+ module ClassMethods
350
+ if instance_methods.include?(:default_scope) &&
351
+ !instance_method(:default_scope).parameters.include?([:block, :block])
352
+ # Fix for AR 3.2-5.1
353
+ def default_scope(scope = nil, &block)
354
+ scope = block if block_given?
355
+
356
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
357
+ raise ArgumentError,
358
+ 'Support for calling #default_scope without a block is removed. For example instead ' \
359
+ "of `default_scope where(color: 'red')`, please use " \
360
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
361
+ 'self.default_scope.)'
362
+ end
363
+
364
+ self.default_scopes += [scope]
365
+ end
366
+ end
367
+ end
368
+ end
369
+ end
370
+ end
371
+ end
372
+ # rubocop:enable Lint/ConstantDefinitionInBlock
373
+
374
+ # Rails < 4.2 is not innately compatible with Ruby 2.4 and later, and comes up with:
375
+ # "TypeError: Cannot visit Integer" unless we patch like this:
376
+ if ruby_version >= ::Gem::Version.new('2.4') &&
377
+ Arel::Visitors.const_defined?('DepthFirst') &&
378
+ !Arel::Visitors::DepthFirst.private_instance_methods.include?(:visit_Integer)
379
+ module Arel
380
+ module Visitors
381
+ class DepthFirst < Visitor
382
+ alias visit_Integer terminal
383
+ end
384
+
385
+ class Dot < Visitor
386
+ alias visit_Integer visit_String
387
+ end
388
+
389
+ class ToSql < Visitor
390
+ private
391
+
392
+ # ActiveRecord before v3.2 uses Arel < 3.x, which does not have Arel#literal.
393
+ unless private_instance_methods.include?(:literal)
394
+ def literal(obj)
395
+ obj
396
+ end
397
+ end
398
+ alias visit_Integer literal
399
+ end
400
+ end
401
+ end
402
+ end
403
+
404
+ unless DateTime.instance_methods.include?(:nsec)
405
+ class DateTime < Date
406
+ def nsec
407
+ (sec_fraction * 1_000_000_000).to_i
408
+ end
409
+ end
410
+ end
411
+
412
+ # First part of arel_table_type stuff:
413
+ # ------------------------------------
414
+ # (more found below)
415
+ # was: ActiveRecord.version >= ::Gem::Version.new('3.2') &&
416
+ if ActiveRecord.version < ::Gem::Version.new('5.0')
417
+ # Used by Util#_arel_table_type
418
+ module ActiveRecord
419
+ class Base
420
+ def self.arel_table
421
+ @arel_table ||= Arel::Table.new(table_name, arel_engine).tap do |x|
422
+ x.instance_variable_set(:@_arel_table_type, self)
423
+ end
424
+ end
425
+ end
426
+ end
427
+ end
428
+
429
+ include ::Brick::Extensions
430
+
431
+ unless ::Brick::Extensions::IS_AMOEBA
432
+ # Add amoeba-compatible support
433
+ module ActiveRecord
434
+ class Base
435
+ def self.amoeba(*args)
436
+ puts "Amoeba called from #{name} with #{args.inspect}"
437
+ end
438
+ end
439
+ end
440
+ end
441
+ end
442
+
443
+ # Do this earlier because stuff here gets mixed into JoinDependency::JoinAssociation and AssociationScope
444
+ if ActiveRecord.version < ::Gem::Version.new('5.0') && Object.const_defined?('PG::Connection')
445
+ # Avoid pg gem deprecation warning: "You should use PG::Connection, PG::Result, and PG::Error instead"
446
+ PGconn = PG::Connection
447
+ PGresult = PG::Result
448
+ PGError = PG::Error
449
+ end
450
+
451
+ # More arel_table_type stuff:
452
+ # ---------------------------
453
+ if ActiveRecord.version < ::Gem::Version.new('5.2')
454
+ # Specifically for AR 3.1 and 3.2 to avoid: "undefined method `delegate' for ActiveRecord::Reflection::ThroughReflection:Class"
455
+ require 'active_support/core_ext/module/delegation' if ActiveRecord.version < ::Gem::Version.new('4.0')
456
+ # Used by Util#_arel_table_type
457
+ # rubocop:disable Style/CommentedKeyword
458
+ module ActiveRecord
459
+ module Reflection
460
+ # AR < 4.0 doesn't know about join_table and derive_join_table
461
+ unless AssociationReflection.instance_methods.include?(:join_table)
462
+ class AssociationReflection < MacroReflection
463
+ def join_table
464
+ @join_table ||= options[:join_table] || derive_join_table
465
+ end
466
+
467
+ private
468
+
469
+ def derive_join_table
470
+ [active_record.table_name, klass.table_name].sort.join("\0").gsub(/^(.*[._])(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", '_')
471
+ end
472
+ end
473
+ end
474
+ end
475
+
476
+ module Associations
477
+ # Specific to AR 4.2 - 5.1:
478
+ if Associations.const_defined?('JoinDependency') && JoinDependency.private_instance_methods.include?(:table_aliases_for)
479
+ class JoinDependency
480
+ private
481
+
482
+ if ActiveRecord.version < ::Gem::Version.new('5.1') # 4.2 or 5.0
483
+ def table_aliases_for(parent, node)
484
+ node.reflection.chain.map do |reflection|
485
+ alias_tracker.aliased_table_for(
486
+ reflection.table_name,
487
+ table_alias_for(reflection, parent, reflection != node.reflection)
488
+ ).tap do |x|
489
+ # %%% Specific only to Rails 4.2 (and maybe 4.1?)
490
+ x = x.left if x.is_a?(Arel::Nodes::TableAlias)
491
+ y = reflection.chain.find { |c| c.table_name == x.name }
492
+ x.instance_variable_set(:@_arel_table_type, y.klass)
493
+ end
494
+ end
495
+ end
496
+ end
497
+ end
498
+ elsif Associations.const_defined?('JoinHelper') && JoinHelper.private_instance_methods.include?(:construct_tables)
499
+ module JoinHelper
500
+ private
501
+
502
+ # AR > 3.0 and < 4.2 (%%% maybe only < 4.1?) uses construct_tables like this:
503
+ def construct_tables
504
+ tables = []
505
+ chain.each do |reflection|
506
+ tables << alias_tracker.aliased_table_for(
507
+ table_name_for(reflection),
508
+ table_alias_for(reflection, reflection != self.reflection)
509
+ ).tap do |x|
510
+ x = x.left if x.is_a?(Arel::Nodes::TableAlias)
511
+ x.instance_variable_set(:@_arel_table_type, reflection.chain.find { |c| c.table_name == x.name }.klass)
512
+ end
513
+
514
+ next unless reflection.source_macro == :has_and_belongs_to_many
515
+
516
+ tables << alias_tracker.aliased_table_for(
517
+ (reflection.source_reflection || reflection).join_table,
518
+ table_alias_for(reflection, true)
519
+ )
520
+ end
521
+ tables
522
+ end
523
+ end
524
+ end
525
+ end
526
+ end # module ActiveRecord
527
+ # rubocop:enable Style/CommentedKeyword
528
+ end
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Modifies an existing model so that it includes an IMPORT_TEMPLATE.
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ # require 'rails/generators/active_record'
5
+
6
+ module Brick
7
+ class InstallGenerator < ::Rails::Generators::Base
8
+ # include ::Rails::Generators::Migration
9
+
10
+ source_root File.expand_path('templates', __dir__)
11
+ class_option(
12
+ :with_changes,
13
+ type: :boolean,
14
+ default: false,
15
+ desc: 'Store changeset (diff) with each version'
16
+ )
17
+
18
+ desc 'Generates an initializer file for configuring Brick'
19
+
20
+ def create_initializer_file
21
+ unless File.exists?(filename = 'config/initializers/brick.rb')
22
+ create_file filename, "# frozen_string_literal: true
23
+
24
+ # # Settings for the Brick gem
25
+ # # (By default this auto-creates models, controllers, views, and routes on-the-fly.)
26
+
27
+ # # Normally these all start out as being enabled, but can be selectively disabled:
28
+ # Brick.enable_routes = false
29
+ # Brick.enable_models = false
30
+ # Brick.enable_controllers = false
31
+ # Brick.enable_views = false
32
+
33
+ # # By default models are auto-created from database views, and set to be read-only. This can be skipped.
34
+ # Brick.skip_database_views = true
35
+
36
+ # # Any tables or views you'd like to skip when auto-creating models
37
+ # Brick.exclude_tables = ['custom_metadata', 'version_info']
38
+
39
+ # # Additional table references which are used to create has_many / belongs_to associations inside auto-created
40
+ # # models. (You can consider these to be \"virtual foreign keys\" if you wish)... You only have to add these
41
+ # # in cases where your database for some reason does not have foreign key constraints defined. Sometimes for
42
+ # # performance reasons or just out of sheer laziness these might be missing.
43
+ # # Each of these virtual foreign keys is defined as an array having three values:
44
+ # # foreign table name / foreign key column / primary table name.
45
+ # # (We boldly expect that the primary key identified by ActiveRecord on the primary table will be accurate,
46
+ # # usually this is \"id\" but there are some good smarts that are used in case some other column has been set
47
+ # # to be the primary key.
48
+ # Brick.additional_references = [['orders', 'customer_id', 'customer'],
49
+ # ['customer', 'region_id', 'regions']]
50
+
51
+ # # We normally don't consider the timestamp columns \"created_at\", \"updated_at\", and \"deleted_at\" to count when
52
+ # # finding tables which can serve as associative tables in an N:M association. That is, ones that can be a
53
+ # # part of a has_many :through association. If you want to use different exclusion columns than our defaults
54
+ # # then this setting resets that list. For instance, here is the override for the Sakila sample database:
55
+ # Brick.metadata_columns = ['last_updated']
56
+
57
+ # # If a default route is not supplied, Brick attempts to find the most \"central\" table and wires up the default
58
+ # # route to go to the :index action for what would be a controller for that table. You can specify any controller
59
+ # # name and action you wish in order to override this and have that be the default route when none other has been
60
+ # # specified in routes.rb or elsewhere. (Or just use an empty string in order to disable this behaviour.)
61
+ # Brick.default_route_fallback = 'customers' # This defaults to \"customers/index\"
62
+ # Brick.default_route_fallback = 'orders/outstanding' # Example of a non-RESTful route
63
+ # Brick.default_route_fallback = '' # Omits setting a default route in the absence of any other
64
+ "
65
+ end
66
+ end
67
+
68
+ # def create_migration_file
69
+ # add_brick_migration('create_versions')
70
+ # add_brick_migration('add_object_changes_to_versions') if options.with_changes?
71
+ # end
72
+
73
+ # def self.next_migration_number(dirname)
74
+ # ::ActiveRecord::Generators::Base.next_migration_number(dirname)
75
+ # end
76
+
77
+ protected
78
+
79
+ # def add_brick_migration(template)
80
+ # migration_dir = File.expand_path('db/migrate')
81
+ # if self.class.migration_exists?(migration_dir, template)
82
+ # ::Kernel.warn "Migration already exists: #{template}"
83
+ # else
84
+ # migration_template(
85
+ # "#{template}.rb.erb",
86
+ # "db/migrate/#{template}.rb",
87
+ # item_type_options: item_type_options,
88
+ # migration_version: migration_version,
89
+ # versions_table_options: versions_table_options
90
+ # )
91
+ # end
92
+ # end
93
+
94
+ private
95
+
96
+ # # MySQL 5.6 utf8mb4 limit is 191 chars for keys used in indexes.
97
+ # def item_type_options
98
+ # opt = { null: false }
99
+ # opt[:limit] = 191 if mysql?
100
+ # ", #{opt}"
101
+ # end
102
+
103
+ # def migration_version
104
+ # return unless (major = ActiveRecord::VERSION::MAJOR) >= 5
105
+
106
+ # "[#{major}.#{ActiveRecord::VERSION::MINOR}]"
107
+ # end
108
+
109
+ # # Class names of MySQL adapters.
110
+ # # - `MysqlAdapter` - Used by gems: `mysql`, `activerecord-jdbcmysql-adapter`.
111
+ # # - `Mysql2Adapter` - Used by `mysql2` gem.
112
+ # def mysql?
113
+ # [
114
+ # 'ActiveRecord::ConnectionAdapters::MysqlAdapter',
115
+ # 'ActiveRecord::ConnectionAdapters::Mysql2Adapter'
116
+ # ].freeze.include?(ActiveRecord::Base.connection.class.name)
117
+ # end
118
+
119
+ # # Even modern versions of MySQL still use `latin1` as the default character
120
+ # # encoding. Many users are not aware of this, and run into trouble when they
121
+ # # try to use Brick in apps that otherwise tend to use UTF-8. Postgres, by
122
+ # # comparison, uses UTF-8 except in the unusual case where the OS is configured
123
+ # # with a custom locale.
124
+ # #
125
+ # # - https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html
126
+ # # - http://www.postgresql.org/docs/9.4/static/multibyte.html
127
+ # #
128
+ # # Furthermore, MySQL's original implementation of UTF-8 was flawed, and had
129
+ # # to be fixed later by introducing a new charset, `utf8mb4`.
130
+ # #
131
+ # # - https://mathiasbynens.be/notes/mysql-utf8mb4
132
+ # # - https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
133
+ # #
134
+ # def versions_table_options
135
+ # if mysql?
136
+ # ', { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" }'
137
+ # else
138
+ # ''
139
+ # end
140
+ # end
141
+ end
142
+ end