arql 0.3.31 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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'