global-registry-bindings 0.1.3 → 0.1.4

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