global-registry-bindings 0.1.3 → 0.1.4

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.
@@ -16,103 +16,6 @@ require 'global_registry_bindings/worker'
16
16
 
17
17
  module GlobalRegistry #:nodoc:
18
18
  module Bindings #:nodoc:
19
- # Call this in your model to enable and configure Global Registry bindings.
20
- #
21
- # Options:
22
- #
23
- # * `:binding`: Type of Global Registry binding. Either `:entity` or `:relationship`.
24
- # (default: `:entity`)
25
- #
26
- # * `:id_column`: Column used to track the Global Registry ID for the model instance or relationship entity.
27
- # Can be a :string or :uuid column. (default: `:global_registry_id`) **[`:entity`, `:relationship`]**
28
- #
29
- # * `:type`: Global Registry entity type. Accepts a Symbol or a Proc. Symbol is the name of the entity type, Proc
30
- # is passed the model instance and must return a symbol which is the entity type. Default value is underscored
31
- # name of the model. Ex: ```type: proc { |model| model.name.to_sym }```. When used in a `:relationship`, `:type`
32
- # is a unique name to identify the relationship. **[`:entity`, `:relationship`]**
33
- #
34
- # * `:push_on`: Array of Active Record lifecycle events used to push changes to Global Registry.
35
- # (default: `[:create, :update, :destroy]`) **[`:entity`]**
36
- #
37
- # * `:parent_association`: Name of the Active Record parent association. Must be defined before calling
38
- # global_registry_bindings in order to determine foreign_key for use in exclude. Used to create a
39
- # hierarchy or to push child entity types. (Ex: person -> address) (default: `nil`) **[`:entity`]**
40
- #
41
- # * `:parent_association_class`: Class name of the parent model. Required if `:parent_association` can not be used
42
- # to determine the parent class. This can happen if parent is defined by another gem, like `ancestry`.
43
- # (default: `nil`) **[`:entity`]**
44
- #
45
- # * `:primary_binding`: Determines what type of global-registry-binding the primary association points to. Defaults
46
- # to `:entity`, but can be set to a `:relationship` type name (ex: `:assignment`) to create a relationship_type
47
- # between a relationship and an entity. (default: `:entity`) **[`:relationship`]**
48
- #
49
- # * `:primary_association`: Name of the Active Record primary association. Must be defined before calling
50
- # global_registry_bindings in order to determine foreign_key for use in exclude. (default: `nil`)
51
- # **[`:relationship`]**
52
- #
53
- # * `:primary_association_class`: Class name of the primary model. Required if `:primary_association` can not be
54
- # used to determine the parent class. This can happen if parent is defined by another gem, like `ancestry`.
55
- # (default: `self.class`) **[`:relationship`]**
56
- #
57
- # * `:primary_association_foreign_key`: Foreign Key column for the primary association. Used if foreign_key can
58
- # not be determined from `:primary_association`. (default: `:primary_association.foreign_key`)
59
- # **[`:relationship`]**
60
- #
61
- # * `:related_association`: Name of the Active Record related association. Active Record association must be
62
- # defined before calling global_registry_bindings in order to determine the foreign key.
63
- # (default: `nil`) **[`:relationship`]**
64
- #
65
- # * `:related_association_class`: Class name of the related model. Required if `:related_association` can not be
66
- # used to determine the related class. (default: `nil`) **[`:relationship`]**
67
- #
68
- # * `:related_association_foreign_key`: Foreign Key column for the related association. Used if foreign_key can
69
- # not be determined from `:primary_association`. (default: `:primary_association.foreign_key`)
70
- # **[`:relationship`]**
71
- #
72
- # * `:primary_relationship_name`: **Required** Name of primary relationship. Should be unique to prevent
73
- # ambiguous relationship names. (default: `nil`) **[`:relationship`]**
74
- #
75
- # * `:related_relationship_name`: **Required** Name of the related relationship. Should be unique to prevent
76
- # ambiguous relationship names (default: `nil`) **[`:relationship`]**
77
- #
78
- # * `:related_association_type`: Name of the related association entity_type. Required if unable to determined
79
- # `:type` from related. (default: `nil`) **[`:relationship`]**
80
- #
81
- # * `:related_global_registry_id`: Global Registry ID of a remote related entity. Proc or Symbol. Implementation
82
- # should cache this as it may be requested multiple times. (default: `nil`) **[`:relationship`]**
83
- #
84
- # * `:ensure_relationship_type`: Ensure Global Registry RelationshipType exists and is up to date.
85
- # (default: `true`) **[`:relationship`]**
86
- #
87
- # * `:ensure_entity_type`: Ensure Global Registry Entity Type exists and is up to date.
88
- # (default: `true`) **[`:entity`]**
89
- #
90
- # * `:client_integration_id`: Client Integration ID for relationship. Proc or Symbol.
91
- # (default: `:primary_association.id`) **[`:relationship`]**
92
- #
93
- # * `:exclude`: Array, Proc or Symbol. Array of Model fields (as symbols) to exclude when pushing to Global
94
- # Registry. Array Will additionally include `:mdm_id_column` and `:parent_association` foreign key when defined.
95
- # If Proc, is passed type and model instance and should return an Array of the fields to exclude. If Symbol,
96
- # this should be a method name the Model instance responds to. It is passed the type and should return an Array
97
- # of fields to exclude. When Proc or Symbol are used, you must explicitly return the standard defaults.
98
- # (default: `[:id, :created_at, :updated_at, :global_registry_id]`) **[`:entity`, `:relationship`]**
99
- #
100
- # * `:fields`: Additional fields to send to Global Registry. Hash, Proc or Symbol. As a Hash, names are the
101
- # keys and :type attributes are the values. Ex: `{language: :string}`. Name is a symbol and type is an
102
- # ActiveRecord column type. As a Proc, it is passed the type and model instance, and should return a Hash.
103
- # As a Symbol, the model should respond to this method, is passed the type, and should return a Hash.
104
- # **[`:entity`, `:relationship`]**
105
- #
106
- # * `:include_all_columns`: Include all model columns in the fields to push to Global Registry. If `false`, fields
107
- # must be defined in the `:fields` option. (default: `false`) **[`:entity`, `:relationship`]**
108
- #
109
- # * `:mdm_id_column`: Column used to enable MDM tracking and set the name of the column. MDM is disabled when this
110
- # option is nil or empty. (default: `nil`) **[`:entity`]**
111
- #
112
- # * `:mdm_timeout`: Only pull mdm information at most once every `:mdm_timeout`. (default: `1.minute`)
113
- # **[`:entity`]**
114
- #
115
- # @api public
116
19
  def global_registry_bindings(options = {})
117
20
  options[:binding] ||= :entity
118
21
  unless method_defined? :_global_registry_bindings_options
@@ -61,8 +61,8 @@ module GlobalRegistry #:nodoc:
61
61
  # rubocop:disable Metrics/PerceivedComplexity
62
62
  # rubocop:disable Metrics/AbcSize
63
63
  def global_registry_relationship_change_action(type)
64
- [global_registry_relationship(type).primary_association_foreign_key,
65
- global_registry_relationship(type).related_association_foreign_key].each do |key|
64
+ [global_registry_relationship(type).primary_foreign_key,
65
+ global_registry_relationship(type).related_foreign_key].each do |key|
66
66
  if previous_changes.key?(key)
67
67
  # Delete if changed from anything to nil
68
68
  return :delete if previous_changes[key].last.nil?
@@ -11,8 +11,8 @@ module GlobalRegistry #:nodoc:
11
11
  :type,
12
12
  :mdm_timeout,
13
13
  :push_on,
14
- :parent_association,
15
- :parent_association_class,
14
+ :parent,
15
+ :parent_class,
16
16
  :exclude,
17
17
  :fields, to: :@options
18
18
 
@@ -21,8 +21,8 @@ module GlobalRegistry #:nodoc:
21
21
  @options = OpenStruct.new model_class._global_registry_bindings_options[:entity]
22
22
  end
23
23
 
24
- def ensure_entity_type?
25
- @options.ensure_entity_type.present?
24
+ def ensure_type?
25
+ @options.ensure_type.present?
26
26
  end
27
27
 
28
28
  def include_all_columns?
@@ -8,10 +8,8 @@ module GlobalRegistry #:nodoc:
8
8
  :mdm_id_column,
9
9
  :mdm_timeout,
10
10
  :push_on,
11
- :parent_association,
12
- :parent_association_class,
13
11
  :mdm_worker_class_name,
14
- :ensure_entity_type?,
12
+ :ensure_type?,
15
13
  :include_all_columns?,
16
14
  to: :@class_options
17
15
 
@@ -38,12 +36,12 @@ module GlobalRegistry #:nodoc:
38
36
  end
39
37
 
40
38
  def parent
41
- @model.send(parent_association) if parent_association.present?
39
+ @model.send(@class_options.parent) if @class_options.parent.present?
42
40
  end
43
41
 
44
42
  def parent_class
45
- return if parent_association.blank?
46
- parent_association_class
43
+ return if @class_options.parent.blank?
44
+ @class_options.parent_class
47
45
  end
48
46
 
49
47
  def parent_type
@@ -55,11 +53,11 @@ module GlobalRegistry #:nodoc:
55
53
  end
56
54
 
57
55
  def parent_required?
58
- parent_association.present? && !parent_is_self?
56
+ @class_options.parent.present? && !parent_is_self?
59
57
  end
60
58
 
61
59
  def parent_is_self?
62
- parent_association.present? && parent_class == @model.class
60
+ @class_options.parent.present? && parent_class == @model.class
63
61
  end
64
62
 
65
63
  def exclude
@@ -10,22 +10,23 @@ module GlobalRegistry #:nodoc:
10
10
 
11
11
  def defaults
12
12
  {
13
+ binding: :entity,
13
14
  id_column: :global_registry_id,
14
15
  mdm_id_column: nil,
15
16
  type: @model_class.name.demodulize.underscore.to_sym,
16
17
  push_on: %i[create update destroy],
17
- parent_association: nil,
18
- parent_association_class: nil,
19
- parent_relationship_name: nil,
18
+ parent: nil,
19
+ parent_class: nil,
20
20
  exclude: %i[id created_at updated_at],
21
21
  fields: {},
22
22
  include_all_columns: false,
23
23
  mdm_timeout: 1.minute,
24
- ensure_entity_type: true
24
+ ensure_type: true
25
25
  }.freeze
26
26
  end
27
27
 
28
28
  def parse(options_hash = {})
29
+ validate_options! options_hash
29
30
  merge_defaults options_hash
30
31
  update_association_classes
31
32
  update_excludes
@@ -34,6 +35,11 @@ module GlobalRegistry #:nodoc:
34
35
 
35
36
  private
36
37
 
38
+ def validate_options!(options = {})
39
+ unknown = options.keys - defaults.keys
40
+ raise ArgumentError, "global-registry-bindings: Unknown options (#{unknown.join ', '})" unless unknown.empty?
41
+ end
42
+
37
43
  def merge_defaults(options_hash = {})
38
44
  @options = defaults.merge(options_hash) do |key, oldval, newval|
39
45
  if key == :exclude
@@ -50,8 +56,8 @@ module GlobalRegistry #:nodoc:
50
56
  end
51
57
 
52
58
  def update_association_classes
53
- unless @options[:parent_association_class] # rubocop:disable Style/GuardClause
54
- @options[:parent_association_class] = association_class @options[:parent_association]
59
+ unless @options[:parent_class] # rubocop:disable Style/GuardClause
60
+ @options[:parent_class] = association_class @options[:parent]
55
61
  end
56
62
  end
57
63
 
@@ -60,7 +66,7 @@ module GlobalRegistry #:nodoc:
60
66
  @options[:exclude] << @options[:id_column]
61
67
  @options[:exclude] << @options[:mdm_id_column] if @options[:mdm_id_column].present?
62
68
 
63
- parent_id_column = association_foreign_key @options[:parent_association]
69
+ parent_id_column = association_foreign_key @options[:parent]
64
70
  @options[:exclude] << parent_id_column.to_sym if parent_id_column
65
71
  end
66
72
 
@@ -11,15 +11,15 @@ module GlobalRegistry #:nodoc:
11
11
  :push_on,
12
12
  :client_integration_id,
13
13
  :primary_binding,
14
- :primary_association,
15
- :primary_association_class,
16
- :primary_association_foreign_key,
17
- :primary_relationship_name,
18
- :related_association,
19
- :related_association_class,
20
- :related_association_foreign_key,
21
- :related_association_type,
22
- :related_relationship_name,
14
+ :primary,
15
+ :primary_class,
16
+ :primary_foreign_key,
17
+ :primary_name,
18
+ :related,
19
+ :related_class,
20
+ :related_foreign_key,
21
+ :related_type,
22
+ :related_name,
23
23
  :related_global_registry_id,
24
24
  :exclude,
25
25
  :fields, to: :@options
@@ -29,8 +29,8 @@ module GlobalRegistry #:nodoc:
29
29
  @options = OpenStruct.new model_class._global_registry_bindings_options[:relationships][type]
30
30
  end
31
31
 
32
- def ensure_relationship_type?
33
- @options.ensure_relationship_type.present?
32
+ def ensure_type?
33
+ @options.ensure_type.present?
34
34
  end
35
35
 
36
36
  def rename_entity_type?
@@ -7,13 +7,9 @@ module GlobalRegistry #:nodoc:
7
7
  delegate :id_column,
8
8
  :push_on,
9
9
  :primary_binding,
10
- :primary_association,
11
- :primary_association_class,
12
- :primary_association_foreign_key,
13
- :related_association,
14
- :related_association_class,
15
- :related_association_foreign_key,
16
- :ensure_relationship_type?,
10
+ :primary_foreign_key,
11
+ :related_foreign_key,
12
+ :ensure_type?,
17
13
  :rename_entity_type?,
18
14
  :include_all_columns?,
19
15
  to: :@class_options
@@ -53,12 +49,12 @@ module GlobalRegistry #:nodoc:
53
49
  end
54
50
 
55
51
  def primary
56
- return @model.send(primary_association) if primary_association.present?
52
+ return @model.send(@class_options.primary) if @class_options.primary.present?
57
53
  @model
58
54
  end
59
55
 
60
56
  def primary_class
61
- primary_association_class || primary.class
57
+ @class_options.primary_class || primary.class
62
58
  end
63
59
 
64
60
  def primary_type
@@ -83,16 +79,16 @@ module GlobalRegistry #:nodoc:
83
79
  primary_class == @model.class
84
80
  end
85
81
 
86
- def primary_relationship_name
87
- @class_options.primary_relationship_name || primary_type
82
+ def primary_name
83
+ @class_options.primary_name || primary_type
88
84
  end
89
85
 
90
86
  def related
91
- @model.send(related_association) if related_association.present?
87
+ @model.send(@class_options.related) if @class_options.related.present?
92
88
  end
93
89
 
94
90
  def related_type
95
- @class_options.related_association_type || related&.global_registry_entity&.type
91
+ @class_options.related_type || related&.global_registry_entity&.type
96
92
  end
97
93
 
98
94
  def related_id_value
@@ -107,8 +103,8 @@ module GlobalRegistry #:nodoc:
107
103
  end
108
104
  end
109
105
 
110
- def related_relationship_name
111
- @class_options.related_relationship_name || related_type
106
+ def related_name
107
+ @class_options.related_name || related_type
112
108
  end
113
109
 
114
110
  def exclude
@@ -10,22 +10,19 @@ module GlobalRegistry #:nodoc:
10
10
 
11
11
  def defaults
12
12
  {
13
- id_column: :global_registry_id,
13
+ binding: :relationship, id_column: :global_registry_id,
14
14
  type: @model_class.name.demodulize.underscore.to_sym,
15
- client_integration_id: :id, primary_binding: :entity,
16
- primary_association: nil,
17
- primary_association_class: nil,
18
- primary_relationship_name: nil,
19
- related_association: nil,
20
- related_association_class: nil, related_association_type: nil,
21
- related_relationship_name: nil,
15
+ client_integration_id: :id,
16
+ primary_binding: :entity, primary: nil, primary_class: nil, primary_name: nil, primary_foreign_key: nil,
17
+ related: nil, related_class: nil, related_type: nil, related_name: nil, related_foreign_key: nil,
22
18
  related_global_registry_id: nil,
23
19
  exclude: %i[id created_at updated_at], include_all_columns: false,
24
- fields: {}, ensure_relationship_type: true, rename_entity_type: true
20
+ fields: {}, ensure_type: true, rename_entity_type: true
25
21
  }.freeze
26
22
  end
27
23
 
28
24
  def parse(options_hash = {})
25
+ validate_options! options_hash
29
26
  merge_defaults(options_hash)
30
27
  update_association_classes
31
28
  update_foreign_keys
@@ -35,6 +32,11 @@ module GlobalRegistry #:nodoc:
35
32
 
36
33
  private
37
34
 
35
+ def validate_options!(options = {})
36
+ unknown = options.keys - defaults.keys
37
+ raise ArgumentError, "global-registry-bindings: Unknown options (#{unknown.join ', '})" unless unknown.empty?
38
+ end
39
+
38
40
  def merge_defaults(options_hash = {})
39
41
  @options = defaults.merge(options_hash) do |key, oldval, newval|
40
42
  if key == :exclude
@@ -51,24 +53,24 @@ module GlobalRegistry #:nodoc:
51
53
  end
52
54
 
53
55
  def update_association_classes
54
- unless @options[:primary_association_class]
55
- @options[:primary_association_class] = if @options[:primary_association]
56
- association_class @options[:primary_association]
57
- else
58
- @model_class
59
- end
56
+ unless @options[:primary_class]
57
+ @options[:primary_class] = if @options[:primary]
58
+ association_class @options[:primary]
59
+ else
60
+ @model_class
61
+ end
60
62
  end
61
- unless @options[:related_association_class] # rubocop:disable Style/GuardClause
62
- @options[:related_association_class] = association_class @options[:related_association]
63
+ unless @options[:related_class] # rubocop:disable Style/GuardClause
64
+ @options[:related_class] = association_class @options[:related]
63
65
  end
64
66
  end
65
67
 
66
68
  def update_foreign_keys
67
- unless @options[:primary_association_foreign_key]
68
- @options[:primary_association_foreign_key] = association_foreign_key @options[:primary_association]
69
+ unless @options[:primary_foreign_key]
70
+ @options[:primary_foreign_key] = association_foreign_key @options[:primary]
69
71
  end
70
- unless @options[:related_association_foreign_key] # rubocop:disable Style/GuardClause
71
- @options[:related_association_foreign_key] = association_foreign_key @options[:related_association]
72
+ unless @options[:related_foreign_key] # rubocop:disable Style/GuardClause
73
+ @options[:related_foreign_key] = association_foreign_key @options[:related]
72
74
  end
73
75
  end
74
76
 
@@ -77,11 +79,11 @@ module GlobalRegistry #:nodoc:
77
79
  @options[:exclude] << @options[:id_column]
78
80
  @options[:exclude] << @options[:mdm_id_column] if @options[:mdm_id_column].present?
79
81
 
80
- if @options[:primary_association_foreign_key]
81
- @options[:exclude] << @options[:primary_association_foreign_key]
82
+ if @options[:primary_foreign_key]
83
+ @options[:exclude] << @options[:primary_foreign_key]
82
84
  end
83
- if @options[:related_association_foreign_key] # rubocop:disable Style/GuardClause
84
- @options[:exclude] << @options[:related_association_foreign_key]
85
+ if @options[:related_foreign_key] # rubocop:disable Style/GuardClause
86
+ @options[:exclude] << @options[:related_foreign_key]
85
87
  end
86
88
  end
87
89
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GlobalRegistry #:nodoc:
4
4
  module Bindings #:nodoc:
5
- VERSION = '0.1.3'
5
+ VERSION = '0.1.4'
6
6
  end
7
7
  end
@@ -13,7 +13,7 @@ RSpec.describe 'GlobalRegistry::Bindings' do
13
13
  it 'should have default values for all options' do
14
14
  expect(Default.global_registry_entity.id_column).to be :global_registry_id
15
15
  expect(Default.global_registry_entity.mdm_id_column).to be nil
16
- expect(Default.global_registry_entity.parent_association).to be nil
16
+ expect(Default.global_registry_entity.parent).to be nil
17
17
  expect(Default.global_registry_entity.push_on)
18
18
  .to contain_exactly(:create, :update, :destroy)
19
19
  expect(Default.global_registry_entity.mdm_timeout).to eq 1.minute
@@ -42,7 +42,7 @@ RSpec.describe 'GlobalRegistry::Bindings' do
42
42
  expect(Address.global_registry_entity.id_column).to be :global_registry_id
43
43
  expect(Address.global_registry_entity.mdm_id_column).to be nil
44
44
  expect(Address.global_registry_entity.type).to be :address
45
- expect(Address.global_registry_entity.parent_association).to be :person
45
+ expect(Address.global_registry_entity.parent).to be :person
46
46
  expect(Address.global_registry_entity.exclude).to be_a Proc
47
47
  expect(address.global_registry_entity.exclude)
48
48
  .to contain_exactly(:global_registry_id, :id, :created_at, :updated_at, :person_id, :address1)
@@ -57,7 +57,7 @@ RSpec.describe 'GlobalRegistry::Bindings' do
57
57
  expect(Organization.global_registry_entity.mdm_id_column).to be nil
58
58
  expect(Organization.global_registry_entity.type).to be_a Proc
59
59
  expect(org.global_registry_entity.type).to be :fancy_org
60
- expect(Organization.global_registry_entity.parent_association).to be :parent
60
+ expect(Organization.global_registry_entity.parent).to be :parent
61
61
  expect(Organization.global_registry_entity.push_on).to be_an(Array).and eq(%i[create destroy])
62
62
  expect(Organization.global_registry_entity.exclude).to be_a Symbol
63
63
  expect(org.global_registry_entity.exclude)
@@ -72,10 +72,10 @@ RSpec.describe 'GlobalRegistry::Bindings' do
72
72
  assignment = build(:assignment, person: person, organization: org)
73
73
  expect(Assignment.global_registry_relationship(:fancy_org_assignment).id_column).to be :global_registry_id
74
74
  expect(Assignment.global_registry_relationship(:fancy_org_assignment).type).to be :fancy_org_assignment
75
- expect(Assignment.global_registry_relationship(:fancy_org_assignment).primary_association).to be :person
76
- expect(Assignment.global_registry_relationship(:fancy_org_assignment).related_association).to be :organization
77
- expect(assignment.global_registry_relationship(:fancy_org_assignment).primary_relationship_name).to be :person
78
- expect(assignment.global_registry_relationship(:fancy_org_assignment).related_relationship_name).to be :fancy_org
75
+ expect(Assignment.global_registry_relationship(:fancy_org_assignment).primary).to be :person
76
+ expect(Assignment.global_registry_relationship(:fancy_org_assignment).related).to be :organization
77
+ expect(assignment.global_registry_relationship(:fancy_org_assignment).primary_name).to be :person
78
+ expect(assignment.global_registry_relationship(:fancy_org_assignment).related_name).to be :fancy_org
79
79
  expect(assignment.global_registry_relationship(:fancy_org_assignment).exclude)
80
80
  .to contain_exactly(:global_registry_id, :id, :created_at, :updated_at, :person_id, :organization_id,
81
81
  :assigned_by_gr_rel_id, :assigned_by_id)