arql 0.3.31 → 0.4.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.vscode/launch.json +1 -1
  3. data/Gemfile.lock +1 -1
  4. data/README-zh_CN.org +616 -491
  5. data/README.org +803 -628
  6. data/auto-set-id-before-save-zh_CN.org +1 -1
  7. data/auto-set-id-before-save.org +1 -1
  8. data/custom-configurations-zh_CN.org +40 -3
  9. data/custom-configurations.org +71 -32
  10. data/define-associations-zh_CN.org +31 -17
  11. data/define-associations.org +52 -29
  12. data/initializer-structure-zh_CN.org +23 -5
  13. data/initializer-structure.org +46 -18
  14. data/lib/arql/app.rb +98 -71
  15. data/lib/arql/cli.rb +37 -15
  16. data/lib/arql/commands/info.rb +41 -28
  17. data/lib/arql/commands/models.rb +106 -61
  18. data/lib/arql/commands/reconnect.rb +8 -4
  19. data/lib/arql/commands/redefine.rb +3 -1
  20. data/lib/arql/commands/sandbox.rb +6 -4
  21. data/lib/arql/commands.rb +0 -2
  22. data/lib/arql/concerns/global_data_definition.rb +40 -6
  23. data/lib/arql/concerns/model_extension.rb +168 -0
  24. data/lib/arql/concerns/table_data_definition.rb +20 -20
  25. data/lib/arql/concerns.rb +1 -0
  26. data/lib/arql/definition.rb +169 -317
  27. data/lib/arql/ext/active_record/relation.rb +29 -0
  28. data/lib/arql/ext/active_record/result.rb +29 -0
  29. data/lib/arql/ext/array.rb +40 -1
  30. data/lib/arql/ext/kernel.rb +70 -61
  31. data/lib/arql/ext/object.rb +14 -0
  32. data/lib/arql/ext/ransack/search.rb +29 -0
  33. data/lib/arql/mysqldump.rb +0 -1
  34. data/lib/arql/repl.rb +1 -1
  35. data/lib/arql/ssh_proxy.rb +25 -22
  36. data/lib/arql/version.rb +1 -1
  37. data/lib/arql.rb +11 -7
  38. data/oss-files-zh_CN.org +2 -2
  39. data/oss-files.org +2 -2
  40. data/sql-log-zh_CN.org +8 -3
  41. data/sql-log.org +8 -3
  42. metadata +6 -5
  43. data/lib/arql/commands/table.rb +0 -55
  44. data/lib/arql/commands/vd.rb +0 -46
  45. data/lib/arql/connection.rb +0 -16
@@ -9,16 +9,18 @@ module Arql::Commands
9
9
 
10
10
  def enter
11
11
  ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback(:checkout, :after, &@sandbox_callback)
12
- ActiveRecord::Base.connection.begin_transaction(joinable: false)
12
+ Arql::App.instance.definitions.each do |_, definition|
13
+ definition.connection.begin_transaction(joinable: false)
14
+ end
13
15
  @enabled = true
14
16
  end
15
17
 
16
18
  def quit
17
19
  ActiveRecord::ConnectionAdapters::AbstractAdapter.skip_callback(:checkout, :after, &@sandbox_callback)
20
+ Arql::App.instance.definitions.each do |_, definition|
21
+ definition.connection.rollback_transaction
22
+ end
18
23
  @enabled = false
19
-
20
- puts "begin_transaction callbacks removed."
21
- puts "You still have open %d transactions open, don't forget commit or rollback them." % ActiveRecord::Base.connection.open_transactions if ActiveRecord::Base.connection.open_transactions > 0
22
24
  end
23
25
  end
24
26
 
data/lib/arql/commands.rb CHANGED
@@ -1,11 +1,9 @@
1
1
  require 'arql/commands/info'
2
2
  require 'arql/commands/models'
3
- require 'arql/commands/table'
4
3
  require 'arql/commands/reconnect'
5
4
  require 'arql/commands/redefine'
6
5
  require 'arql/commands/show_sql'
7
6
  require 'arql/commands/sandbox'
8
- require 'arql/commands/vd'
9
7
 
10
8
  module Arql::Commands
11
9
  end
@@ -159,7 +159,14 @@ module Arql
159
159
  #
160
160
  # See also TableDefinition#column for details on how to create columns.
161
161
  def create_table(table_name, **options, &blk)
162
- ActiveRecord::Base.connection.create_table(table_name, **options, &blk)
162
+ env_name = options[:env]
163
+ unless env_name
164
+ raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
165
+
166
+ env_name = Arql::App.instance.environments.first
167
+ end
168
+ options = options.except(:env)
169
+ Arql::App.instance.definitions[env_name].connection.create_table(table_name, **options, &blk)
163
170
  end
164
171
 
165
172
  # Creates a new join table with the name created using the lexical order of the first two
@@ -201,7 +208,14 @@ module Arql
201
208
  # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
202
209
  #
203
210
  def create_join_table(table_1, table_2, column_options: {}, **options)
204
- ActiveRecord::Base.connection.create_join_table(table_1, table_2, column_options, **options)
211
+ env_name = options[:env]
212
+ unless env_name
213
+ raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
214
+
215
+ env_name = Arql::App.instance.environments.first
216
+ end
217
+ options = options.except(:env)
218
+ Arql::App.instance.definitions[env_name].connection.create_join_table(table_1, table_2, column_options, **options)
205
219
  end
206
220
 
207
221
  # Drops a table from the database.
@@ -217,7 +231,14 @@ module Arql
217
231
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
218
232
  # In that case, +options+ and the block will be used by #create_table.
219
233
  def drop_table(table_name, **options)
220
- ActiveRecord::Base.connection.drop_table(table_name, **options)
234
+ env_name = options[:env]
235
+ unless env_name
236
+ raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
237
+
238
+ env_name = Arql::App.instance.environments.first
239
+ end
240
+ options = options.except(:env)
241
+ Arql::App.instance.definitions[env_name].connection.drop_table(table_name, **options)
221
242
  end
222
243
 
223
244
  # Drops the join table specified by the given arguments.
@@ -227,7 +248,14 @@ module Arql
227
248
  # to provide one in a migration's +change+ method so it can be reverted.
228
249
  # In that case, the block will be used by #create_join_table.
229
250
  def drop_join_table(table_1, table_2, **options)
230
- ActiveRecord::Base.connection.drop_join_table(table_1, table_2, **options)
251
+ env_name = options[:env]
252
+ unless env_name
253
+ raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
254
+
255
+ env_name = Arql::App.instance.environments.first
256
+ end
257
+ options = options.except(:env)
258
+ Arql::App.instance.definitions[env_name].connection.drop_join_table(table_1, table_2, **options)
231
259
  end
232
260
 
233
261
  # Renames a table.
@@ -235,9 +263,15 @@ module Arql
235
263
  # rename_table('octopuses', 'octopi')
236
264
  #
237
265
  def rename_table(table_name, new_name)
238
- ActiveRecord::Base.connection.rename_table(table_name, new_name)
239
- end
266
+ env_name = options[:env]
267
+ unless env_name
268
+ raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
240
269
 
270
+ env_name = Arql::App.instance.environments.first
271
+ end
272
+ options = options.except(:env)
273
+ Arql::App.instance.definitions[env_name].connection.rename_table(table_name, new_name)
274
+ end
241
275
  end
242
276
  end
243
277
  end
@@ -0,0 +1,168 @@
1
+ module Arql
2
+ module Extension
3
+ extend ActiveSupport::Concern
4
+
5
+ def v(compact: false)
6
+ t = []
7
+ t << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
8
+ t << nil
9
+ self.class.connection.columns(self.class.table_name).each do |column|
10
+ value = read_attribute(column.name)
11
+ if compact && value.blank?
12
+ next
13
+ end
14
+ t << [column.name, value, column.sql_type, column.comment || '']
15
+ end
16
+ t
17
+ end
18
+
19
+ def t(compact: false, format: :terminal)
20
+ puts Terminal::Table.new { |t|
21
+ t.style = self.class.table_style_for_format(format)
22
+ v(compact: compact).each { |row| t << (row || :separator) }
23
+ }.try { |e|
24
+ case format
25
+ when :md
26
+ e.to_s.lines.map { |l| ' ' + l }.join
27
+ when :org
28
+ e.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
29
+ else
30
+ e.to_s
31
+ end
32
+ }
33
+ end
34
+
35
+ def vd(compact: false)
36
+ VD.new do |vd|
37
+ vd << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
38
+ self.class.connection.columns(self.class.table_name).each do |column|
39
+ value = read_attribute(column.name)
40
+ next if compact && value.blank?
41
+
42
+ vd << [column.name, read_attribute(column.name), column.sql_type, column.comment || '']
43
+ end
44
+ end
45
+ end
46
+
47
+ def to_insert_sql
48
+ self.class.to_insert_sql([self])
49
+ end
50
+
51
+ def to_upsert_sql
52
+ self.class.to_upsert_sql([self])
53
+ end
54
+
55
+ def write_csv(filename, *fields, **options)
56
+ [self].write_csv(filename, *fields, **options)
57
+ end
58
+
59
+ def write_excel(filename, *fields, **options)
60
+ [self].write_excel(filename, *fields, **options)
61
+ end
62
+
63
+ def dump(filename, batch_size=500)
64
+ [self].dump(filename, batch_size)
65
+ end
66
+
67
+ included do
68
+ end
69
+
70
+ class_methods do
71
+
72
+ def v
73
+ t = [['PK', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']]
74
+ t << nil
75
+ columns.each do |column|
76
+ pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
77
+ 'Y'
78
+ else
79
+ ''
80
+ end
81
+ t << [pk, column.name, column.sql_type,
82
+ column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
83
+ column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
84
+ column.null, column.comment || '']
85
+ end
86
+ t
87
+ end
88
+
89
+ def t(format: :terminal)
90
+ heading_prefix = case format
91
+ when :md
92
+ '# '
93
+ when :org
94
+ '* '
95
+ when :sql
96
+ '-- '
97
+ end
98
+ puts "\n#{heading_prefix}Table: #{table_name}\n\n"
99
+ if format == :sql
100
+ puts to_create_sql + ';'
101
+ else
102
+ puts(Terminal::Table.new { |t|
103
+ t.style = self.table_style_for_format(format)
104
+ v.each { |row| t << (row || :separator) }
105
+ }.try { |e|
106
+ case format
107
+ when :md
108
+ e.to_s.lines.map { |l| ' ' + l }.join
109
+ when :org
110
+ e.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
111
+ else
112
+ e.to_s
113
+ end
114
+ })
115
+ end
116
+ end
117
+
118
+ def vd
119
+ VD.new do |vd|
120
+ v.each do |row|
121
+ vd << row if row
122
+ end
123
+ end
124
+ nil
125
+ end
126
+
127
+ def to_insert_sql(records, batch_size=1)
128
+ to_sql(records, :skip, batch_size)
129
+ end
130
+
131
+ def to_upsert_sql(records, batch_size=1)
132
+ to_sql(records, :update, batch_size)
133
+ end
134
+
135
+ def to_sql(records, on_duplicate, batch_size)
136
+ records.in_groups_of(batch_size, false).map do |group|
137
+ ActiveRecord::InsertAll.new(self, group.map(&:attributes), on_duplicate: on_duplicate).send(:to_sql) + ';'
138
+ end.join("\n")
139
+ end
140
+
141
+ def to_create_sql
142
+ superclass.definition.connection.exec_query("show create table `#{table_name}`").rows.last.last
143
+ end
144
+
145
+ def dump(filename, no_create_table=false)
146
+ Arql::Mysqldump.new(superclass.definition.options).dump_table(filename, table_name, no_create_table)
147
+ end
148
+
149
+ def table_style_for_format(format)
150
+ case format.to_s
151
+ when 'md'
152
+ {
153
+ border_top: false,
154
+ border_bottom: false,
155
+ border_i: '|'
156
+ }
157
+ when 'org'
158
+ {
159
+ border_top: false,
160
+ border_bottom: false,
161
+ }
162
+ else
163
+ {}
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -91,7 +91,7 @@ module Arql
91
91
  # Shape.add_column(:triangle, 'polygon')
92
92
  # # ALTER TABLE "shapes" ADD "triangle" polygon
93
93
  def add_column(column_name, type, **options)
94
- ActiveRecord::Base.connection.add_column(table_name, column_name, type, **options)
94
+ connection.add_column(table_name, column_name, type, **options)
95
95
  end
96
96
 
97
97
  # Changes the column's definition according to the new options.
@@ -101,7 +101,7 @@ module Arql
101
101
  # Post.change_column(:description, :text)
102
102
  #
103
103
  def change_column(column_name, type, options = {})
104
- ActiveRecord::Base.connection.change_column(table_name, column_name, type, **options)
104
+ connection.change_column(table_name, column_name, type, **options)
105
105
  end
106
106
 
107
107
  # Removes the column from the table definition.
@@ -113,7 +113,7 @@ module Arql
113
113
  # In that case, +type+ and +options+ will be used by #add_column.
114
114
  # Indexes on the column are automatically removed.
115
115
  def remove_column(column_name, type = nil, **options)
116
- ActiveRecord::Base.connection.remove_column(table_name, column_name, type, **options)
116
+ connection.remove_column(table_name, column_name, type, **options)
117
117
  end
118
118
 
119
119
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
@@ -229,7 +229,7 @@ module Arql
229
229
  #
230
230
  # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
231
231
  def add_index(column_name, options = {})
232
- ActiveRecord::Base.connection.add_index(table_name, column_name, **options)
232
+ connection.add_index(table_name, column_name, **options)
233
233
  end
234
234
 
235
235
  # Adds a new foreign key.
@@ -277,7 +277,7 @@ module Arql
277
277
  # [<tt>:validate</tt>]
278
278
  # (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
279
279
  def add_foreign_key(to_table, **options)
280
- ActiveRecord::Base.connection.add_foreign_key(table_name, to_table, **options)
280
+ connection.add_foreign_key(table_name, to_table, **options)
281
281
  end
282
282
 
283
283
  # Adds timestamps (+created_at+ and +updated_at+) columns to this table.
@@ -286,7 +286,7 @@ module Arql
286
286
  # Supplier.add_timestamps(null: true)
287
287
  #
288
288
  def add_timestamps(**options)
289
- ActiveRecord::Base.connection.add_timestamps(table_name, **options)
289
+ connection.add_timestamps(table_name, **options)
290
290
  end
291
291
 
292
292
  # Changes the comment for a column or removes it if +nil+.
@@ -296,7 +296,7 @@ module Arql
296
296
  #
297
297
  # Post.change_column_comment(:state, from: "old_comment", to: "new_comment")
298
298
  def change_column_comment(column_name, comment_or_changes)
299
- ActiveRecord::Base.connection.change_column_comment(table_name, column_name, comment_or_changes)
299
+ connection.change_column_comment(table_name, column_name, comment_or_changes)
300
300
  end
301
301
 
302
302
  # Sets a new default value for a column:
@@ -314,7 +314,7 @@ module Arql
314
314
  # Post.change_column_default(:state, from: nil, to: "draft")
315
315
  #
316
316
  def change_column_default(column_name, default_or_changes)
317
- ActiveRecord::Base.connection.change_column_default(table_name, column_name, default_or_changes)
317
+ connection.change_column_default(table_name, column_name, default_or_changes)
318
318
  end
319
319
 
320
320
  # Sets or removes a <tt>NOT NULL</tt> constraint on a column. The +null+ flag
@@ -334,7 +334,7 @@ module Arql
334
334
  #
335
335
  # Please note the fourth argument does not set a column's default.
336
336
  def change_column_null(column_name, null, default = nil)
337
- ActiveRecord::Base.connection.change_column_null(table_name, column_name, null, default)
337
+ connection.change_column_null(table_name, column_name, null, default)
338
338
  end
339
339
 
340
340
  # Renames a column.
@@ -342,7 +342,7 @@ module Arql
342
342
  # Supplier.rename_column(:description, :name)
343
343
  #
344
344
  def rename_column(column_name, new_column_name)
345
- ActiveRecord::Base.connection.rename_column(table_name, column_name, new_column_name)
345
+ connection.rename_column(table_name, column_name, new_column_name)
346
346
  end
347
347
 
348
348
  # A block for changing columns in +table+.
@@ -418,7 +418,7 @@ module Arql
418
418
  #
419
419
  # See also Table for details on all of the various column transformations.
420
420
  def change_table(**options)
421
- ActiveRecord::Base.connection.change_table(table_name, **options)
421
+ connection.change_table(table_name, **options)
422
422
  end
423
423
 
424
424
  # Renames a table.
@@ -426,7 +426,7 @@ module Arql
426
426
  # rename_table('octopi')
427
427
  #
428
428
  def rename_table(new_name)
429
- ActiveRecord::Base.connection.rename_table(table_name, new_name)
429
+ connection.rename_table(table_name, new_name)
430
430
  end
431
431
 
432
432
  # Changes the comment for a table or removes it if +nil+.
@@ -436,7 +436,7 @@ module Arql
436
436
  #
437
437
  # Post.change_table_comment(from: "old_comment", to: "new_comment")
438
438
  def change_table_comment(comment_or_changes)
439
- ActiveRecord::Base.connection.change_table_comment(table_name, comment_or_changes)
439
+ connection.change_table_comment(table_name, comment_or_changes)
440
440
  end
441
441
 
442
442
  # Drops a table from the database.
@@ -452,13 +452,13 @@ module Arql
452
452
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
453
453
  # In that case, +options+ and the block will be used by #create_table.
454
454
  def drop_table(**options)
455
- ActiveRecord::Base.connection.drop_table(table_name, **options)
455
+ connection.drop_table(table_name, **options)
456
456
  end
457
457
 
458
458
  # Returns an array of foreign keys for the given table.
459
459
  # The foreign keys are represented as ForeignKeyDefinition objects.
460
460
  def foreign_keys
461
- ActiveRecord::Base.connection.foreign_keys(table_name)
461
+ connection.foreign_keys(table_name)
462
462
  end
463
463
 
464
464
  # Removes the given foreign key from the table. Any option parameters provided
@@ -487,7 +487,7 @@ module Arql
487
487
  # [<tt>:to_table</tt>]
488
488
  # The name of the table that contains the referenced primary key.
489
489
  def remove_foreign_key(to_table = nil, **options)
490
- ActiveRecord::Base.connection.remove_foreign_key(table_name, to_table, **options)
490
+ connection.remove_foreign_key(table_name, to_table, **options)
491
491
  end
492
492
 
493
493
  # Removes the given index from the table.
@@ -518,7 +518,7 @@ module Arql
518
518
  #
519
519
  # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
520
520
  def remove_index(options = {})
521
- ActiveRecord::Base.connection.remove_index(table_name, **options)
521
+ connection.remove_index(table_name, **options)
522
522
  end
523
523
 
524
524
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
@@ -526,7 +526,7 @@ module Arql
526
526
  # Supplier.remove_timestamps
527
527
  #
528
528
  def remove_timestamps(**options)
529
- ActiveRecord::Base.connection.remove_timestamps(**options)
529
+ connection.remove_timestamps(**options)
530
530
  end
531
531
 
532
532
  # Renames an index.
@@ -536,12 +536,12 @@ module Arql
536
536
  # Person.rename_index 'index_people_on_last_name', 'index_users_on_last_name'
537
537
  #
538
538
  def rename_index(old_name, new_name)
539
- ActiveRecord::Base.connection.rename_index(table_name, old_name, new_name)
539
+ connection.rename_index(table_name, old_name, new_name)
540
540
  end
541
541
 
542
542
  # Returns the table comment that's stored in database metadata.
543
543
  def table_comment
544
- ActiveRecord::Base.connection.table_comment(table_name)
544
+ connection.table_comment(table_name)
545
545
  end
546
546
 
547
547
  end
data/lib/arql/concerns.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'arql/concerns/global_data_definition'
2
2
  require 'arql/concerns/table_data_definition'
3
+ require 'arql/concerns/model_extension'