arql 0.2.7 → 0.2.12

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