cru_lib 0.0.6 → 0.1.2

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
- SHA1:
3
- metadata.gz: 3ca87f01a10819552466a88828a6765bfcd4ba8c
4
- data.tar.gz: 2e474d95a22698c1d5a2269ea083ed3a99a700bd
2
+ SHA256:
3
+ metadata.gz: 728c78d6c47945aca14a06d298d49c81980d6dc841dee906fca34d5057765513
4
+ data.tar.gz: cbc0424afd867582c214f486acea47017c19ea593b4ac2f3bc3144d66646cd02
5
5
  SHA512:
6
- metadata.gz: ea2d79e896fc7c21e8634082912a4c0956a4d3cf2d487b89f1969da36610e18be47f0646df77d57ca99a5d9314821a0db88a4b205d120f514daf082d06f81f1f
7
- data.tar.gz: 7ae0567d3331b5065c7f6e85e93b93e584b2327758ff92f441ad9a26f4f61179632f8861350e12013180f4e5efae6cdf045615e705a00b36e3ca2dc4d1438ddb
6
+ metadata.gz: 72c7463e6c6df87f0273607c04fe9ffb6fd27353c2fc1617a9610cf95dcc659da78baeb54879f46b9ef32df57ed1985d233154a3e4ba1682ec0f79f034949586
7
+ data.tar.gz: e1dea8dbc805b803e7889970f7ea1f1d1689e790af86a52ad5278406132403a420ddd7ca6a1ae8e5b1813efd4f06ededc2eabed88139738c6ce70af4633b7801
data/.gitignore CHANGED
@@ -21,4 +21,4 @@ tmp
21
21
  *.a
22
22
  mkmf.log
23
23
  .idea
24
- *.iml
24
+ vendor/ruby
data/cru_lib.gemspec CHANGED
@@ -1,4 +1,6 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  lib = File.expand_path('../lib', __FILE__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'cru_lib/version'
@@ -8,19 +10,25 @@ Gem::Specification.new do |spec|
8
10
  spec.version = CruLib::VERSION
9
11
  spec.authors = ['Josh Starcher']
10
12
  spec.email = ['josh.starcher@gmail.com']
11
- spec.summary = %q{Misc libraries for Cru}
12
- spec.description = %q{Collection of common ruby logic used by a number of Cru apps}
13
- spec.homepage = ''
13
+ spec.summary = 'Map ActiveRecord to Global Registry'
14
+ spec.description = 'Provides a common interface for mapping ActiveRecord ' \
15
+ 'models to Global Registry entities and relationships.'
16
+ spec.homepage = 'https://github.com/CruGlobal/cru_lib'
14
17
  spec.license = 'MIT'
15
18
 
16
19
  spec.files = `git ls-files -z`.split("\x0")
17
20
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
22
  spec.require_paths = ['lib']
20
- spec.add_dependency 'global_registry'
21
- spec.add_dependency 'active_model_serializers'
22
- spec.add_dependency 'redis'
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.6'
25
- spec.add_development_dependency 'rake'
24
+ spec.add_dependency 'global_registry', '~> 1.0'
25
+
26
+ spec.add_runtime_dependency 'rails', '>= 6.0'
27
+ spec.add_runtime_dependency 'activesupport', '>= 6.0'
28
+
29
+ spec.add_development_dependency 'bundler', '~> 2.3'
30
+ spec.add_development_dependency 'rake', '~> 13'
31
+
32
+ spec.add_development_dependency 'rspec-rails', '~> 5'
33
+ spec.add_development_dependency 'sidekiq', '~> 6'
26
34
  end
@@ -0,0 +1,40 @@
1
+ module CruLib
2
+ module GlobalRegistryMasterPersonMethods
3
+ extend ActiveSupport::Concern
4
+ include CruLib::GlobalRegistryMethods
5
+
6
+ included do
7
+ after_commit :retrieve_gr_master_person_id, on: [:create, :update]
8
+ end
9
+
10
+ def retrieve_gr_master_person_id
11
+ return unless respond_to?(:gr_master_person_id)
12
+ async("async_retrieve_gr_master_person_id")
13
+ end
14
+
15
+ def async_retrieve_gr_master_person_id
16
+ fail CruLib::NoGlobalRegistryIdError, "Person #{id} has no global_registry_id; will retry" unless global_registry_id
17
+ begin
18
+ person_entity = GlobalRegistry::Entity.find(global_registry_id, 'filters[owned_by]' => 'mdm')
19
+ rescue RestClient::ResourceNotFound
20
+ Rails.logger.info "GR entity #{global_registry_id} for Person #{id} does not exist; will _not_ retry"
21
+ return
22
+ end
23
+ mdm_entity_id = Array.wrap(person_entity.dig('entity', 'person', 'master_person:relationship'))
24
+ .first # although there should not be more than one
25
+ .try(:[], 'master_person')
26
+ fail CruLib::NoGlobalRegistryMasterPersonError, "GR entity #{global_registry_id} for Person #{id} has no master_person; will retry" unless mdm_entity_id
27
+ update_columns(gr_master_person_id: mdm_entity_id)
28
+ end
29
+
30
+ module ClassMethods
31
+ def skip_fields_for_gr
32
+ super + %w(gr_master_person_id)
33
+ end
34
+ end
35
+ end
36
+
37
+ class NoGlobalRegistryIdError < StandardError; end
38
+
39
+ class NoGlobalRegistryMasterPersonError < StandardError; end
40
+ end
@@ -6,21 +6,20 @@ module CruLib
6
6
  extend ActiveSupport::Concern
7
7
  include CruLib::Async
8
8
 
9
-
10
9
  included do
11
- after_commit :push_to_global_registry
12
- after_destroy :delete_from_global_registry
10
+ after_commit :push_to_global_registry, on: [ :create, :update ]
11
+ after_commit :delete_from_global_registry, on: :destroy
13
12
  end
14
13
 
15
14
  def delete_from_global_registry
16
15
  if global_registry_id
17
- Sidekiq::Client.enqueue(self.class, nil, :async_delete_from_global_registry, global_registry_id)
16
+ Sidekiq::Client.enqueue(self.class, nil, "async_delete_from_global_registry", global_registry_id)
18
17
  end
19
18
  end
20
19
 
21
20
  # Define default push method
22
21
  def push_to_global_registry
23
- async(:async_push_to_global_registry)
22
+ async("async_push_to_global_registry")
24
23
  end
25
24
 
26
25
  def async_push_to_global_registry(parent_id = nil, parent_type = nil, parent = nil)
@@ -43,7 +42,7 @@ module CruLib
43
42
  @attributes_to_push = {}
44
43
  attributes_to_push['client_integration_id'] = id unless self.class.skip_fields_for_gr.include?('client_integration_id')
45
44
  attributes_to_push['client_updated_at'] = updated_at if respond_to?(:updated_at)
46
- attributes.collect {|k, v| @attributes_to_push[k.underscore] = self.class.gr_value(k.underscore, v)}
45
+ attributes.each {|k, v| @attributes_to_push[k.underscore] = self.class.gr_value(k.underscore, v)}
47
46
  @attributes_to_push.select! {|k, v| v.present? && !self.class.skip_fields_for_gr.include?(k)}
48
47
  end
49
48
  @attributes_to_push
@@ -102,7 +101,7 @@ module CruLib
102
101
 
103
102
  columns_to_push.each do |column|
104
103
  unless existing_fields.include?(column[:name])
105
- GlobalRegistry::EntityType.post(entity_type: {name: column[:name], parent_id: entity_type['id'], field_type: column[:type]})
104
+ GlobalRegistry::EntityType.post(entity_type: {name: column[:name], parent_id: entity_type['id'], field_type: column[:field_type]})
106
105
  end
107
106
  end
108
107
  end
@@ -10,7 +10,7 @@ module CruLib
10
10
  # TODO - deleting a relationship is different.
11
11
  def delete_from_global_registry
12
12
  if global_registry_id
13
- Sidekiq::Client.enqueue(self.class, nil, :async_delete_from_global_registry, global_registry_id)
13
+ Sidekiq::Client.enqueue(self.class, nil, "async_delete_from_global_registry", global_registry_id)
14
14
  end
15
15
  end
16
16
 
@@ -46,7 +46,11 @@ module CruLib
46
46
 
47
47
  global_registry_id = Array.wrap(
48
48
  entity[base_object.class.global_registry_entity_type_name]["#{relationship_name}:relationship"]
49
- ).detect { |hash| hash['client_integration_id'] == id.to_s }['relationship_entity_id']
49
+ ).detect do |hash|
50
+ cid = hash['client_integration_id']
51
+ cid = cid['value'] if cid.is_a?(Hash)
52
+ cid == id.to_s
53
+ end['relationship_entity_id']
50
54
 
51
55
  update_column(:global_registry_id, global_registry_id)
52
56
 
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CruLib
4
+ class Railtie < Rails::Railtie
5
+ initializer 'crulib_railtie.configure_rollbar' do
6
+ if Module::const_defined? :Rollbar
7
+ ::Rollbar.configure do |config|
8
+ config.exception_level_filters.merge!('CruLib::NoGlobalRegistryIdError' => 'ignore',
9
+ 'CruLib::NoGlobalRegistryMasterPersonError' => 'ignore')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module CruLib
2
- VERSION = "0.0.6"
2
+ VERSION = '0.1.2'
3
3
  end
data/lib/cru_lib.rb CHANGED
@@ -2,35 +2,8 @@ require 'cru_lib/version'
2
2
  require 'cru_lib/async'
3
3
  require 'cru_lib/global_registry_methods'
4
4
  require 'cru_lib/global_registry_relationship_methods'
5
- require 'cru_lib/access_token'
6
- require 'cru_lib/access_token_serializer'
7
- require 'cru_lib/access_token_protected_concern'
8
- require 'cru_lib/api_error'
9
- require 'cru_lib/api_error_serializer'
10
- require 'redis'
5
+ require 'cru_lib/global_registry_master_person_methods'
6
+ require 'cru_lib/railtie'
11
7
 
12
8
  module CruLib
13
- class << self
14
- attr_accessor :redis_host, :redis_port, :redis_db, :redis_client
15
-
16
- def configure
17
- yield self
18
- end
19
-
20
- def redis_host
21
- @redis_host ||= 'localhost'
22
- end
23
-
24
- def redis_port
25
- @redis_port ||= '6379'
26
- end
27
-
28
- def redis_db
29
- @redis_db ||= 2
30
- end
31
-
32
- def redis_client
33
- Redis.new(:host => CruLib.redis_host, :port => CruLib.redis_port, :db => CruLib.redis_db)
34
- end
35
- end
36
9
  end
@@ -0,0 +1,19 @@
1
+
2
+ # Mock ActiveRecord::RecordNotFound
3
+ #
4
+ module ActiveRecord
5
+ class RecordNotFound < StandardError
6
+ end
7
+ end
8
+
9
+ # ActiveRecord-ish - a mocked ActiveRecord that behaves like a model class with id
10
+ #
11
+ class ActiveRecordIsh
12
+ attr_accessor :id
13
+
14
+ def self.find(id)
15
+ obj = self.new
16
+ obj.id = id
17
+ obj
18
+ end
19
+ end
@@ -0,0 +1,90 @@
1
+
2
+ require 'cru_lib/async'
3
+ require_relative 'async_commons'
4
+
5
+ require 'sidekiq/testing'
6
+ Sidekiq::Testing.inline!
7
+
8
+ # The class includes Sidekiq worker and responds properly to Async calls
9
+ #
10
+ class SidekiqAsync < ActiveRecordIsh
11
+ include Sidekiq::Worker
12
+ include CruLib::Async
13
+ end
14
+
15
+
16
+ describe CruLib::Async do
17
+ describe 'when there is no id' do
18
+ before(:each) do
19
+ @tested = SidekiqAsync.new
20
+ end
21
+
22
+ it 'calls class method when one argument' do
23
+ param_1 = SecureRandom.uuid
24
+
25
+ # Expect class method get called with just one parameter
26
+ #
27
+ expect(SidekiqAsync).to receive(:method_1) do |arg_1, *arg_2|
28
+ expect(arg_1).to eq(param_1)
29
+ expect(arg_2.length).to eq(0)
30
+ end
31
+
32
+ @tested.async("method_1", param_1)
33
+ end
34
+
35
+ it 'calls class method when two arguments' do
36
+ param_1 = SecureRandom.uuid
37
+ param_2 = SecureRandom.uuid
38
+
39
+ # Expect class method get called with two parameters
40
+ #
41
+ expect(SidekiqAsync).to receive(:method_2) do |arg_1, arg_2, *arg_3|
42
+ expect(arg_1).to eq(param_1)
43
+ expect(arg_2).to eq(param_2)
44
+ expect(arg_3.length).to eq(0)
45
+ end
46
+
47
+ @tested.async("method_2", param_1, param_2)
48
+ end
49
+ end
50
+
51
+ describe 'with id' do
52
+ before(:each) do
53
+ @tested = SidekiqAsync.new
54
+ @id = SecureRandom.random_number(100_000)
55
+ @tested.id = @id
56
+ end
57
+
58
+ it 'calls instance method properly when one argument' do
59
+ param_1 = SecureRandom.uuid
60
+
61
+ # Expect instance method get called with one parameter
62
+ # The object's attribute id is properly set
63
+ #
64
+ expect_any_instance_of(SidekiqAsync).to receive(:inst_method_1) do |object, arg_1, *arg_2|
65
+ expect(object.id).to eq(@id)
66
+ expect(arg_1).to eq(param_1)
67
+ expect(arg_2.length).to eq(0)
68
+ end
69
+
70
+ @tested.async("inst_method_1", param_1)
71
+ end
72
+
73
+ it 'calls instance method properly when two arguments' do
74
+ param_1 = SecureRandom.uuid
75
+ param_2 = SecureRandom.uuid
76
+
77
+ # Expect instance method get called with two parameters
78
+ # The object's attribute id is properly set
79
+ #
80
+ expect_any_instance_of(SidekiqAsync).to receive(:inst_method_2) do |object, arg_1, arg_2, *arg_3|
81
+ expect(object.id).to eq(@id)
82
+ expect(arg_1).to eq(param_1)
83
+ expect(arg_2).to eq(param_2)
84
+ expect(arg_3.length).to eq(0)
85
+ end
86
+
87
+ @tested.async("inst_method_2", param_1, param_2)
88
+ end
89
+ end
90
+ end
metadata CHANGED
@@ -1,86 +1,115 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cru_lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Starcher
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-11 00:00:00.000000000 Z
11
+ date: 2022-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: global_registry
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: active_model_serializers
28
+ name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '6.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: redis
42
+ name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '6.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '6.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.6'
61
+ version: '2.3'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.6'
68
+ version: '2.3'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '13'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sidekiq
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
81
109
  - !ruby/object:Gem::Version
82
- version: '0'
83
- description: Collection of common ruby logic used by a number of Cru apps
110
+ version: '6'
111
+ description: Provides a common interface for mapping ActiveRecord models to Global
112
+ Registry entities and relationships.
84
113
  email:
85
114
  - josh.starcher@gmail.com
86
115
  executables: []
@@ -94,21 +123,20 @@ files:
94
123
  - Rakefile
95
124
  - cru_lib.gemspec
96
125
  - lib/cru_lib.rb
97
- - lib/cru_lib/access_token.rb
98
- - lib/cru_lib/access_token_protected_concern.rb
99
- - lib/cru_lib/access_token_serializer.rb
100
- - lib/cru_lib/api_error.rb
101
- - lib/cru_lib/api_error_serializer.rb
102
126
  - lib/cru_lib/async.rb
127
+ - lib/cru_lib/global_registry_master_person_methods.rb
103
128
  - lib/cru_lib/global_registry_methods.rb
104
129
  - lib/cru_lib/global_registry_relationship_methods.rb
130
+ - lib/cru_lib/railtie.rb
105
131
  - lib/cru_lib/version.rb
106
132
  - spec/shared_examples_for_global_registry_models.rb
107
- homepage: ''
133
+ - spec/support/async_commons.rb
134
+ - spec/support/async_spec.rb
135
+ homepage: https://github.com/CruGlobal/cru_lib
108
136
  licenses:
109
137
  - MIT
110
138
  metadata: {}
111
- post_install_message:
139
+ post_install_message:
112
140
  rdoc_options: []
113
141
  require_paths:
114
142
  - lib
@@ -123,11 +151,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
151
  - !ruby/object:Gem::Version
124
152
  version: '0'
125
153
  requirements: []
126
- rubyforge_project:
127
- rubygems_version: 2.4.5.1
128
- signing_key:
154
+ rubygems_version: 3.3.0
155
+ signing_key:
129
156
  specification_version: 4
130
- summary: Misc libraries for Cru
157
+ summary: Map ActiveRecord to Global Registry
131
158
  test_files:
132
159
  - spec/shared_examples_for_global_registry_models.rb
133
- has_rdoc:
160
+ - spec/support/async_commons.rb
161
+ - spec/support/async_spec.rb
@@ -1,50 +0,0 @@
1
- require 'securerandom'
2
-
3
- module CruLib
4
- class AccessToken < ActiveModelSerializers::Model
5
- attr_accessor :key_guid, :email, :first_name, :last_name, :token, :pgt
6
-
7
- def initialize(attributes = {})
8
- super
9
- generate_access_token unless attributes['token']
10
- write
11
- end
12
-
13
- class << self
14
-
15
- def read(token)
16
- json = exist?(token)
17
- new(Oj.load(json)) if json
18
- end
19
-
20
- def exist?(token)
21
- redis_client.get(redis_key(token))
22
- end
23
-
24
- def redis_client
25
- @redis_client ||= CruLib.redis_client
26
- end
27
-
28
- def redis_key(token)
29
- ['cru_lib:access_token', token].join(':')
30
- end
31
-
32
- def del(token)
33
- redis_client.del(redis_key(token))
34
- end
35
- end
36
-
37
- private
38
-
39
- def generate_access_token
40
- loop do
41
- attributes[:token] = SecureRandom.uuid.gsub(/\-/, '')
42
- break unless self.class.exist?(attributes[:token])
43
- end
44
- end
45
-
46
- def write
47
- self.class.redis_client.setex(self.class.redis_key(attributes[:token]), 30.minutes.to_i, to_json)
48
- end
49
- end
50
- end
@@ -1,30 +0,0 @@
1
- module CruLib
2
- module AccessTokenProtectedConcern
3
- extend ActiveSupport::Concern
4
-
5
- protected
6
-
7
- def authenticate_request
8
- authenticate_token || render_unauthorized
9
- end
10
-
11
- def authenticate_token
12
- token = oauth_access_token_from_header
13
- return unless oauth_access_token_from_header
14
- @access_token = AccessToken.read(token)
15
- end
16
-
17
- # grabs access_token from header if one is present
18
- def oauth_access_token_from_header
19
- auth_header = request.env['HTTP_AUTHORIZATION'] || ''
20
- match = auth_header.match(/^Bearer\s(.*)/)
21
- return match[1] if match.present?
22
- false
23
- end
24
-
25
- def render_unauthorized
26
- headers['WWW-Authenticate'] = %{CAS realm="Application"}
27
- render_error('Bad token', status: 401)
28
- end
29
- end
30
- end
@@ -1,13 +0,0 @@
1
- module CruLib
2
- class AccessTokenSerializer < ActiveModel::Serializer
3
- attributes :key_guid, :email, :first_name, :last_name, :token
4
-
5
- def _type
6
- 'access_token'
7
- end
8
-
9
- def id
10
- token
11
- end
12
- end
13
- end
@@ -1,5 +0,0 @@
1
- module CruLib
2
- class ApiError < ActiveModelSerializers::Model
3
- attr_accessor :message, :options
4
- end
5
- end
@@ -1,13 +0,0 @@
1
- module CruLib
2
- class ApiErrorSerializer < ActiveModel::Serializer
3
- attributes :message
4
-
5
- def _type
6
- 'api_error'
7
- end
8
-
9
- def id
10
- _type
11
- end
12
- end
13
- end