activerecord-dbt 0.1.0
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +921 -0
- data/Rakefile +5 -0
- data/lib/active_record/dbt/column/column.rb +84 -0
- data/lib/active_record/dbt/column/test.rb +61 -0
- data/lib/active_record/dbt/column/testable/accepted_values_testable.rb +59 -0
- data/lib/active_record/dbt/column/testable/not_null_testable.rb +23 -0
- data/lib/active_record/dbt/column/testable/relationships_testable.rb +49 -0
- data/lib/active_record/dbt/column/testable/unique_testable.rb +37 -0
- data/lib/active_record/dbt/config.rb +45 -0
- data/lib/active_record/dbt/configuration/data_sync.rb +15 -0
- data/lib/active_record/dbt/configuration/logger.rb +41 -0
- data/lib/active_record/dbt/configuration/parser.rb +15 -0
- data/lib/active_record/dbt/configuration/used_dbt_package.rb +25 -0
- data/lib/active_record/dbt/dbt_package/dbt_utils/table/testable/unique_combination_of_columns_testable.rb +42 -0
- data/lib/active_record/dbt/dbt_package/dbterd/column/testable/relationships_meta_relationship_type.rb +138 -0
- data/lib/active_record/dbt/factory/columns_factory.rb +31 -0
- data/lib/active_record/dbt/factory/model/staging_factory.rb +22 -0
- data/lib/active_record/dbt/factory/source_factory.rb +16 -0
- data/lib/active_record/dbt/factory/table_factory.rb +16 -0
- data/lib/active_record/dbt/factory/tables_factory.rb +15 -0
- data/lib/active_record/dbt/model/staging/base.rb +73 -0
- data/lib/active_record/dbt/model/staging/sql.rb +43 -0
- data/lib/active_record/dbt/model/staging/yml.rb +108 -0
- data/lib/active_record/dbt/railtie.rb +8 -0
- data/lib/active_record/dbt/source/yml.rb +37 -0
- data/lib/active_record/dbt/table/base.rb +16 -0
- data/lib/active_record/dbt/table/test.rb +19 -0
- data/lib/active_record/dbt/table/yml.rb +75 -0
- data/lib/active_record/dbt/version.rb +7 -0
- data/lib/active_record/dbt.rb +17 -0
- data/lib/generators/active_record/dbt/config/USAGE +9 -0
- data/lib/generators/active_record/dbt/config/config_generator.rb +30 -0
- data/lib/generators/active_record/dbt/config/templates/source_config.yml.tt +68 -0
- data/lib/generators/active_record/dbt/initializer/USAGE +8 -0
- data/lib/generators/active_record/dbt/initializer/initializer_generator.rb +15 -0
- data/lib/generators/active_record/dbt/initializer/templates/dbt.rb +10 -0
- data/lib/generators/active_record/dbt/source/USAGE +8 -0
- data/lib/generators/active_record/dbt/source/source_generator.rb +22 -0
- data/lib/generators/active_record/dbt/staging_model/USAGE +9 -0
- data/lib/generators/active_record/dbt/staging_model/staging_model_generator.rb +38 -0
- data/lib/generators/active_record/dbt/staging_model/templates/staging_model.sql.tt +29 -0
- data/lib/tasks/active_record/dbt_tasks.rake +6 -0
- metadata +133 -0
data/README.md
ADDED
@@ -0,0 +1,921 @@
|
|
1
|
+
# ActiveRecord::Dbt
|
2
|
+
|
3
|
+
`ActiveRecord::Dbt` generates dbt files from the information of the database connected via ActiveRecord.
|
4
|
+
|
5
|
+
Currently, it can generate `yaml` files for `sources` and `models` files for `staging`.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To install `activerecord-dbt`, add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'activerecord-dbt'
|
13
|
+
```
|
14
|
+
|
15
|
+
Since it is only used in the development environment, it is recommended to add it to the development group:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
group :development do
|
19
|
+
gem 'activerecord-dbt'
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
Then run:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
$ bundle
|
27
|
+
```
|
28
|
+
|
29
|
+
Alternatively, you can install it manually by running:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
$ gem install activerecord-dbt
|
33
|
+
```
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
### Configuration
|
38
|
+
|
39
|
+
#### ActiveRecord::Dbt Configuration
|
40
|
+
|
41
|
+
Create an initializer file for dbt:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
$ bin/rails generate active_record:dbt:initializer
|
45
|
+
```
|
46
|
+
|
47
|
+
This will generate the `config/initializers/dbt.rb` file.
|
48
|
+
|
49
|
+
Configuration | Description
|
50
|
+
--------- | ---------
|
51
|
+
config_directory_path | The path to the directory where files generated by `bin/rails generate active_record:dbt:*` are stored. The default is `lib/dbt`.
|
52
|
+
export_directory_path | The path to the directory where configuration files are stored. The default is `doc/dbt`.
|
53
|
+
data_sync_delayed | Indicates whether there is a data delay. If set to `true`, `severity: warn` is applied to the `relationships` test. The default is `false`.
|
54
|
+
logger | The destination for log output. The default is `Logger.new('./log/active_record_dbt.log')`.
|
55
|
+
used_dbt_package_names | An array of `dbt` package names to use.
|
56
|
+
|
57
|
+
Example:
|
58
|
+
|
59
|
+
Adjust the settings according to your environment.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# frozen_string_literal: true
|
63
|
+
|
64
|
+
require 'active_record/dbt'
|
65
|
+
|
66
|
+
ActiveRecord::Dbt.configure do |c|
|
67
|
+
c.config_directory_path = 'lib/dbt'
|
68
|
+
c.export_directory_path = 'doc/dbt'
|
69
|
+
c.data_sync_delayed = false
|
70
|
+
c.used_dbt_package_names = [
|
71
|
+
'dbt-labs/dbt_utils',
|
72
|
+
'datnguye/dbterd'
|
73
|
+
]
|
74
|
+
end
|
75
|
+
|
76
|
+
```
|
77
|
+
|
78
|
+
#### Create Configuration Files
|
79
|
+
|
80
|
+
Create configuration files for dbt:
|
81
|
+
|
82
|
+
```bash
|
83
|
+
$ bin/rails generate active_record:dbt:config
|
84
|
+
```
|
85
|
+
|
86
|
+
This will create the following files.
|
87
|
+
|
88
|
+
File | Description
|
89
|
+
--------- | ---------
|
90
|
+
`#{config_directory_path}/source_config.yml` | Used to generate `#{export_directory_path}/src_#{source_name}.yml`.
|
91
|
+
`#{config_directory_path}/staging_model.sql.tt` | Used to generate `#{export_directory_path}/stg_#{source_name}__#{table_name}.sql`.
|
92
|
+
|
93
|
+
### Generate dbt Source File
|
94
|
+
|
95
|
+
#### dbt Source Configuration
|
96
|
+
|
97
|
+
In the `#{config_directory_path}/source_config.yml` file, describe the properties you want to set for the source.
|
98
|
+
You can configure `sources`, `table_overrides`, `defaults`, and `table_descriptions` in this file.
|
99
|
+
|
100
|
+
The available properties for `sources` and `table_overrides` are detailed in [Source properties | dbt Developer Hub](https://docs.getdbt.com/reference/source-properties).
|
101
|
+
|
102
|
+
##### sources
|
103
|
+
|
104
|
+
Set all properties except for `tables`.
|
105
|
+
|
106
|
+
Example:
|
107
|
+
|
108
|
+
```yml
|
109
|
+
sources:
|
110
|
+
name: dummy
|
111
|
+
meta:
|
112
|
+
generated_by: activerecord-dbt
|
113
|
+
description: |-
|
114
|
+
Write a description of the 'dummy' source.
|
115
|
+
You can write multiple lines.
|
116
|
+
|
117
|
+
```
|
118
|
+
|
119
|
+
##### table_overrides
|
120
|
+
|
121
|
+
Set all properties for `tables` except for `name` and `description`.
|
122
|
+
|
123
|
+
Example:
|
124
|
+
|
125
|
+
```yml
|
126
|
+
table_overrides:
|
127
|
+
users:
|
128
|
+
loaded_at_field: created_at
|
129
|
+
freshness:
|
130
|
+
warn_after:
|
131
|
+
count: 3
|
132
|
+
period: day
|
133
|
+
error_after:
|
134
|
+
count: 5
|
135
|
+
period: day
|
136
|
+
columns:
|
137
|
+
created_at:
|
138
|
+
tests:
|
139
|
+
- not_null:
|
140
|
+
where: 'id != 1'
|
141
|
+
|
142
|
+
```
|
143
|
+
|
144
|
+
##### defaults
|
145
|
+
|
146
|
+
Set default values for the `name` and `description` of `tables`.
|
147
|
+
|
148
|
+
In `logical_name` and `description` of `table_descriptions`, you can refer to the table name with `{{ table_name }}`.
|
149
|
+
In the `description` of `columns`, you can refer to the table name with `{{ table_name }}` and the column name with `{{ column_name }}`.
|
150
|
+
|
151
|
+
Example:
|
152
|
+
|
153
|
+
```yml
|
154
|
+
defaults:
|
155
|
+
table_descriptions:
|
156
|
+
logical_name: Write a logical_name of the '{{ table_name }}' table.
|
157
|
+
columns:
|
158
|
+
description: Write a description of the '{{ table_name }}.{{ column_name }}' column.
|
159
|
+
|
160
|
+
```
|
161
|
+
|
162
|
+
If nothing is set, it defaults to the following:
|
163
|
+
|
164
|
+
```yml
|
165
|
+
defaults:
|
166
|
+
table_descriptions:
|
167
|
+
logical_name: Write a logical_name of the '{{ table_name }}' table.
|
168
|
+
columns:
|
169
|
+
description: Write a description of the '{{ table_name }}.{{ column_name }}' column.
|
170
|
+
|
171
|
+
```
|
172
|
+
|
173
|
+
##### table_descriptions
|
174
|
+
|
175
|
+
Set the `name` and `description` for `tables`.
|
176
|
+
|
177
|
+
Configuration | Description
|
178
|
+
--------- | ---------
|
179
|
+
logical_name | A title or one-line description to be output in the dbt `description`.
|
180
|
+
description | A detailed description of `logical_name` to be output in the dbt `description`.
|
181
|
+
|
182
|
+
Example:
|
183
|
+
|
184
|
+
```yml
|
185
|
+
table_descriptions:
|
186
|
+
ar_internal_metadata:
|
187
|
+
logical_name: Internal Metadata
|
188
|
+
description: |-
|
189
|
+
By default Rails will store information about your Rails environment and schema
|
190
|
+
in an internal table named `ar_internal_metadata`.
|
191
|
+
columns:
|
192
|
+
key: Key
|
193
|
+
value: Value
|
194
|
+
created_at: Created At
|
195
|
+
updated_at: Updated At
|
196
|
+
schema_migrations:
|
197
|
+
logical_name: Schema Migrations
|
198
|
+
description: |-
|
199
|
+
Rails keeps track of which migrations have been committed to the database and
|
200
|
+
stores them in a neighboring table in that same database called `schema_migrations`.
|
201
|
+
columns:
|
202
|
+
version: The version number of the migration.
|
203
|
+
|
204
|
+
```
|
205
|
+
|
206
|
+
##### Example:
|
207
|
+
|
208
|
+
Adjust the settings according to your environment.
|
209
|
+
|
210
|
+
```yml
|
211
|
+
sources:
|
212
|
+
name: dummy
|
213
|
+
meta:
|
214
|
+
generated_by: activerecord-dbt
|
215
|
+
description: |-
|
216
|
+
Write a description of the 'dummy' source.
|
217
|
+
You can write multiple lines.
|
218
|
+
|
219
|
+
table_overrides:
|
220
|
+
users:
|
221
|
+
loaded_at_field: created_at
|
222
|
+
freshness:
|
223
|
+
warn_after:
|
224
|
+
count: 3
|
225
|
+
period: day
|
226
|
+
error_after:
|
227
|
+
count: 5
|
228
|
+
period: day
|
229
|
+
columns:
|
230
|
+
created_at:
|
231
|
+
tests:
|
232
|
+
- not_null:
|
233
|
+
where: 'id != 1'
|
234
|
+
|
235
|
+
defaults:
|
236
|
+
table_descriptions:
|
237
|
+
logical_name: Write a logical_name of the '{{ table_name }}' table.
|
238
|
+
columns:
|
239
|
+
description: Write a description of the '{{ table_name }}.{{ column_name }}' column.
|
240
|
+
|
241
|
+
table_descriptions:
|
242
|
+
ar_internal_metadata:
|
243
|
+
logical_name: Internal Metadata
|
244
|
+
description: |-
|
245
|
+
By default Rails will store information about your Rails environment and schema
|
246
|
+
in an internal table named `ar_internal_metadata`.
|
247
|
+
columns:
|
248
|
+
key: Key
|
249
|
+
value: Value
|
250
|
+
created_at: Created At
|
251
|
+
updated_at: Updated At
|
252
|
+
schema_migrations:
|
253
|
+
logical_name: Schema Migrations
|
254
|
+
description: |-
|
255
|
+
Rails keeps track of which migrations have been committed to the database and
|
256
|
+
stores them in a neighboring table in that same database called `schema_migrations`.
|
257
|
+
columns:
|
258
|
+
version: The version number of the migration.
|
259
|
+
|
260
|
+
```
|
261
|
+
|
262
|
+
#### Generate `#{export_directory_path}/src_#{source_name}.yml`
|
263
|
+
|
264
|
+
Generate a source file for dbt:
|
265
|
+
|
266
|
+
```bash
|
267
|
+
$ bin/rails generate active_record:dbt:source
|
268
|
+
```
|
269
|
+
|
270
|
+
Generate `#{export_directory_path}/src_#{source_name}.yml`.
|
271
|
+
|
272
|
+
##### Example:
|
273
|
+
|
274
|
+
> [!NOTE]
|
275
|
+
>
|
276
|
+
> The output will be as shown below. It is recommended to indent the YAML file with a tool of your choice.
|
277
|
+
|
278
|
+
```yaml
|
279
|
+
---
|
280
|
+
version: 2
|
281
|
+
sources:
|
282
|
+
- name: dummy
|
283
|
+
meta:
|
284
|
+
generated_by: activerecord-dbt
|
285
|
+
description: |-
|
286
|
+
Write a description of the 'dummy' source.
|
287
|
+
You can write multiple lines.
|
288
|
+
tables:
|
289
|
+
- name: ar_internal_metadata
|
290
|
+
description: |-
|
291
|
+
# Internal Metadata
|
292
|
+
By default Rails will store information about your Rails environment and schema
|
293
|
+
in an internal table named `ar_internal_metadata`.
|
294
|
+
columns:
|
295
|
+
- name: key
|
296
|
+
description: Key
|
297
|
+
meta:
|
298
|
+
column_type: string
|
299
|
+
tests:
|
300
|
+
- unique
|
301
|
+
- not_null
|
302
|
+
- name: value
|
303
|
+
description: Value
|
304
|
+
meta:
|
305
|
+
column_type: string
|
306
|
+
- name: created_at
|
307
|
+
description: Created At
|
308
|
+
meta:
|
309
|
+
column_type: datetime
|
310
|
+
tests:
|
311
|
+
- not_null
|
312
|
+
- name: updated_at
|
313
|
+
description: Updated At
|
314
|
+
meta:
|
315
|
+
column_type: datetime
|
316
|
+
tests:
|
317
|
+
- not_null
|
318
|
+
- name: companies
|
319
|
+
description: Write a logical_name of the 'companies' table.
|
320
|
+
columns:
|
321
|
+
- name: id
|
322
|
+
description: id
|
323
|
+
meta:
|
324
|
+
column_type: integer
|
325
|
+
tests:
|
326
|
+
- unique
|
327
|
+
- not_null
|
328
|
+
- name: name
|
329
|
+
description: Write a description of the 'companies.name' column.
|
330
|
+
meta:
|
331
|
+
column_type: string
|
332
|
+
tests:
|
333
|
+
- not_null
|
334
|
+
- name: establishment_date
|
335
|
+
description: Write a description of the 'companies.establishment_date' column.
|
336
|
+
meta:
|
337
|
+
column_type: string
|
338
|
+
- name: average_age
|
339
|
+
description: Write a description of the 'companies.average_age' column.
|
340
|
+
meta:
|
341
|
+
column_type: float
|
342
|
+
- name: published
|
343
|
+
description: Write a description of the 'companies.published' column.
|
344
|
+
meta:
|
345
|
+
column_type: boolean
|
346
|
+
tests:
|
347
|
+
- not_null
|
348
|
+
- accepted_values:
|
349
|
+
values:
|
350
|
+
- true
|
351
|
+
- false
|
352
|
+
quote: false
|
353
|
+
- name: created_at
|
354
|
+
description: Created At
|
355
|
+
meta:
|
356
|
+
column_type: datetime
|
357
|
+
tests:
|
358
|
+
- not_null
|
359
|
+
- name: updated_at
|
360
|
+
description: Updated At
|
361
|
+
meta:
|
362
|
+
column_type: datetime
|
363
|
+
tests:
|
364
|
+
- not_null
|
365
|
+
- name: posts
|
366
|
+
description: Post
|
367
|
+
columns:
|
368
|
+
- name: id
|
369
|
+
description: ID
|
370
|
+
meta:
|
371
|
+
column_type: integer
|
372
|
+
tests:
|
373
|
+
- unique
|
374
|
+
- not_null
|
375
|
+
- name: user_id
|
376
|
+
description: User
|
377
|
+
meta:
|
378
|
+
column_type: integer
|
379
|
+
tests:
|
380
|
+
- not_null
|
381
|
+
- relationships:
|
382
|
+
to: source('dummy', 'users')
|
383
|
+
field: id
|
384
|
+
meta:
|
385
|
+
relationship_type: many-to-one
|
386
|
+
- name: title
|
387
|
+
description: Title
|
388
|
+
meta:
|
389
|
+
column_type: string
|
390
|
+
- name: content
|
391
|
+
description: Content
|
392
|
+
meta:
|
393
|
+
column_type: text
|
394
|
+
- name: created_at
|
395
|
+
description: Post Created At
|
396
|
+
meta:
|
397
|
+
column_type: datetime
|
398
|
+
tests:
|
399
|
+
- not_null
|
400
|
+
- name: updated_at
|
401
|
+
description: Post Updated At
|
402
|
+
meta:
|
403
|
+
column_type: datetime
|
404
|
+
tests:
|
405
|
+
- not_null
|
406
|
+
- name: status
|
407
|
+
description: Write a description of the 'posts.status' column.
|
408
|
+
meta:
|
409
|
+
column_type: integer
|
410
|
+
tests:
|
411
|
+
- accepted_values:
|
412
|
+
values:
|
413
|
+
- 0
|
414
|
+
- 1
|
415
|
+
- 2
|
416
|
+
quote: false
|
417
|
+
- name: posts_tags
|
418
|
+
description: Write a logical_name of the 'posts_tags' table.
|
419
|
+
tests:
|
420
|
+
- dbt_utils.unique_combination_of_columns:
|
421
|
+
combination_of_columns:
|
422
|
+
- post_id
|
423
|
+
- tag_id
|
424
|
+
columns:
|
425
|
+
- name: post_id
|
426
|
+
description: post_id
|
427
|
+
meta:
|
428
|
+
column_type: integer
|
429
|
+
tests:
|
430
|
+
- not_null
|
431
|
+
- relationships:
|
432
|
+
to: source('dummy', 'posts')
|
433
|
+
field: id
|
434
|
+
meta:
|
435
|
+
relationship_type: many-to-one
|
436
|
+
active_record_dbt_error:
|
437
|
+
class: NameError
|
438
|
+
message: uninitialized constant PostsTag
|
439
|
+
- name: tag_id
|
440
|
+
description: tag_id
|
441
|
+
meta:
|
442
|
+
column_type: integer
|
443
|
+
tests:
|
444
|
+
- not_null
|
445
|
+
- relationships:
|
446
|
+
to: source('dummy', 'tags')
|
447
|
+
field: id
|
448
|
+
meta:
|
449
|
+
relationship_type: many-to-one
|
450
|
+
active_record_dbt_error:
|
451
|
+
class: NameError
|
452
|
+
message: uninitialized constant PostsTag
|
453
|
+
- name: profiles
|
454
|
+
description: Write a logical_name of the 'profiles' table.
|
455
|
+
columns:
|
456
|
+
- name: id
|
457
|
+
description: id
|
458
|
+
meta:
|
459
|
+
column_type: integer
|
460
|
+
tests:
|
461
|
+
- unique
|
462
|
+
- not_null
|
463
|
+
- name: user_id
|
464
|
+
description: user_id
|
465
|
+
meta:
|
466
|
+
column_type: integer
|
467
|
+
tests:
|
468
|
+
- unique
|
469
|
+
- not_null
|
470
|
+
- relationships:
|
471
|
+
to: source('dummy', 'users')
|
472
|
+
field: id
|
473
|
+
meta:
|
474
|
+
relationship_type: one-to-one
|
475
|
+
- name: first_name
|
476
|
+
description: Write a description of the 'profiles.first_name' column.
|
477
|
+
meta:
|
478
|
+
column_type: string
|
479
|
+
tests:
|
480
|
+
- not_null
|
481
|
+
- name: last_name
|
482
|
+
description: Write a description of the 'profiles.last_name' column.
|
483
|
+
meta:
|
484
|
+
column_type: string
|
485
|
+
tests:
|
486
|
+
- not_null
|
487
|
+
- name: created_at
|
488
|
+
description: Created At
|
489
|
+
meta:
|
490
|
+
column_type: datetime
|
491
|
+
tests:
|
492
|
+
- not_null
|
493
|
+
- name: updated_at
|
494
|
+
description: Updated At
|
495
|
+
meta:
|
496
|
+
column_type: datetime
|
497
|
+
tests:
|
498
|
+
- not_null
|
499
|
+
- name: relationships
|
500
|
+
description: Write a logical_name of the 'relationships' table.
|
501
|
+
tests:
|
502
|
+
- dbt_utils.unique_combination_of_columns:
|
503
|
+
combination_of_columns:
|
504
|
+
- follower_id
|
505
|
+
- followed_id
|
506
|
+
columns:
|
507
|
+
- name: id
|
508
|
+
description: id
|
509
|
+
meta:
|
510
|
+
column_type: integer
|
511
|
+
tests:
|
512
|
+
- unique
|
513
|
+
- not_null
|
514
|
+
- name: follower_id
|
515
|
+
description: follower_id
|
516
|
+
meta:
|
517
|
+
column_type: integer
|
518
|
+
tests:
|
519
|
+
- not_null
|
520
|
+
- relationships:
|
521
|
+
to: source('dummy', 'users')
|
522
|
+
field: id
|
523
|
+
meta:
|
524
|
+
relationship_type: many-to-one
|
525
|
+
- name: followed_id
|
526
|
+
description: followed_id
|
527
|
+
meta:
|
528
|
+
column_type: integer
|
529
|
+
tests:
|
530
|
+
- not_null
|
531
|
+
- relationships:
|
532
|
+
to: source('dummy', 'users')
|
533
|
+
field: id
|
534
|
+
meta:
|
535
|
+
relationship_type: many-to-one
|
536
|
+
- name: created_at
|
537
|
+
description: Created At
|
538
|
+
meta:
|
539
|
+
column_type: datetime
|
540
|
+
tests:
|
541
|
+
- not_null
|
542
|
+
- name: updated_at
|
543
|
+
description: Updated At
|
544
|
+
meta:
|
545
|
+
column_type: datetime
|
546
|
+
tests:
|
547
|
+
- not_null
|
548
|
+
- name: schema_migrations
|
549
|
+
description: |-
|
550
|
+
# Schema Migrations
|
551
|
+
Rails keeps track of which migrations have been committed to the database and
|
552
|
+
stores them in a neighboring table in that same database called `schema_migrations`.
|
553
|
+
columns:
|
554
|
+
- name: version
|
555
|
+
description: The version number of the migration.
|
556
|
+
meta:
|
557
|
+
column_type: string
|
558
|
+
tests:
|
559
|
+
- unique
|
560
|
+
- not_null
|
561
|
+
- name: tags
|
562
|
+
description: Write a logical_name of the 'tags' table.
|
563
|
+
columns:
|
564
|
+
- name: id
|
565
|
+
description: id
|
566
|
+
meta:
|
567
|
+
column_type: integer
|
568
|
+
tests:
|
569
|
+
- unique
|
570
|
+
- not_null
|
571
|
+
- name: name
|
572
|
+
description: Write a description of the 'tags.name' column.
|
573
|
+
meta:
|
574
|
+
column_type: string
|
575
|
+
tests:
|
576
|
+
- unique
|
577
|
+
- not_null
|
578
|
+
- name: created_at
|
579
|
+
description: Created At
|
580
|
+
meta:
|
581
|
+
column_type: datetime
|
582
|
+
tests:
|
583
|
+
- not_null
|
584
|
+
- name: updated_at
|
585
|
+
description: Updated At
|
586
|
+
meta:
|
587
|
+
column_type: datetime
|
588
|
+
tests:
|
589
|
+
- not_null
|
590
|
+
- name: user_tags
|
591
|
+
description: Write a logical_name of the 'user_tags' table.
|
592
|
+
tests:
|
593
|
+
- dbt_utils.unique_combination_of_columns:
|
594
|
+
combination_of_columns:
|
595
|
+
- user_id
|
596
|
+
- tag_id
|
597
|
+
columns:
|
598
|
+
- name: id
|
599
|
+
description: id
|
600
|
+
meta:
|
601
|
+
column_type: integer
|
602
|
+
tests:
|
603
|
+
- unique
|
604
|
+
- not_null
|
605
|
+
- name: user_id
|
606
|
+
description: user_id
|
607
|
+
meta:
|
608
|
+
column_type: integer
|
609
|
+
tests:
|
610
|
+
- not_null
|
611
|
+
- relationships:
|
612
|
+
to: source('dummy', 'users')
|
613
|
+
field: id
|
614
|
+
meta:
|
615
|
+
relationship_type: many-to-one
|
616
|
+
- name: tag_id
|
617
|
+
description: tag_id
|
618
|
+
meta:
|
619
|
+
column_type: integer
|
620
|
+
tests:
|
621
|
+
- not_null
|
622
|
+
- relationships:
|
623
|
+
to: source('dummy', 'tags')
|
624
|
+
field: id
|
625
|
+
meta:
|
626
|
+
relationship_type: many-to-one
|
627
|
+
- name: created_at
|
628
|
+
description: Created At
|
629
|
+
meta:
|
630
|
+
column_type: datetime
|
631
|
+
tests:
|
632
|
+
- not_null
|
633
|
+
- name: updated_at
|
634
|
+
description: Updated At
|
635
|
+
meta:
|
636
|
+
column_type: datetime
|
637
|
+
tests:
|
638
|
+
- not_null
|
639
|
+
- name: users
|
640
|
+
description: User
|
641
|
+
loaded_at_field: created_at
|
642
|
+
freshness:
|
643
|
+
warn_after:
|
644
|
+
count: 3
|
645
|
+
period: day
|
646
|
+
error_after:
|
647
|
+
count: 5
|
648
|
+
period: day
|
649
|
+
columns:
|
650
|
+
- name: id
|
651
|
+
description: ID
|
652
|
+
meta:
|
653
|
+
column_type: integer
|
654
|
+
tests:
|
655
|
+
- unique
|
656
|
+
- not_null
|
657
|
+
- name: created_at
|
658
|
+
description: User Created At
|
659
|
+
meta:
|
660
|
+
column_type: datetime
|
661
|
+
tests:
|
662
|
+
- not_null:
|
663
|
+
where: id != 1
|
664
|
+
- name: updated_at
|
665
|
+
description: User Updated At
|
666
|
+
meta:
|
667
|
+
column_type: datetime
|
668
|
+
tests:
|
669
|
+
- not_null
|
670
|
+
- name: company_id
|
671
|
+
description: company_id
|
672
|
+
meta:
|
673
|
+
column_type: integer
|
674
|
+
tests:
|
675
|
+
- relationships:
|
676
|
+
to: source('dummy', 'companies')
|
677
|
+
field: id
|
678
|
+
meta:
|
679
|
+
relationship_type: many-to-one
|
680
|
+
|
681
|
+
```
|
682
|
+
|
683
|
+
### Generate dbt Staging Files
|
684
|
+
|
685
|
+
#### dbt Staging Configuration
|
686
|
+
|
687
|
+
In the `#{config_directory_path}/staging_model.sql.tt` file, write the SQL template for the `staging` model you want to create.
|
688
|
+
You can use `sql.source_name`, `sql.table_name`, `sql.select_column_names`, `sql.primary_key_eql_id?`, and `sql.rename_primary_id` within this file.
|
689
|
+
|
690
|
+
Example:
|
691
|
+
|
692
|
+
```sql
|
693
|
+
with
|
694
|
+
|
695
|
+
source as (
|
696
|
+
|
697
|
+
select * from {{ source('<%= sql.source_name %>', '<%= sql.table_name %>') }}
|
698
|
+
|
699
|
+
),
|
700
|
+
|
701
|
+
renamed as (
|
702
|
+
|
703
|
+
select
|
704
|
+
|
705
|
+
<%- sql.select_column_names.each_with_index do |(column_type, columns), column_type_index| -%>
|
706
|
+
-- <%= column_type %>
|
707
|
+
<%- columns.each_with_index do |column, column_index| -%>
|
708
|
+
<%- is_rename_primary_id = sql.primary_key_eql_id? && sql.primary_key?(column.name) -%>
|
709
|
+
<%- is_last_column = column_type_index == sql.select_column_names.size - 1 && column_index == columns.size - 1 -%>
|
710
|
+
<%= is_rename_primary_id ? "id as #{sql.rename_primary_id}" : column.name %><% unless is_last_column -%>,<%- end %>
|
711
|
+
<%- if column_type_index != sql.select_column_names.size - 1 && column_index == columns.size - 1 -%>
|
712
|
+
|
713
|
+
<%- end -%>
|
714
|
+
<%- end -%>
|
715
|
+
<%- end -%>
|
716
|
+
|
717
|
+
from source
|
718
|
+
|
719
|
+
)
|
720
|
+
|
721
|
+
select * from renamed
|
722
|
+
|
723
|
+
```
|
724
|
+
|
725
|
+
Different Pattern:
|
726
|
+
|
727
|
+
```sql
|
728
|
+
#standardSQL
|
729
|
+
|
730
|
+
with source as (
|
731
|
+
select
|
732
|
+
<%- if sql.primary_key_eql_id? -%>
|
733
|
+
id as <%= sql.rename_primary_id %>
|
734
|
+
, * except(id)
|
735
|
+
<%- else -%>
|
736
|
+
*
|
737
|
+
<%- end -%>
|
738
|
+
from {{ source('<%= sql.source_name %>', '<%= sql.table_name %>') }}
|
739
|
+
)
|
740
|
+
|
741
|
+
, final as (
|
742
|
+
select
|
743
|
+
<%- sql.select_column_names.each_with_index do |(column_type, columns), column_type_index| -%>
|
744
|
+
-- <%= column_type %>
|
745
|
+
<%- columns.each_with_index do |column, column_index| -%>
|
746
|
+
<% unless column_type_index == 0 && column_index == 0 -%>, <%- end %><%= (sql.primary_key_eql_id? && sql.primary_key?(column.name) ? sql.rename_primary_id : column.name) %>
|
747
|
+
<%- if column_type_index != sql.select_column_names.size - 1 && column_index == columns.size - 1 -%>
|
748
|
+
|
749
|
+
<%- end -%>
|
750
|
+
<%- end -%>
|
751
|
+
<%- end -%>
|
752
|
+
from source
|
753
|
+
)
|
754
|
+
|
755
|
+
select
|
756
|
+
*
|
757
|
+
from final
|
758
|
+
|
759
|
+
```
|
760
|
+
|
761
|
+
#### Generate dbt Staging Files
|
762
|
+
|
763
|
+
Generate staging model files for dbt:
|
764
|
+
|
765
|
+
```bash
|
766
|
+
$ bin/rails generate active_record:dbt:staging_model TABLE_NAME
|
767
|
+
```
|
768
|
+
|
769
|
+
Generate staging model files for dbt that reference the specified `TABLE_NAME`.
|
770
|
+
|
771
|
+
File | Description
|
772
|
+
--------- | ---------
|
773
|
+
`#{export_directory_path}/stg_#{source_name}__#{table_name}.sql` | Staging model file for dbt.
|
774
|
+
`#{export_directory_path}/stg_#{source_name}__#{table_name}.yml` | Staging model documentation file for dbt.
|
775
|
+
|
776
|
+
Example:
|
777
|
+
|
778
|
+
```bash
|
779
|
+
$ bin/rails generate active_record:dbt:staging_model profiles
|
780
|
+
```
|
781
|
+
|
782
|
+
##### Generate `#{export_directory_path}/stg_#{source_name}__#{table_name}.sql`
|
783
|
+
|
784
|
+
Example:
|
785
|
+
|
786
|
+
```sql
|
787
|
+
with
|
788
|
+
|
789
|
+
source as (
|
790
|
+
|
791
|
+
select * from {{ source('dummy', 'profiles') }}
|
792
|
+
|
793
|
+
),
|
794
|
+
|
795
|
+
renamed as (
|
796
|
+
|
797
|
+
select
|
798
|
+
|
799
|
+
-- ids
|
800
|
+
id as profile_id,
|
801
|
+
user_id,
|
802
|
+
|
803
|
+
-- strings
|
804
|
+
first_name,
|
805
|
+
last_name,
|
806
|
+
|
807
|
+
-- datetimes
|
808
|
+
created_at,
|
809
|
+
updated_at
|
810
|
+
|
811
|
+
from source
|
812
|
+
|
813
|
+
)
|
814
|
+
|
815
|
+
select * from renamed
|
816
|
+
|
817
|
+
```
|
818
|
+
|
819
|
+
Different Pattern:
|
820
|
+
|
821
|
+
```sql
|
822
|
+
#standardSQL
|
823
|
+
|
824
|
+
with source as (
|
825
|
+
select
|
826
|
+
id as profile_id
|
827
|
+
, * except(id)
|
828
|
+
from {{ source('dummy', 'profiles') }}
|
829
|
+
)
|
830
|
+
|
831
|
+
, final as (
|
832
|
+
select
|
833
|
+
-- ids
|
834
|
+
profile_id
|
835
|
+
, user_id
|
836
|
+
|
837
|
+
-- strings
|
838
|
+
, first_name
|
839
|
+
, last_name
|
840
|
+
|
841
|
+
-- datetimes
|
842
|
+
, created_at
|
843
|
+
, updated_at
|
844
|
+
from source
|
845
|
+
)
|
846
|
+
|
847
|
+
select
|
848
|
+
*
|
849
|
+
from final
|
850
|
+
|
851
|
+
```
|
852
|
+
|
853
|
+
##### Generate `#{export_directory_path}/stg_#{source_name}__#{table_name}.yml`
|
854
|
+
|
855
|
+
Example:
|
856
|
+
|
857
|
+
```yaml
|
858
|
+
---
|
859
|
+
version: 2
|
860
|
+
models:
|
861
|
+
- name: stg_dummy__profiles
|
862
|
+
description: Write a logical_name of the 'profiles' table.
|
863
|
+
columns:
|
864
|
+
- name: profile_id
|
865
|
+
description: profile_id
|
866
|
+
meta:
|
867
|
+
column_type: integer
|
868
|
+
tests:
|
869
|
+
- unique
|
870
|
+
- not_null
|
871
|
+
- relationships:
|
872
|
+
to: source('dummy', 'profiles')
|
873
|
+
field: id
|
874
|
+
meta:
|
875
|
+
relationship_type: one-to-one
|
876
|
+
- name: user_id
|
877
|
+
description: user_id
|
878
|
+
meta:
|
879
|
+
column_type: integer
|
880
|
+
tests:
|
881
|
+
- unique
|
882
|
+
- not_null
|
883
|
+
- relationships:
|
884
|
+
to: source('dummy', 'users')
|
885
|
+
field: id
|
886
|
+
meta:
|
887
|
+
relationship_type: one-to-one
|
888
|
+
- name: first_name
|
889
|
+
description: Write a description of the 'profiles.first_name' column.
|
890
|
+
meta:
|
891
|
+
column_type: string
|
892
|
+
tests:
|
893
|
+
- not_null
|
894
|
+
- name: last_name
|
895
|
+
description: Write a description of the 'profiles.last_name' column.
|
896
|
+
meta:
|
897
|
+
column_type: string
|
898
|
+
tests:
|
899
|
+
- not_null
|
900
|
+
- name: created_at
|
901
|
+
description: Created At
|
902
|
+
meta:
|
903
|
+
column_type: datetime
|
904
|
+
tests:
|
905
|
+
- not_null
|
906
|
+
- name: updated_at
|
907
|
+
description: Updated At
|
908
|
+
meta:
|
909
|
+
column_type: datetime
|
910
|
+
tests:
|
911
|
+
- not_null
|
912
|
+
|
913
|
+
```
|
914
|
+
|
915
|
+
## Contributing
|
916
|
+
|
917
|
+
Contribution directions go here.
|
918
|
+
|
919
|
+
## License
|
920
|
+
|
921
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|