activerecord-dbt 0.1.0 → 0.2.0

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: 897ffab9f05715634ea7eb0ef68be9c70e8d305458657696fe544255f17293c9
4
- data.tar.gz: f82f9f7b02c592572077f3ba41bf0920ae0abb831de065b707d107124080353d
3
+ metadata.gz: c7948bb8cc4c14d07c3fca2855b20957a2871c54dd67149fb178029fa93f6f09
4
+ data.tar.gz: c8146bfcd3ffa762f16889a79750807ab1e72986e49f34069ac043fe8c89d5f0
5
5
  SHA512:
6
- metadata.gz: cd87b1c4a5ba3e97aad5320f58eb9151e14ff8752b93519b0b14314b9ba872b48afee79e93e09de813898ccf83dc3d41a0d64d07277c1e8cf7413dabd93a7fd2
7
- data.tar.gz: 829ff19c802bc18c7e721ede97beff805e26e9642382153a64ececb21e7f5b6512cab9f226e1ef3c7ca51399a9ec4604cf7b3b1a1f61e237e74a99327b12429e
6
+ metadata.gz: a2d3ce1aa15cafbd0bb6f282d5faa64f6319d669a38a8dde20b04af3cccf12a21e16fa22cf6f7b87b245dd094bad296de2dd22bd027db047b2ed845cc7de2b8a
7
+ data.tar.gz: 6097b5f0b25324679e012d4a16833afba17514f2ebb82eabe778ae510bc8f283c280dd3d6916b2a3220092c63c7827c56b4b0660f14caa6f1b210a496dff7cdc
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # ActiveRecord::Dbt
2
2
 
3
- `ActiveRecord::Dbt` generates dbt files from the information of the database connected via ActiveRecord.
3
+ [![Gem Version](https://badge.fury.io/rb/activerecord-dbt.svg)](https://badge.fury.io/rb/activerecord-dbt)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/ef9a0a71c73dae7b8156/maintainability)](https://codeclimate.com/github/yamotech/activerecord-dbt/maintainability)
5
+ [![Ruby CI](https://github.com/yamotech/activerecord-dbt/actions/workflows/ruby-ci.yml/badge.svg)](https://github.com/yamotech/activerecord-dbt/actions/workflows/ruby-ci.yml)
6
+
7
+ `ActiveRecord::Dbt` generates [dbt](https://www.getdbt.com/) files from the information of the database connected via ActiveRecord.
4
8
 
5
9
  Currently, it can generate `yaml` files for `sources` and `models` files for `staging`.
6
10
 
@@ -50,10 +54,28 @@ Configuration | Description
50
54
  --------- | ---------
51
55
  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
56
  export_directory_path | The path to the directory where configuration files are stored. The default is `doc/dbt`.
57
+ dwh_platform | Specify the data warehouse platform to which dbt connects. The default is `bigquery`.
53
58
  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
59
  logger | The destination for log output. The default is `Logger.new('./log/active_record_dbt.log')`.
55
60
  used_dbt_package_names | An array of `dbt` package names to use.
56
61
 
62
+ List of platforms that can currently be set with `dwh_platform`.
63
+
64
+ Data Warehouse Platform | Link
65
+ --------- | ---------
66
+ bigquery | [BigQuery enterprise data warehouse - Google Cloud](https://cloud.google.com/bigquery?hl=en)
67
+ postgres | [PostgreSQL: The world's most advanced open source database](https://www.postgresql.org/)
68
+ redshift | [Cloud Data Warehouse - Amazon Redshift - AWS](https://aws.amazon.com/redshift/)
69
+ snowflake | [The Snowflake AI Data Cloud - Mobilize Data, Apps, and AI](https://www.snowflake.com/en/)
70
+ spark | [Apache Spark™ - Unified Engine for large-scale data analytics](https://spark.apache.org/)
71
+
72
+ List of packages that can currently be set with `used_dbt_package_names`.
73
+
74
+ dbt Package Name | Link
75
+ --------- | ---------
76
+ dbt-labs/dbt-utils | [dbt-labs/dbt-utils: Utility functions for dbt projects.](https://github.com/dbt-labs/dbt-utils)
77
+ datnguye/dbterd | [datnguye/dbterd: Generate the ERD as a code from dbt artifacts](https://github.com/datnguye/dbterd)
78
+
57
79
  Example:
58
80
 
59
81
  Adjust the settings according to your environment.
@@ -294,25 +316,21 @@ sources:
294
316
  columns:
295
317
  - name: key
296
318
  description: Key
297
- meta:
298
- column_type: string
319
+ data_type: string
299
320
  tests:
300
321
  - unique
301
322
  - not_null
302
323
  - name: value
303
324
  description: Value
304
- meta:
305
- column_type: string
325
+ data_type: string
306
326
  - name: created_at
307
327
  description: Created At
308
- meta:
309
- column_type: datetime
328
+ data_type: datetime
310
329
  tests:
311
330
  - not_null
312
331
  - name: updated_at
313
332
  description: Updated At
314
- meta:
315
- column_type: datetime
333
+ data_type: datetime
316
334
  tests:
317
335
  - not_null
318
336
  - name: companies
@@ -320,29 +338,24 @@ sources:
320
338
  columns:
321
339
  - name: id
322
340
  description: id
323
- meta:
324
- column_type: integer
341
+ data_type: int64
325
342
  tests:
326
343
  - unique
327
344
  - not_null
328
345
  - name: name
329
346
  description: Write a description of the 'companies.name' column.
330
- meta:
331
- column_type: string
347
+ data_type: string
332
348
  tests:
333
349
  - not_null
334
350
  - name: establishment_date
335
351
  description: Write a description of the 'companies.establishment_date' column.
336
- meta:
337
- column_type: string
352
+ data_type: string
338
353
  - name: average_age
339
354
  description: Write a description of the 'companies.average_age' column.
340
- meta:
341
- column_type: float
355
+ data_type: float64
342
356
  - name: published
343
357
  description: Write a description of the 'companies.published' column.
344
- meta:
345
- column_type: boolean
358
+ data_type: bool
346
359
  tests:
347
360
  - not_null
348
361
  - accepted_values:
@@ -352,14 +365,12 @@ sources:
352
365
  quote: false
353
366
  - name: created_at
354
367
  description: Created At
355
- meta:
356
- column_type: datetime
368
+ data_type: datetime
357
369
  tests:
358
370
  - not_null
359
371
  - name: updated_at
360
372
  description: Updated At
361
- meta:
362
- column_type: datetime
373
+ data_type: datetime
363
374
  tests:
364
375
  - not_null
365
376
  - name: posts
@@ -367,15 +378,13 @@ sources:
367
378
  columns:
368
379
  - name: id
369
380
  description: ID
370
- meta:
371
- column_type: integer
381
+ data_type: int64
372
382
  tests:
373
383
  - unique
374
384
  - not_null
375
385
  - name: user_id
376
386
  description: User
377
- meta:
378
- column_type: integer
387
+ data_type: int64
379
388
  tests:
380
389
  - not_null
381
390
  - relationships:
@@ -385,28 +394,23 @@ sources:
385
394
  relationship_type: many-to-one
386
395
  - name: title
387
396
  description: Title
388
- meta:
389
- column_type: string
397
+ data_type: string
390
398
  - name: content
391
399
  description: Content
392
- meta:
393
- column_type: text
400
+ data_type: string
394
401
  - name: created_at
395
402
  description: Post Created At
396
- meta:
397
- column_type: datetime
403
+ data_type: datetime
398
404
  tests:
399
405
  - not_null
400
406
  - name: updated_at
401
407
  description: Post Updated At
402
- meta:
403
- column_type: datetime
408
+ data_type: datetime
404
409
  tests:
405
410
  - not_null
406
411
  - name: status
407
412
  description: Write a description of the 'posts.status' column.
408
- meta:
409
- column_type: integer
413
+ data_type: int64
410
414
  tests:
411
415
  - accepted_values:
412
416
  values:
@@ -424,8 +428,7 @@ sources:
424
428
  columns:
425
429
  - name: post_id
426
430
  description: post_id
427
- meta:
428
- column_type: integer
431
+ data_type: int64
429
432
  tests:
430
433
  - not_null
431
434
  - relationships:
@@ -438,8 +441,7 @@ sources:
438
441
  message: uninitialized constant PostsTag
439
442
  - name: tag_id
440
443
  description: tag_id
441
- meta:
442
- column_type: integer
444
+ data_type: int64
443
445
  tests:
444
446
  - not_null
445
447
  - relationships:
@@ -455,15 +457,13 @@ sources:
455
457
  columns:
456
458
  - name: id
457
459
  description: id
458
- meta:
459
- column_type: integer
460
+ data_type: int64
460
461
  tests:
461
462
  - unique
462
463
  - not_null
463
464
  - name: user_id
464
465
  description: user_id
465
- meta:
466
- column_type: integer
466
+ data_type: int64
467
467
  tests:
468
468
  - unique
469
469
  - not_null
@@ -474,26 +474,22 @@ sources:
474
474
  relationship_type: one-to-one
475
475
  - name: first_name
476
476
  description: Write a description of the 'profiles.first_name' column.
477
- meta:
478
- column_type: string
477
+ data_type: string
479
478
  tests:
480
479
  - not_null
481
480
  - name: last_name
482
481
  description: Write a description of the 'profiles.last_name' column.
483
- meta:
484
- column_type: string
482
+ data_type: string
485
483
  tests:
486
484
  - not_null
487
485
  - name: created_at
488
486
  description: Created At
489
- meta:
490
- column_type: datetime
487
+ data_type: datetime
491
488
  tests:
492
489
  - not_null
493
490
  - name: updated_at
494
491
  description: Updated At
495
- meta:
496
- column_type: datetime
492
+ data_type: datetime
497
493
  tests:
498
494
  - not_null
499
495
  - name: relationships
@@ -506,15 +502,13 @@ sources:
506
502
  columns:
507
503
  - name: id
508
504
  description: id
509
- meta:
510
- column_type: integer
505
+ data_type: int64
511
506
  tests:
512
507
  - unique
513
508
  - not_null
514
509
  - name: follower_id
515
510
  description: follower_id
516
- meta:
517
- column_type: integer
511
+ data_type: int64
518
512
  tests:
519
513
  - not_null
520
514
  - relationships:
@@ -524,8 +518,7 @@ sources:
524
518
  relationship_type: many-to-one
525
519
  - name: followed_id
526
520
  description: followed_id
527
- meta:
528
- column_type: integer
521
+ data_type: int64
529
522
  tests:
530
523
  - not_null
531
524
  - relationships:
@@ -535,14 +528,12 @@ sources:
535
528
  relationship_type: many-to-one
536
529
  - name: created_at
537
530
  description: Created At
538
- meta:
539
- column_type: datetime
531
+ data_type: datetime
540
532
  tests:
541
533
  - not_null
542
534
  - name: updated_at
543
535
  description: Updated At
544
- meta:
545
- column_type: datetime
536
+ data_type: datetime
546
537
  tests:
547
538
  - not_null
548
539
  - name: schema_migrations
@@ -553,8 +544,7 @@ sources:
553
544
  columns:
554
545
  - name: version
555
546
  description: The version number of the migration.
556
- meta:
557
- column_type: string
547
+ data_type: string
558
548
  tests:
559
549
  - unique
560
550
  - not_null
@@ -563,28 +553,24 @@ sources:
563
553
  columns:
564
554
  - name: id
565
555
  description: id
566
- meta:
567
- column_type: integer
556
+ data_type: int64
568
557
  tests:
569
558
  - unique
570
559
  - not_null
571
560
  - name: name
572
561
  description: Write a description of the 'tags.name' column.
573
- meta:
574
- column_type: string
562
+ data_type: string
575
563
  tests:
576
564
  - unique
577
565
  - not_null
578
566
  - name: created_at
579
567
  description: Created At
580
- meta:
581
- column_type: datetime
568
+ data_type: datetime
582
569
  tests:
583
570
  - not_null
584
571
  - name: updated_at
585
572
  description: Updated At
586
- meta:
587
- column_type: datetime
573
+ data_type: datetime
588
574
  tests:
589
575
  - not_null
590
576
  - name: user_tags
@@ -597,15 +583,13 @@ sources:
597
583
  columns:
598
584
  - name: id
599
585
  description: id
600
- meta:
601
- column_type: integer
586
+ data_type: int64
602
587
  tests:
603
588
  - unique
604
589
  - not_null
605
590
  - name: user_id
606
591
  description: user_id
607
- meta:
608
- column_type: integer
592
+ data_type: int64
609
593
  tests:
610
594
  - not_null
611
595
  - relationships:
@@ -615,8 +599,7 @@ sources:
615
599
  relationship_type: many-to-one
616
600
  - name: tag_id
617
601
  description: tag_id
618
- meta:
619
- column_type: integer
602
+ data_type: int64
620
603
  tests:
621
604
  - not_null
622
605
  - relationships:
@@ -626,14 +609,12 @@ sources:
626
609
  relationship_type: many-to-one
627
610
  - name: created_at
628
611
  description: Created At
629
- meta:
630
- column_type: datetime
612
+ data_type: datetime
631
613
  tests:
632
614
  - not_null
633
615
  - name: updated_at
634
616
  description: Updated At
635
- meta:
636
- column_type: datetime
617
+ data_type: datetime
637
618
  tests:
638
619
  - not_null
639
620
  - name: users
@@ -649,28 +630,24 @@ sources:
649
630
  columns:
650
631
  - name: id
651
632
  description: ID
652
- meta:
653
- column_type: integer
633
+ data_type: int64
654
634
  tests:
655
635
  - unique
656
636
  - not_null
657
637
  - name: created_at
658
638
  description: User Created At
659
- meta:
660
- column_type: datetime
639
+ data_type: datetime
661
640
  tests:
662
641
  - not_null:
663
642
  where: id != 1
664
643
  - name: updated_at
665
644
  description: User Updated At
666
- meta:
667
- column_type: datetime
645
+ data_type: datetime
668
646
  tests:
669
647
  - not_null
670
648
  - name: company_id
671
649
  description: company_id
672
- meta:
673
- column_type: integer
650
+ data_type: int64
674
651
  tests:
675
652
  - relationships:
676
653
  to: source('dummy', 'companies')
@@ -863,8 +840,7 @@ models:
863
840
  columns:
864
841
  - name: profile_id
865
842
  description: profile_id
866
- meta:
867
- column_type: integer
843
+ data_type: int64
868
844
  tests:
869
845
  - unique
870
846
  - not_null
@@ -875,8 +851,7 @@ models:
875
851
  relationship_type: one-to-one
876
852
  - name: user_id
877
853
  description: user_id
878
- meta:
879
- column_type: integer
854
+ data_type: int64
880
855
  tests:
881
856
  - unique
882
857
  - not_null
@@ -887,26 +862,22 @@ models:
887
862
  relationship_type: one-to-one
888
863
  - name: first_name
889
864
  description: Write a description of the 'profiles.first_name' column.
890
- meta:
891
- column_type: string
865
+ data_type: string
892
866
  tests:
893
867
  - not_null
894
868
  - name: last_name
895
869
  description: Write a description of the 'profiles.last_name' column.
896
- meta:
897
- column_type: string
870
+ data_type: string
898
871
  tests:
899
872
  - not_null
900
873
  - name: created_at
901
874
  description: Created At
902
- meta:
903
- column_type: datetime
875
+ data_type: datetime
904
876
  tests:
905
877
  - not_null
906
878
  - name: updated_at
907
879
  description: Updated At
908
- meta:
909
- column_type: datetime
880
+ data_type: datetime
910
881
  tests:
911
882
  - not_null
912
883
 
@@ -4,6 +4,8 @@ module ActiveRecord
4
4
  module Dbt
5
5
  module Column
6
6
  class Column
7
+ include ActiveRecord::Dbt::DataType::Mapper
8
+
7
9
  attr_reader :table_name, :column, :column_test, :primary_keys
8
10
 
9
11
  delegate :name, :comment, to: :column, prefix: true
@@ -21,7 +23,7 @@ module ActiveRecord
21
23
  {
22
24
  'name' => column_name,
23
25
  'description' => description,
24
- 'meta' => { 'column_type' => column.type.to_s },
26
+ 'data_type' => data_type,
25
27
  **column_overrides.except(:tests),
26
28
  'tests' => column_test.config
27
29
  }.compact
@@ -5,17 +5,13 @@ module ActiveRecord
5
5
  module Column
6
6
  module Testable
7
7
  module AcceptedValuesTestable
8
- REQUIRED_ACCEPTED_VALUES_TESTABLE_METHODS = %i[@config column table_name column_name].freeze
8
+ extend ActiveRecord::Dbt::RequiredMethods
9
+
10
+ define_required_methods :@config, :column, :table_name, :column_name
9
11
 
10
12
  delegate :type, to: :column, prefix: true
11
13
  delegate :add_log, to: :@config
12
14
 
13
- REQUIRED_ACCEPTED_VALUES_TESTABLE_METHODS.each do |method_name|
14
- define_method(method_name) do
15
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
16
- end
17
- end
18
-
19
15
  def accepted_values_test
20
16
  return nil unless column_type == :boolean || enum_values.present?
21
17
 
@@ -5,13 +5,9 @@ module ActiveRecord
5
5
  module Column
6
6
  module Testable
7
7
  module NotNullTestable
8
- REQUIRED_NOT_NULL_TESTABLE_METHODS = %i[column].freeze
8
+ extend ActiveRecord::Dbt::RequiredMethods
9
9
 
10
- REQUIRED_NOT_NULL_TESTABLE_METHODS.each do |method_name|
11
- define_method(method_name) do
12
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
13
- end
14
- end
10
+ define_required_methods :column
15
11
 
16
12
  def not_null_test
17
13
  column.null == true ? nil : 'not_null'
@@ -5,19 +5,15 @@ module ActiveRecord
5
5
  module Column
6
6
  module Testable
7
7
  module RelationshipsTestable
8
- REQUIRED_RELATIONSHIPS_TESTABLE_METHODS = %i[@config foreign_keys column_name].freeze
9
-
10
8
  include ActiveRecord::Dbt::DbtPackage::Dbterd::Column::Testable::RelationshipsMetaRelationshipType
11
9
 
10
+ extend ActiveRecord::Dbt::RequiredMethods
11
+
12
+ define_required_methods :@config, :foreign_keys, :column_name
13
+
12
14
  delegate :source_name, :data_sync_delayed?, to: :@config
13
15
  delegate :to_table, to: :foreign_key
14
16
 
15
- REQUIRED_RELATIONSHIPS_TESTABLE_METHODS.each do |method_name|
16
- define_method(method_name) do
17
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
18
- end
19
- end
20
-
21
17
  def relationships_test
22
18
  return nil if foreign_key.blank?
23
19
 
@@ -5,13 +5,9 @@ module ActiveRecord
5
5
  module Column
6
6
  module Testable
7
7
  module UniqueTestable
8
- REQUIRED_UNIQUE_TESTABLE_METHODS = %i[table_name column_name primary_keys].freeze
8
+ extend ActiveRecord::Dbt::RequiredMethods
9
9
 
10
- REQUIRED_UNIQUE_TESTABLE_METHODS.each do |method_name|
11
- define_method(method_name) do
12
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
13
- end
14
- end
10
+ define_required_methods :table_name, :column_name, :primary_keys
15
11
 
16
12
  def unique_test
17
13
  unique? ? 'unique' : nil
@@ -8,6 +8,7 @@ module ActiveRecord
8
8
  include Singleton
9
9
 
10
10
  include ActiveRecord::Dbt::Configuration::DataSync
11
+ include ActiveRecord::Dbt::Configuration::DwhPlatform
11
12
  include ActiveRecord::Dbt::Configuration::Logger
12
13
  include ActiveRecord::Dbt::Configuration::Parser
13
14
  include ActiveRecord::Dbt::Configuration::UsedDbtPackage
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module Configuration
6
+ module DwhPlatform
7
+ extend ActiveRecord::Dbt::RequiredMethods
8
+
9
+ define_required_methods :source_config_path
10
+
11
+ def dwh_platform=(dwh_platform)
12
+ @dwh_platform = validate_dwh_platform(dwh_platform)
13
+ end
14
+
15
+ def dwh_platform
16
+ @dwh_platform || (raise DwhPlatformIsNullError, "'dwh_platform' is required in '#{source_config_path}'.")
17
+ end
18
+
19
+ private
20
+
21
+ def validate_dwh_platform(dwh_platform)
22
+ return dwh_platform if selectable_dwh_platforms.include?(dwh_platform)
23
+
24
+ raise DoesNotExistOnTheDwhPlatformError, [
25
+ "'#{dwh_platform}' does not exist on the DWH platform.",
26
+ "Please specify one of the following: #{selectable_dwh_platforms.join(', ')}."
27
+ ].join(' ')
28
+ end
29
+
30
+ def selectable_dwh_platforms
31
+ @selectable_dwh_platforms ||= ActiveRecord::Dbt::DataType::Mapper::RUBY_TO_DWH_PLATFORM_TYPE_MAP.keys
32
+ end
33
+
34
+ class DoesNotExistOnTheDwhPlatformError < StandardError; end
35
+ class DwhPlatformIsNullError < StandardError; end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module DwhPlatform
7
+ module ApacheSpark
8
+ # TODO: I have not tried it. I don't know if this is the correct data_type.
9
+ # [Data Types - Spark 3.5.1 Documentation](https://spark.apache.org/docs/latest/sql-ref-datatypes.html)
10
+ RUBY_TO_SPARK_TYPES = {
11
+ binary: 'binary',
12
+ boolean: 'boolean',
13
+ date: 'date',
14
+ datetime: 'timestamp',
15
+ decimal: 'decimal',
16
+ float: 'float',
17
+ integer: 'integer',
18
+ json: 'string',
19
+ string: 'string',
20
+ text: 'string',
21
+ time: 'string'
22
+ }.freeze
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module DwhPlatform
7
+ module Bigquery
8
+ # [Data types  |  BigQuery  |  Google Cloud](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#data_type_list)
9
+ RUBY_TO_BIGQUERY_TYPES = {
10
+ binary: 'bytes',
11
+ boolean: 'bool',
12
+ date: 'date',
13
+ datetime: 'datetime',
14
+ decimal: 'int64',
15
+ float: 'float64',
16
+ integer: 'int64',
17
+ json: 'json',
18
+ string: 'string',
19
+ text: 'string',
20
+ time: 'time'
21
+ }.freeze
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module DwhPlatform
7
+ module PostgreSql
8
+ # TODO: I have not tried it. I don't know if this is the correct data_type.
9
+ # [PostgreSQL: Documentation: 16: Chapter 8. Data Types](https://www.postgresql.org/docs/current/datatype.html)
10
+ RUBY_TO_POSTGRES_TYPES = {
11
+ binary: 'bytea',
12
+ boolean: 'boolean',
13
+ date: 'date',
14
+ datetime: 'timestamp',
15
+ decimal: 'bigint',
16
+ float: 'double precision',
17
+ integer: 'bigint',
18
+ json: 'json',
19
+ string: 'text',
20
+ text: 'text',
21
+ time: 'time'
22
+ }.freeze
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module DwhPlatform
7
+ module Redshift
8
+ # TODO: I have not tried it. I don't know if this is the correct data_type.
9
+ # [Data types - Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html)
10
+ RUBY_TO_REDSHIFT_TYPES = {
11
+ binary: 'varbyte',
12
+ boolean: 'bool',
13
+ date: 'date',
14
+ datetime: 'timestamp',
15
+ decimal: 'decimal',
16
+ float: 'double precision',
17
+ integer: 'integer',
18
+ json: 'super',
19
+ string: 'varchar',
20
+ text: 'varchar',
21
+ time: 'time'
22
+ }.freeze
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module DwhPlatform
7
+ module Snowflake
8
+ # TODO: I have not tried it. I don't know if this is the correct data_type.
9
+ # [Summary of data types | Snowflake Documentation](https://docs.snowflake.com/en/sql-reference/intro-summary-data-types)
10
+ RUBY_TO_SNOWFLAKE_TYPES = {
11
+ binary: 'binary',
12
+ boolean: 'boolean',
13
+ date: 'date',
14
+ datetime: 'datetime',
15
+ decimal: 'decimal',
16
+ float: 'float',
17
+ integer: 'integer',
18
+ json: 'variant',
19
+ string: 'varchar',
20
+ text: 'varchar',
21
+ time: 'time'
22
+ }.freeze
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module DataType
6
+ module Mapper
7
+ include ActiveRecord::Dbt::DataType::DwhPlatform::ApacheSpark
8
+ include ActiveRecord::Dbt::DataType::DwhPlatform::Bigquery
9
+ include ActiveRecord::Dbt::DataType::DwhPlatform::PostgreSql
10
+ include ActiveRecord::Dbt::DataType::DwhPlatform::Redshift
11
+ include ActiveRecord::Dbt::DataType::DwhPlatform::Snowflake
12
+
13
+ extend ActiveRecord::Dbt::RequiredMethods
14
+
15
+ # [Platform-specific data types | dbt Developer Hub](https://docs.getdbt.com/reference/resource-properties/data-types)
16
+ RUBY_TO_DWH_PLATFORM_TYPE_MAP = {
17
+ 'bigquery' => RUBY_TO_BIGQUERY_TYPES,
18
+ 'postgres' => RUBY_TO_POSTGRES_TYPES,
19
+ 'redshift' => RUBY_TO_REDSHIFT_TYPES,
20
+ 'snowflake' => RUBY_TO_SNOWFLAKE_TYPES,
21
+ 'spark' => RUBY_TO_SPARK_TYPES
22
+ }.freeze
23
+
24
+ define_required_methods :column, :@config
25
+
26
+ delegate :dwh_platform, to: :@config
27
+
28
+ private
29
+
30
+ def data_type
31
+ RUBY_TO_DWH_PLATFORM_TYPE_MAP[dwh_platform].fetch(column.type, 'unknown')
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -7,32 +7,39 @@ module ActiveRecord
7
7
  module Table
8
8
  module Testable
9
9
  module UniqueCombinationOfColumnsTestable
10
- REQUIRED_UNIQUE_COMBINATION_OF_COLUMNS_TESTABLE_METHODS = %i[table_name @config].freeze
10
+ extend ActiveRecord::Dbt::RequiredMethods
11
11
 
12
- delegate :used_dbt_utils?, to: :@config
12
+ define_required_methods :table_name, :@config
13
13
 
14
- REQUIRED_UNIQUE_COMBINATION_OF_COLUMNS_TESTABLE_METHODS.each do |method_name|
15
- define_method(method_name) do
16
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
17
- end
18
- end
14
+ delegate :used_dbt_utils?, to: :@config
19
15
 
20
16
  def unique_combination_of_columns_test
21
17
  return nil unless used_dbt_utils?
22
18
 
23
- ActiveRecord::Base.connection.indexes(table_name).each_with_object([]) do |index, array|
24
- next if index.unique == false
25
- next if (unique_indexes = index.columns).size == 1
19
+ indexes.each_with_object([]) do |index, array|
20
+ next if unique_indexes?(index)
26
21
 
27
22
  array.push(
28
23
  {
29
24
  'dbt_utils.unique_combination_of_columns' => {
30
- 'combination_of_columns' => unique_indexes
25
+ 'combination_of_columns' => index.columns
31
26
  }
32
27
  }
33
28
  )
34
29
  end.presence
35
30
  end
31
+
32
+ private
33
+
34
+ def indexes
35
+ ActiveRecord::Base.connection.indexes(table_name)
36
+ end
37
+
38
+ def unique_indexes?(index)
39
+ return true if index.unique == false
40
+
41
+ index.columns.size == 1
42
+ end
36
43
  end
37
44
  end
38
45
  end
@@ -7,33 +7,21 @@ module ActiveRecord
7
7
  module Column
8
8
  module Testable
9
9
  module RelationshipsMetaRelationshipType
10
- REQUIRED_RELATIONSHIP_TYPE_TESTABLE_METHODS = %i[@config foreign_key].freeze
10
+ extend ActiveRecord::Dbt::RequiredMethods
11
11
 
12
- delegate :used_dbterd?, :add_log, to: :@config
12
+ define_required_methods :@config, :foreign_key
13
13
 
14
- REQUIRED_RELATIONSHIP_TYPE_TESTABLE_METHODS.each do |method_name|
15
- define_method(method_name) do
16
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
17
- end
18
- end
14
+ delegate :used_dbterd?, :add_log, to: :@config
19
15
 
20
16
  def relationships_meta_relationship_type
21
17
  return nil unless used_dbterd?
22
- return nil if foreign_key.nil? || relationship_type.blank?
18
+ return nil if no_relationship?
23
19
 
24
20
  {
25
21
  'relationship_type' => relationship_type
26
22
  }
27
23
  rescue NotSpecifiedOrNotInvalidIdError, StandardError => e
28
- add_log(self.class, e)
29
-
30
- {
31
- 'relationship_type' => 'many-to-one',
32
- 'active_record_dbt_error' => {
33
- 'class' => e.class.to_s,
34
- 'message' => e.message.to_s
35
- }
36
- }
24
+ relationships_meta_relationship_type_with_active_record_dbt_error(e)
37
25
  end
38
26
 
39
27
  private
@@ -128,6 +116,22 @@ module ActiveRecord
128
116
  @to_model ||= foreign_key.to_table.classify.constantize
129
117
  end
130
118
 
119
+ def no_relationship?
120
+ foreign_key.nil? || relationship_type.blank?
121
+ end
122
+
123
+ def relationships_meta_relationship_type_with_active_record_dbt_error(error)
124
+ add_log(self.class, error)
125
+
126
+ {
127
+ 'relationship_type' => 'many-to-one',
128
+ 'active_record_dbt_error' => {
129
+ 'class' => error.class.to_s,
130
+ 'message' => error.message.to_s
131
+ }
132
+ }
133
+ end
134
+
131
135
  class NotSpecifiedOrNotInvalidIdError < StandardError; end
132
136
  end
133
137
  end
@@ -43,19 +43,19 @@ module ActiveRecord
43
43
  def sort_columns(columns)
44
44
  columns.sort_by do |column|
45
45
  [
46
- SORT_COLUMN_TYPES.index(column_type(column)) || -1,
46
+ SORT_COLUMN_TYPES.index(data_type(column)) || -1,
47
47
  columns.index(column)
48
48
  ]
49
49
  end
50
50
  end
51
51
 
52
- def column_type(column)
52
+ def data_type(column)
53
53
  if id?(column['name'])
54
54
  'ids'
55
55
  elsif enum?(column['name'])
56
56
  'enums'
57
57
  else
58
- column.dig('meta', 'column_type').pluralize
58
+ column.fetch('data_type', 'unknown').pluralize
59
59
  end
60
60
  end
61
61
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Dbt
5
+ module RequiredMethods
6
+ def define_required_methods(*methods)
7
+ methods.each do |method_name|
8
+ define_method(method_name) do
9
+ raise RequiredImplementationMissingError, "You must implement #{self.class}##{__method__}"
10
+ end
11
+ end
12
+ end
13
+
14
+ class RequiredImplementationMissingError < StandardError; end
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Dbt
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -11,7 +11,5 @@ module ActiveRecord
11
11
 
12
12
  config
13
13
  end
14
-
15
- class Error < StandardError; end
16
14
  end
17
15
  end
@@ -5,6 +5,7 @@ require 'active_record/dbt'
5
5
  ActiveRecord::Dbt.configure do |c|
6
6
  c.config_directory_path = 'lib/dbt'
7
7
  c.export_directory_path = 'doc/dbt'
8
+ c.dwh_platform = 'bigquery'
8
9
  c.data_sync_delayed = false
9
10
  c.used_dbt_package_names = []
10
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-dbt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yamotech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-20 00:00:00.000000000 Z
11
+ date: 2024-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -72,9 +72,16 @@ files:
72
72
  - lib/active_record/dbt/column/testable/unique_testable.rb
73
73
  - lib/active_record/dbt/config.rb
74
74
  - lib/active_record/dbt/configuration/data_sync.rb
75
+ - lib/active_record/dbt/configuration/dwh_platform.rb
75
76
  - lib/active_record/dbt/configuration/logger.rb
76
77
  - lib/active_record/dbt/configuration/parser.rb
77
78
  - lib/active_record/dbt/configuration/used_dbt_package.rb
79
+ - lib/active_record/dbt/data_type/dwh_platform/apache_spark.rb
80
+ - lib/active_record/dbt/data_type/dwh_platform/bigquery.rb
81
+ - lib/active_record/dbt/data_type/dwh_platform/postgre_sql.rb
82
+ - lib/active_record/dbt/data_type/dwh_platform/redshift.rb
83
+ - lib/active_record/dbt/data_type/dwh_platform/snowflake.rb
84
+ - lib/active_record/dbt/data_type/mapper.rb
78
85
  - lib/active_record/dbt/dbt_package/dbt_utils/table/testable/unique_combination_of_columns_testable.rb
79
86
  - lib/active_record/dbt/dbt_package/dbterd/column/testable/relationships_meta_relationship_type.rb
80
87
  - lib/active_record/dbt/factory/columns_factory.rb
@@ -86,6 +93,7 @@ files:
86
93
  - lib/active_record/dbt/model/staging/sql.rb
87
94
  - lib/active_record/dbt/model/staging/yml.rb
88
95
  - lib/active_record/dbt/railtie.rb
96
+ - lib/active_record/dbt/required_methods.rb
89
97
  - lib/active_record/dbt/source/yml.rb
90
98
  - lib/active_record/dbt/table/base.rb
91
99
  - lib/active_record/dbt/table/test.rb