arql 0.2.7 → 0.2.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44604f0630f7b6308b9c53bf90b46bd9138b52fdec169baf46bf4e790adfc82b
4
- data.tar.gz: 7efecc0c754d4f16eb31a19756de3d95a06d8d93440e480726d6df574827af13
3
+ metadata.gz: 59eda4176935ad6c21bff248beac1078df7c44239f17c5febd60cd3af5617b34
4
+ data.tar.gz: f6362e715937b0792285ded2d9d10dc00a1e4e9cb224ec7e6ac01ea67d08f268
5
5
  SHA512:
6
- metadata.gz: d795bedb12d2bf39bbb2b5e394373b545e35a542e00110708915fa57b5ca2248f5ed64ee975283d0a3a23e3e4ed201a560fc3ba78dac4085650d6eef486c7fdf
7
- data.tar.gz: 07c6aacfcd46fe3361ebbf977c553c32aad792cb7cd40ebdb9803f0cb76b32ace4bb4326808dd4db2c61be2f6e3e98ec1ee85753ced7e73ee85f8d1f6ffaf10d
6
+ metadata.gz: 50c7e6ac7e3014bc25a7b345ac126b61b79a194907d728140deef9a62ef2adc64947dc84cfad5870894005c3b1a48b7b1c96daee2708fac423ed71a207dbba96
7
+ data.tar.gz: 825621c088e16302953709aa518e5d19f5064212852b65cb230f685e10b47972400eeb2e77b921fa57fb16a8eb9af743e684a60d7d7bc7cfb0e8a61551608131
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- arql (0.2.7)
4
+ arql (0.2.12)
5
5
  activerecord (~> 6.0.3)
6
6
  activesupport (~> 6.0.3)
7
7
  caxlsx (~> 3.0.2)
8
+ composite_primary_keys (~> 12.0.3)
8
9
  mysql2 (~> 0.5.3)
9
10
  net-ssh-gateway (~> 2.0.0)
10
11
  pry (~> 0.13.1)
@@ -19,12 +20,12 @@ PATH
19
20
  GEM
20
21
  remote: https://rubygems.org/
21
22
  specs:
22
- activemodel (6.0.3.3)
23
- activesupport (= 6.0.3.3)
24
- activerecord (6.0.3.3)
25
- activemodel (= 6.0.3.3)
26
- activesupport (= 6.0.3.3)
27
- activesupport (6.0.3.3)
23
+ activemodel (6.0.3.4)
24
+ activesupport (= 6.0.3.4)
25
+ activerecord (6.0.3.4)
26
+ activemodel (= 6.0.3.4)
27
+ activesupport (= 6.0.3.4)
28
+ activesupport (6.0.3.4)
28
29
  concurrent-ruby (~> 1.0, >= 1.0.2)
29
30
  i18n (>= 0.7, < 2)
30
31
  minitest (~> 5.1)
@@ -37,6 +38,8 @@ GEM
37
38
  nokogiri (~> 1.10, >= 1.10.4)
38
39
  rubyzip (>= 1.3.0, < 3)
39
40
  coderay (1.1.3)
41
+ composite_primary_keys (12.0.3)
42
+ activerecord (~> 6.0.0)
40
43
  concurrent-ruby (1.1.7)
41
44
  htmlentities (4.3.4)
42
45
  i18n (1.8.5)
@@ -71,11 +74,11 @@ GEM
71
74
  terminal-table (1.8.0)
72
75
  unicode-display_width (~> 1.1, >= 1.1.1)
73
76
  thread_safe (0.3.6)
74
- tzinfo (1.2.7)
77
+ tzinfo (1.2.8)
75
78
  thread_safe (~> 0.1)
76
79
  unicode-display_width (1.7.0)
77
80
  yard (0.9.25)
78
- zeitwerk (2.4.0)
81
+ zeitwerk (2.4.2)
79
82
 
80
83
  PLATFORMS
81
84
  ruby
@@ -85,4 +88,4 @@ DEPENDENCIES
85
88
  rake (~> 12.0)
86
89
 
87
90
  BUNDLED WITH
88
- 2.1.2
91
+ 2.1.4
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  # spec.add_dependency 'activerecord-sqlserver-adapter'
30
30
  # spec.add_dependency 'activerecord-oracle_enhanced-adapter'
31
31
  spec.add_dependency 'activerecord', '~> 6.0.3'
32
+ spec.add_dependency 'composite_primary_keys', '~> 12.0.3'
32
33
  spec.add_dependency 'activesupport', '~> 6.0.3'
33
34
  spec.add_dependency 'net-ssh-gateway', '~> 2.0.0'
34
35
  spec.add_dependency 'pry', '~> 0.13.1'
@@ -22,6 +22,7 @@ module Arql
22
22
  def initialize(options)
23
23
  require 'active_support/all'
24
24
  require 'active_record'
25
+ require 'composite_primary_keys'
25
26
  require "arql/connection"
26
27
  require "arql/definition"
27
28
  @options = options
@@ -27,7 +27,7 @@ module Arql::Commands
27
27
 
28
28
  Pry.commands.block_command 'm' do |regexp|
29
29
  puts
30
- puts Models::models_table(regexp.try { |e| eval(e) })
30
+ puts Models::models_table(regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
31
31
  end
32
32
 
33
33
  Pry.commands.alias_command 'l', 'm'
@@ -25,7 +25,7 @@ module Arql::Commands
25
25
  t << nil
26
26
  connection = ::ActiveRecord::Base.connection
27
27
  connection.columns(table_name).each do |column|
28
- pk = if column.name == connection.primary_key(table_name)
28
+ pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
29
29
  'Y'
30
30
  else
31
31
  ''
@@ -90,7 +90,11 @@ module Arql
90
90
  const_name = 'Clazz' if const_name == 'Class'
91
91
  Class.new(::ArqlModel) do
92
92
  include Arql::Extension
93
- self.primary_key = pkey
93
+ if pkey.is_a?(Array)
94
+ self.primary_keys = pkey
95
+ else
96
+ self.primary_key = pkey
97
+ end
94
98
  self.table_name = table_name
95
99
  self.inheritance_column = nil
96
100
  self.default_timezone = :local
@@ -140,7 +144,245 @@ module Arql
140
144
  @@options = options
141
145
  @@models = []
142
146
  ActiveRecord::Base.connection.tap do |conn|
143
- Object.const_set('ArqlModel', Class.new(ActiveRecord::Base) { self.abstract_class = true })
147
+ Object.const_set('ArqlModel', Class.new(ActiveRecord::Base) do
148
+ self.abstract_class = true
149
+
150
+ define_singleton_method(:indexes) do
151
+ conn.indexes(table_name).map do |idx|
152
+ {
153
+ Table: idx.table,
154
+ Name: idx.name,
155
+ Columns: idx.columns.join(', '),
156
+ Unique: idx.unique,
157
+ Comment: idx.comment
158
+ }
159
+ end.t
160
+ end
161
+ # Add a new +type+ column named +column_name+ to +table_name+.
162
+ #
163
+ # The +type+ parameter is normally one of the migrations native types,
164
+ # which is one of the following:
165
+ # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
166
+ # <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
167
+ # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
168
+ # <tt>:binary</tt>, <tt>:boolean</tt>.
169
+ #
170
+ # You may use a type not in this list as long as it is supported by your
171
+ # database (for example, "polygon" in MySQL), but this will not be database
172
+ # agnostic and should usually be avoided.
173
+ #
174
+ # Available options are (none of these exists by default):
175
+ # * <tt>:limit</tt> -
176
+ # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
177
+ # and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
178
+ # This option is ignored by some backends.
179
+ # * <tt>:default</tt> -
180
+ # The column's default value. Use +nil+ for +NULL+.
181
+ # * <tt>:null</tt> -
182
+ # Allows or disallows +NULL+ values in the column.
183
+ # * <tt>:precision</tt> -
184
+ # Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
185
+ # <tt>:datetime</tt>, and <tt>:time</tt> columns.
186
+ # * <tt>:scale</tt> -
187
+ # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
188
+ # * <tt>:collation</tt> -
189
+ # Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
190
+ # column will have the same collation as the table.
191
+ # * <tt>:comment</tt> -
192
+ # Specifies the comment for the column. This option is ignored by some backends.
193
+ #
194
+ # Note: The precision is the total number of significant digits,
195
+ # and the scale is the number of digits that can be stored following
196
+ # the decimal point. For example, the number 123.45 has a precision of 5
197
+ # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
198
+ # range from -999.99 to 999.99.
199
+ #
200
+ # Please be aware of different RDBMS implementations behavior with
201
+ # <tt>:decimal</tt> columns:
202
+ # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
203
+ # <tt>:precision</tt>, and makes no comments about the requirements of
204
+ # <tt>:precision</tt>.
205
+ # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
206
+ # Default is (10,0).
207
+ # * PostgreSQL: <tt>:precision</tt> [1..infinity],
208
+ # <tt>:scale</tt> [0..infinity]. No default.
209
+ # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
210
+ # but the maximum supported <tt>:precision</tt> is 16. No default.
211
+ # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
212
+ # Default is (38,0).
213
+ # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
214
+ # Default unknown.
215
+ # * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
216
+ # Default (38,0).
217
+ #
218
+ # == Examples
219
+ #
220
+ # User.add_column(:picture, :binary, limit: 2.megabytes)
221
+ # # ALTER TABLE "users" ADD "picture" blob(2097152)
222
+ #
223
+ # Article.add_column(:status, :string, limit: 20, default: 'draft', null: false)
224
+ # # ALTER TABLE "articles" ADD "status" varchar(20) DEFAULT 'draft' NOT NULL
225
+ #
226
+ # Answer.add_column(:bill_gates_money, :decimal, precision: 15, scale: 2)
227
+ # # ALTER TABLE "answers" ADD "bill_gates_money" decimal(15,2)
228
+ #
229
+ # Measurement.add_column(:sensor_reading, :decimal, precision: 30, scale: 20)
230
+ # # ALTER TABLE "measurements" ADD "sensor_reading" decimal(30,20)
231
+ #
232
+ # # While :scale defaults to zero on most databases, it
233
+ # # probably wouldn't hurt to include it.
234
+ # Measurement.add_column(:huge_integer, :decimal, precision: 30)
235
+ # # ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
236
+ #
237
+ # # Defines a column that stores an array of a type.
238
+ # User.add_column(:skills, :text, array: true)
239
+ # # ALTER TABLE "users" ADD "skills" text[]
240
+ #
241
+ # # Defines a column with a database-specific type.
242
+ # Shape.add_column(:triangle, 'polygon')
243
+ # # ALTER TABLE "shapes" ADD "triangle" polygon
244
+ define_singleton_method(:add_column) do |column_name, type, **options|
245
+ conn.add_column(table_name, column_name, type, **options)
246
+ end
247
+
248
+ # Changes the column's definition according to the new options.
249
+ # See TableDefinition#column for details of the options you can use.
250
+ #
251
+ # Supplier.change_column(:name, :string, limit: 80)
252
+ # Post.change_column(:description, :text)
253
+ #
254
+ define_singleton_method(:change_column) do |column_name, type, options = {}|
255
+ conn.change_column(table_name, column_name, type, options)
256
+ end
257
+
258
+ # Removes the column from the table definition.
259
+ #
260
+ # Supplier.remove_column(:qualification)
261
+ #
262
+ # The +type+ and +options+ parameters will be ignored if present. It can be helpful
263
+ # to provide these in a migration's +change+ method so it can be reverted.
264
+ # In that case, +type+ and +options+ will be used by #add_column.
265
+ # Indexes on the column are automatically removed.
266
+ define_singleton_method(:remove_column) do |column_name, type = nil, **options|
267
+ conn.remove_column(table_name, column_name, type, **options)
268
+ end
269
+
270
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
271
+ # an Array of Symbols.
272
+ #
273
+ # The index will be named after the table and the column name(s), unless
274
+ # you pass <tt>:name</tt> as an option.
275
+ #
276
+ # ====== Creating a simple index
277
+ #
278
+ # Supplier.add_index(:name)
279
+ #
280
+ # generates:
281
+ #
282
+ # CREATE INDEX suppliers_name_index ON suppliers(name)
283
+ #
284
+ # ====== Creating a unique index
285
+ #
286
+ # Account.add_index([:branch_id, :party_id], unique: true)
287
+ #
288
+ # generates:
289
+ #
290
+ # CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
291
+ #
292
+ # ====== Creating a named index
293
+ #
294
+ # Account.add_index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
295
+ #
296
+ # generates:
297
+ #
298
+ # CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
299
+ #
300
+ # ====== Creating an index with specific key length
301
+ #
302
+ # Account.add_index(:name, name: 'by_name', length: 10)
303
+ #
304
+ # generates:
305
+ #
306
+ # CREATE INDEX by_name ON accounts(name(10))
307
+ #
308
+ # ====== Creating an index with specific key lengths for multiple keys
309
+ #
310
+ # Account.add_index([:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15})
311
+ #
312
+ # generates:
313
+ #
314
+ # CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
315
+ #
316
+ # Note: SQLite doesn't support index length.
317
+ #
318
+ # ====== Creating an index with a sort order (desc or asc, asc is the default)
319
+ #
320
+ # Account.add_index([:branch_id, :party_id, :surname], order: {branch_id: :desc, party_id: :asc})
321
+ #
322
+ # generates:
323
+ #
324
+ # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
325
+ #
326
+ # Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).
327
+ #
328
+ # ====== Creating a partial index
329
+ #
330
+ # Account.add_index([:branch_id, :party_id], unique: true, where: "active")
331
+ #
332
+ # generates:
333
+ #
334
+ # CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
335
+ #
336
+ # Note: Partial indexes are only supported for PostgreSQL and SQLite 3.8.0+.
337
+ #
338
+ # ====== Creating an index with a specific method
339
+ #
340
+ # Developer.add_index(:name, using: 'btree')
341
+ #
342
+ # generates:
343
+ #
344
+ # CREATE INDEX index_developers_on_name ON developers USING btree (name) -- PostgreSQL
345
+ # CREATE INDEX index_developers_on_name USING btree ON developers (name) -- MySQL
346
+ #
347
+ # Note: only supported by PostgreSQL and MySQL
348
+ #
349
+ # ====== Creating an index with a specific operator class
350
+ #
351
+ # Developer.add_index(:name, using: 'gist', opclass: :gist_trgm_ops)
352
+ # # CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
353
+ #
354
+ # Developer.add_index([:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
355
+ # # CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
356
+ #
357
+ # Developer.add_index([:name, :city], using: 'gist', opclass: :gist_trgm_ops)
358
+ # # CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
359
+ #
360
+ # Note: only supported by PostgreSQL
361
+ #
362
+ # ====== Creating an index with a specific type
363
+ #
364
+ # Developer.add_index(:name, type: :fulltext)
365
+ #
366
+ # generates:
367
+ #
368
+ # CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
369
+ #
370
+ # Note: only supported by MySQL.
371
+ #
372
+ # ====== Creating an index with a specific algorithm
373
+ #
374
+ # Developer.add_index(:name, algorithm: :concurrently)
375
+ # # CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
376
+ #
377
+ # Note: only supported by PostgreSQL.
378
+ #
379
+ # Concurrently adding an index is not supported in a transaction.
380
+ #
381
+ # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
382
+ define_singleton_method(:add_index) do |column_name, options = {}|
383
+ conn.add_index(table_name, column_name, options)
384
+ end
385
+ end)
144
386
  conn.tables.each do |table_name|
145
387
  table_comment = conn.table_comment(table_name)
146
388
  conn.primary_key(table_name).tap do |pkey|
@@ -149,7 +391,11 @@ module Arql
149
391
  const_name = 'Clazz' if const_name == 'Class'
150
392
  Class.new(::ArqlModel) do
151
393
  include Arql::Extension
152
- self.primary_key = pkey
394
+ if pkey.is_a?(Array)
395
+ self.primary_keys = pkey
396
+ else
397
+ self.primary_key = pkey
398
+ end
153
399
  self.table_name = table_name
154
400
  self.inheritance_column = nil
155
401
  self.default_timezone = :local
@@ -83,11 +83,17 @@ class Array
83
83
  end
84
84
  csv << fields
85
85
  end
86
+ if size > 0 && first.is_a?(Hash)
87
+ if fields.empty?
88
+ fields = first.keys
89
+ end
90
+ csv << fields
91
+ end
86
92
  each do |row|
87
93
  if row.is_a?(Array)
88
94
  csv << row.map(&:to_s)
89
95
  else
90
- csv << row.slice(fields).values.map(&:to_s)
96
+ csv << row.slice(*fields).values.map(&:to_s)
91
97
  end
92
98
  end
93
99
  end
@@ -105,11 +111,17 @@ class Array
105
111
  end
106
112
  sheet.add_row(fields, types: [:string] * fields.size)
107
113
  end
114
+ if size > 0 && first.is_a?(Hash)
115
+ if fields.empty?
116
+ fields = first.keys
117
+ end
118
+ sheet.add_row(fields, types: [:string] * fields.size)
119
+ end
108
120
  each do |row|
109
121
  if row.is_a?(Array)
110
122
  sheet.add_row(row.map(&:to_s), types: [:string] * row.size)
111
123
  else
112
- sheet.add_row(row.slice(fields).values.map(&:to_s), types: [:string] * fields.size)
124
+ sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
113
125
  end
114
126
  end
115
127
  end
@@ -3,19 +3,35 @@ class Hash
3
3
  generate_excel(filename) do |workbook|
4
4
  each do |sheet_name, sheet_data|
5
5
  workbook.add_worksheet(name: sheet_name) do |sheet|
6
- if sheet_data.is_a?(Hash) && sheet_data[:fields].present?
7
- fields = sheet_data[:fields].map(&:to_s)
8
- else
9
- fields = sheet_data[:data].first.attributes.keys
10
- end
6
+ if sheet_data.is_a?(Hash)
7
+ fields = sheet_data[:fields].map(&:to_s)
11
8
  sheet.add_row(fields, types: [:string] * fields.size)
12
- sheet_data = sheet_data[:data]
9
+ sheet_data[:data].each do |row|
10
+ sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
11
+ end
13
12
  end
14
- sheet_data.each do |row|
15
- if row.is_a?(Array)
16
- sheet.add_row(row.map(&:to_s), types: [:string] * row.size)
17
- else
18
- sheet.add_row(row.slice(fields).values.map(&:to_s), types: [:string] * fields.size)
13
+
14
+ if sheet_data.is_a?(Array)
15
+ if sheet_data.size > 0 && sheet_data.first.is_a?(ActiveModel::Base)
16
+ fields = sheet_data.first.attributes.keys
17
+ sheet.add_row(fields, types: [:string] * fields.size)
18
+ sheet_data.each do |row|
19
+ sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
20
+ end
21
+ end
22
+
23
+ if sheet_data.size > 0 && sheet_data.first.is_a?(Hash)
24
+ fields = sheet_data.first.keys
25
+ sheet.add_row(fields, types: [:string] * fields.size)
26
+ sheet_data.each do |row|
27
+ sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
28
+ end
29
+ end
30
+
31
+ if sheet_data.size > 0 && sheet_data.first.is_a?(Array)
32
+ sheet_data.each do |row|
33
+ sheet.add_row(row.map(&:to_s), types: [:string] * fields.size)
34
+ end
19
35
  end
20
36
  end
21
37
  end
@@ -25,7 +25,7 @@ module Kernel
25
25
  Terminal::Table.new { |t|
26
26
  t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
27
27
  t.rows = table[:columns].map { |column|
28
- pk = if column.name == ::ActiveRecord::Base.connection.primary_key(table_name)
28
+ pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
29
29
  'Y'
30
30
  else
31
31
  ''
@@ -44,7 +44,7 @@ module Kernel
44
44
  Terminal::Table.new { |t|
45
45
  t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
46
46
  t.rows = table[:columns].map { |column|
47
- pk = if column.name == ::ActiveRecord::Base.connection.primary_key(table_name)
47
+ pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
48
48
  'Y'
49
49
  else
50
50
  ''
@@ -105,4 +105,160 @@ module Kernel
105
105
  end
106
106
  end
107
107
  end
108
+
109
+ # Example:
110
+ #
111
+ # create_table :post, id: false, primary_key: :id do |t|
112
+ # t.column :id, :bigint, precison: 19, comment: 'ID'
113
+ # t.column :name, :string, comment: '名称'
114
+ # t.column :gmt_created, :datetime, comment: '创建时间'
115
+ # t.column :gmt_modified, :datetime, comment: '最后修改时间'
116
+ # end
117
+ #
118
+ # Creates a new table with the name +table_name+. +table_name+ may either
119
+ # be a String or a Symbol.
120
+ #
121
+ # There are two ways to work with #create_table. You can use the block
122
+ # form or the regular form, like this:
123
+ #
124
+ # === Block form
125
+ #
126
+ # # create_table() passes a TableDefinition object to the block.
127
+ # # This form will not only create the table, but also columns for the
128
+ # # table.
129
+ #
130
+ # create_table(:suppliers) do |t|
131
+ # t.column :name, :string, limit: 60
132
+ # # Other fields here
133
+ # end
134
+ #
135
+ # === Block form, with shorthand
136
+ #
137
+ # # You can also use the column types as method calls, rather than calling the column method.
138
+ # create_table(:suppliers) do |t|
139
+ # t.string :name, limit: 60
140
+ # # Other fields here
141
+ # end
142
+ #
143
+ # === Regular form
144
+ #
145
+ # # Creates a table called 'suppliers' with no columns.
146
+ # create_table(:suppliers)
147
+ # # Add a column to 'suppliers'.
148
+ # add_column(:suppliers, :name, :string, {limit: 60})
149
+ #
150
+ # The +options+ hash can include the following keys:
151
+ # [<tt>:id</tt>]
152
+ # Whether to automatically add a primary key column. Defaults to true.
153
+ # Join tables for {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] should set it to false.
154
+ #
155
+ # A Symbol can be used to specify the type of the generated primary key column.
156
+ # [<tt>:primary_key</tt>]
157
+ # The name of the primary key, if one is to be added automatically.
158
+ # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
159
+ #
160
+ # If an array is passed, a composite primary key will be created.
161
+ #
162
+ # Note that Active Record models will automatically detect their
163
+ # primary key. This can be avoided by using
164
+ # {self.primary_key=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#primary_key=] on the model
165
+ # to define the key explicitly.
166
+ #
167
+ # [<tt>:options</tt>]
168
+ # Any extra options you want appended to the table definition.
169
+ # [<tt>:temporary</tt>]
170
+ # Make a temporary table.
171
+ # [<tt>:force</tt>]
172
+ # Set to true to drop the table before creating it.
173
+ # Set to +:cascade+ to drop dependent objects as well.
174
+ # Defaults to false.
175
+ # [<tt>:if_not_exists</tt>]
176
+ # Set to true to avoid raising an error when the table already exists.
177
+ # Defaults to false.
178
+ # [<tt>:as</tt>]
179
+ # SQL to use to generate the table. When this option is used, the block is
180
+ # ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
181
+ #
182
+ # ====== Add a backend specific option to the generated SQL (MySQL)
183
+ #
184
+ # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
185
+ #
186
+ # generates:
187
+ #
188
+ # CREATE TABLE suppliers (
189
+ # id bigint auto_increment PRIMARY KEY
190
+ # ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
191
+ #
192
+ # ====== Rename the primary key column
193
+ #
194
+ # create_table(:objects, primary_key: 'guid') do |t|
195
+ # t.column :name, :string, limit: 80
196
+ # end
197
+ #
198
+ # generates:
199
+ #
200
+ # CREATE TABLE objects (
201
+ # guid bigint auto_increment PRIMARY KEY,
202
+ # name varchar(80)
203
+ # )
204
+ #
205
+ # ====== Change the primary key column type
206
+ #
207
+ # create_table(:tags, id: :string) do |t|
208
+ # t.column :label, :string
209
+ # end
210
+ #
211
+ # generates:
212
+ #
213
+ # CREATE TABLE tags (
214
+ # id varchar PRIMARY KEY,
215
+ # label varchar
216
+ # )
217
+ #
218
+ # ====== Create a composite primary key
219
+ #
220
+ # create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
221
+ # t.belongs_to :product
222
+ # t.belongs_to :client
223
+ # end
224
+ #
225
+ # generates:
226
+ #
227
+ # CREATE TABLE order (
228
+ # product_id bigint NOT NULL,
229
+ # client_id bigint NOT NULL
230
+ # );
231
+ #
232
+ # ALTER TABLE ONLY "orders"
233
+ # ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
234
+ #
235
+ # ====== Do not add a primary key column
236
+ #
237
+ # create_table(:categories_suppliers, id: false) do |t|
238
+ # t.column :category_id, :bigint
239
+ # t.column :supplier_id, :bigint
240
+ # end
241
+ #
242
+ # generates:
243
+ #
244
+ # CREATE TABLE categories_suppliers (
245
+ # category_id bigint,
246
+ # supplier_id bigint
247
+ # )
248
+ #
249
+ # ====== Create a temporary table based on a query
250
+ #
251
+ # create_table(:long_query, temporary: true,
252
+ # as: "SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id")
253
+ #
254
+ # generates:
255
+ #
256
+ # CREATE TEMPORARY TABLE long_query AS
257
+ # SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
258
+ #
259
+ # See also TableDefinition#column for details on how to create columns.
260
+
261
+ def create_table(table_name, **options, &blk)
262
+ ActiveRecord::Base.connection.create_table(table_name, **options, &blk)
263
+ end
108
264
  end
@@ -1,3 +1,3 @@
1
1
  module Arql
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.12"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-04 00:00:00.000000000 Z
11
+ date: 2021-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 6.0.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: composite_primary_keys
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 12.0.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 12.0.3
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -257,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
257
271
  - !ruby/object:Gem::Version
258
272
  version: '0'
259
273
  requirements: []
260
- rubygems_version: 3.1.2
274
+ rubygems_version: 3.1.4
261
275
  signing_key:
262
276
  specification_version: 4
263
277
  summary: Rails ActiveRecord + Pry is the best SQL query editor