barkibu-kb 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.example +3 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.rubocop.yml +45 -0
- data/.ruby-version +2 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +185 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +182 -0
- data/LICENSE.txt +21 -0
- data/README.md +243 -0
- data/Rakefile +28 -0
- data/barkibu-kb-fake.gemspec +41 -0
- data/barkibu-kb.gemspec +54 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker-compose.yaml +15 -0
- data/lib/barkibu-kb-fake.rb +1 -0
- data/lib/barkibu-kb.rb +33 -0
- data/lib/kb/cache.rb +23 -0
- data/lib/kb/client.rb +85 -0
- data/lib/kb/client_resolver.rb +62 -0
- data/lib/kb/concerns/as_kb_wrapper.rb +67 -0
- data/lib/kb/concerns.rb +1 -0
- data/lib/kb/errors/client_error.rb +9 -0
- data/lib/kb/errors/conflict_error.rb +3 -0
- data/lib/kb/errors/error.rb +26 -0
- data/lib/kb/errors/resource_not_found.rb +3 -0
- data/lib/kb/errors/unprocessable_entity_error.rb +3 -0
- data/lib/kb/errors.rb +6 -0
- data/lib/kb/fake/api.rb +72 -0
- data/lib/kb/fake/bounded_context/pet_family/breeds.rb +15 -0
- data/lib/kb/fake/bounded_context/pet_family/hubspot_relationship.rb +17 -0
- data/lib/kb/fake/bounded_context/pet_family/pet_contracts.rb +24 -0
- data/lib/kb/fake/bounded_context/pet_family/pet_parents.rb +98 -0
- data/lib/kb/fake/bounded_context/pet_family/pets.rb +84 -0
- data/lib/kb/fake/bounded_context/pet_family/products.rb +28 -0
- data/lib/kb/fake/bounded_context/rest_resource.rb +134 -0
- data/lib/kb/fake.rb +6 -0
- data/lib/kb/inflections.rb +3 -0
- data/lib/kb/models/assessment.rb +58 -0
- data/lib/kb/models/base_model.rb +40 -0
- data/lib/kb/models/breed.rb +39 -0
- data/lib/kb/models/concerns/creatable.rb +18 -0
- data/lib/kb/models/concerns/destroyable.rb +17 -0
- data/lib/kb/models/concerns/find_or_creatable.rb +19 -0
- data/lib/kb/models/concerns/findable.rb +19 -0
- data/lib/kb/models/concerns/inspectionable.rb +13 -0
- data/lib/kb/models/concerns/listable.rb +21 -0
- data/lib/kb/models/concerns/queryable.rb +34 -0
- data/lib/kb/models/concerns/updatable.rb +18 -0
- data/lib/kb/models/concerns/upsertable.rb +17 -0
- data/lib/kb/models/concerns.rb +10 -0
- data/lib/kb/models/condition.rb +32 -0
- data/lib/kb/models/hubspot_relationship.rb +34 -0
- data/lib/kb/models/pet.rb +68 -0
- data/lib/kb/models/pet_contract.rb +77 -0
- data/lib/kb/models/pet_parent.rb +111 -0
- data/lib/kb/models/plan.rb +44 -0
- data/lib/kb/models/product.rb +34 -0
- data/lib/kb/models/symptom.rb +25 -0
- data/lib/kb/models.rb +15 -0
- data/lib/kb/type/array_of_conditions_type.rb +13 -0
- data/lib/kb/type/array_of_strings_type.rb +9 -0
- data/lib/kb/type/array_of_symptoms_type.rb +13 -0
- data/lib/kb/types.rb +7 -0
- data/lib/kb/validators/uniqueness_validator.rb +26 -0
- data/lib/kb/validators.rb +1 -0
- data/lib/kb/version.rb +3 -0
- metadata +325 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module KB
|
2
|
+
class Error < StandardError
|
3
|
+
attr_accessor :status_code, :body, :message
|
4
|
+
|
5
|
+
def initialize(status_code = nil, body = nil, error = nil)
|
6
|
+
super(error)
|
7
|
+
@status_code = status_code
|
8
|
+
@body = body
|
9
|
+
@message = "Received Status: #{status_code}\n#{body}"
|
10
|
+
set_backtrace error.backtrace if error
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_faraday(error)
|
14
|
+
case error.response[:status]
|
15
|
+
when 404
|
16
|
+
ResourceNotFound
|
17
|
+
when 409
|
18
|
+
ConflictError
|
19
|
+
when 422
|
20
|
+
UnprocessableEntityError
|
21
|
+
else
|
22
|
+
self
|
23
|
+
end.new(error.response[:status], error.response[:body], error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/kb/errors.rb
ADDED
data/lib/kb/fake/api.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'kb/fake/bounded_context/pet_family/breeds'
|
2
|
+
require 'kb/fake/bounded_context/pet_family/pet_parents'
|
3
|
+
require 'kb/fake/bounded_context/pet_family/pets'
|
4
|
+
require 'kb/fake/bounded_context/pet_family/products'
|
5
|
+
require 'kb/fake/bounded_context/pet_family/pet_contracts'
|
6
|
+
require 'kb/fake/bounded_context/pet_family/hubspot_relationship'
|
7
|
+
|
8
|
+
module KB
|
9
|
+
module Fake
|
10
|
+
class ApiState
|
11
|
+
attr_accessor :petparents, :pets, :consultations, :petcontracts, :plans, :breeds, :products, :hubspot_relationship
|
12
|
+
|
13
|
+
# rubocop:disable Metrics/ParameterLists
|
14
|
+
def initialize(petparents: [], pets: [], consultations: [], petcontracts: [], plans: [], breeds: [],
|
15
|
+
products: [], hubspot_relationship: [])
|
16
|
+
@petparents = petparents
|
17
|
+
@pets = pets
|
18
|
+
@consultations = consultations
|
19
|
+
@petcontracts = petcontracts
|
20
|
+
@plans = plans
|
21
|
+
@breeds = breeds
|
22
|
+
@products = products
|
23
|
+
@hubspot_relationship = hubspot_relationship
|
24
|
+
end
|
25
|
+
# rubocop:enable Metrics/ParameterLists
|
26
|
+
|
27
|
+
def to_snapshot
|
28
|
+
{
|
29
|
+
pets: @pets.clone,
|
30
|
+
petparents: @petparents.clone,
|
31
|
+
consultations: @consultations.clone,
|
32
|
+
petcontracts: @petcontracts.clone,
|
33
|
+
plans: @plans.clone,
|
34
|
+
breeds: @breeds.clone,
|
35
|
+
products: @products.clone,
|
36
|
+
hubspot_relationship: @hubspot_relationship.clone
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Api < Sinatra::Base
|
42
|
+
include BoundedContext::PetFamily::Breeds
|
43
|
+
include BoundedContext::PetFamily::Pets
|
44
|
+
include BoundedContext::PetFamily::PetParents
|
45
|
+
include BoundedContext::PetFamily::PetContracts
|
46
|
+
include BoundedContext::PetFamily::Products
|
47
|
+
include BoundedContext::PetFamily::HubspotRelationship
|
48
|
+
|
49
|
+
set :state, ApiState.new
|
50
|
+
|
51
|
+
def self.snapshot
|
52
|
+
Api.state.to_snapshot
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.restore(snapshot)
|
56
|
+
set :state, ApiState.new(**snapshot)
|
57
|
+
end
|
58
|
+
|
59
|
+
def resource_state(name)
|
60
|
+
Api.state.send(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_resource_state(name, value)
|
64
|
+
Api.state.send("#{name}=", value)
|
65
|
+
end
|
66
|
+
|
67
|
+
resource :consultations, except: %i[create update destroy]
|
68
|
+
|
69
|
+
resource :plans, except: %i[show create update destroy]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'kb/fake/bounded_context/rest_resource'
|
2
|
+
|
3
|
+
module BoundedContext
|
4
|
+
module PetFamily
|
5
|
+
module HubspotRelationship
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include RestResource
|
10
|
+
|
11
|
+
get '/v1/hubspot/:model/:key/relationship' do
|
12
|
+
resource_by_key(:hubspot_relationship, params['key'])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'kb/fake/bounded_context/rest_resource'
|
2
|
+
|
3
|
+
module BoundedContext
|
4
|
+
module PetFamily
|
5
|
+
module PetContracts
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include RestResource
|
10
|
+
|
11
|
+
get '/v1/petcontracts/contractnumber/:contract_number' do
|
12
|
+
resource = resource_state(:petcontracts).detect do |contract|
|
13
|
+
contract['contractNumber'] == params['contract_number']
|
14
|
+
end
|
15
|
+
return json_response 404, {} if resource.nil?
|
16
|
+
|
17
|
+
json_response 200, resource
|
18
|
+
end
|
19
|
+
|
20
|
+
resource :petcontracts, except: %i[index destroy]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'kb/fake/bounded_context/rest_resource'
|
2
|
+
# rubocop:disable Metrics/BlockLength
|
3
|
+
|
4
|
+
module BoundedContext
|
5
|
+
module PetFamily
|
6
|
+
module PetParents
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
include RestResource
|
11
|
+
|
12
|
+
resource :petparents
|
13
|
+
|
14
|
+
def petparents_filterable_attributes
|
15
|
+
KB::PetParent::FIELDS.map { |k| k.to_s.camelize(:lower) }
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/v1/petparents/:key/pets' do
|
19
|
+
json_response 200, pets_by_pet_parent_key(params['key'])
|
20
|
+
end
|
21
|
+
|
22
|
+
get '/v1/petparents/:key/contracts' do
|
23
|
+
pet_keys = pets_by_pet_parent_key(params['key']).map { |pet| pet['key'] }
|
24
|
+
contracts = resource_state(:petcontracts).select { |contract| pet_keys.include? contract['petKey'] }
|
25
|
+
|
26
|
+
json_response 200, contracts
|
27
|
+
end
|
28
|
+
|
29
|
+
put '/v1/petparents' do
|
30
|
+
params = JSON.parse(request.body.read)
|
31
|
+
existing_pet_parent = pet_parent_by_key(params) || pet_parent_by_email(params) || pet_parent_by_phone(params)
|
32
|
+
resource = (existing_pet_parent || { 'key' => SecureRandom.uuid }).merge params
|
33
|
+
|
34
|
+
if existing_pet_parent.present?
|
35
|
+
if same_phone_number_but_different_email?(existing_pet_parent, params)
|
36
|
+
return json_response 422, { error: 'Unprocessable Entity', message: 'Email can not be overridden' }
|
37
|
+
end
|
38
|
+
|
39
|
+
if same_email_but_different_phone_number?(existing_pet_parent, params)
|
40
|
+
previous_pet_parent_by_phone = pet_parent_by_phone(params)
|
41
|
+
if previous_pet_parent_by_phone.present?
|
42
|
+
return json_response 409,
|
43
|
+
{ error: 'ConflictError',
|
44
|
+
message: 'Duplicated pet parent: same partner, phoneNumber \
|
45
|
+
and phoneNumberPrefix' }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
update_resource_state(:petparents, resource)
|
50
|
+
else
|
51
|
+
resource_state(:petparents) << resource
|
52
|
+
end
|
53
|
+
|
54
|
+
json_response 200, resource
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def pet_parent_by_key(params)
|
60
|
+
find_resource(:petparents, params['key']) if params['key']
|
61
|
+
end
|
62
|
+
|
63
|
+
def pet_parent_by_phone(params)
|
64
|
+
matches_by_phone = (if params['phoneNumber']
|
65
|
+
filter_resources(:petparents,
|
66
|
+
params.slice('phoneNumber',
|
67
|
+
'prefixPhoneNumber'))
|
68
|
+
end)
|
69
|
+
matches_by_phone.first if matches_by_phone&.count == 1
|
70
|
+
end
|
71
|
+
|
72
|
+
def pet_parent_by_email(params)
|
73
|
+
matches_by_email = (filter_resources(:petparents, params.slice('email')) if params['email'])
|
74
|
+
matches_by_email.first if matches_by_email&.count == 1
|
75
|
+
end
|
76
|
+
|
77
|
+
def pets_by_pet_parent_key(key)
|
78
|
+
resource_state(:pets).select { |pet| pet['petParentKey'] == key }
|
79
|
+
end
|
80
|
+
|
81
|
+
def same_email_but_different_phone_number?(previous, new)
|
82
|
+
(previous['email'] == new['email']) &&
|
83
|
+
((previous['phoneNumber'] != new['phoneNumber']) ||
|
84
|
+
(previous['prefixPhoneNumber'] != new['prefixPhoneNumber']))
|
85
|
+
end
|
86
|
+
|
87
|
+
def same_phone_number_but_different_email?(previous, new_resource)
|
88
|
+
return false unless new_resource.key?('email')
|
89
|
+
|
90
|
+
(previous['phoneNumber'] == new_resource['phoneNumber']) &&
|
91
|
+
(previous['prefixPhoneNumber'] == new_resource['prefixPhoneNumber']) &&
|
92
|
+
(previous['email'] != new_resource['email'])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
# rubocop:enable Metrics/BlockLength
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'kb/fake/bounded_context/rest_resource'
|
2
|
+
require 'date'
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
4
|
+
|
5
|
+
module BoundedContext
|
6
|
+
module PetFamily
|
7
|
+
module Pets
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
include RestResource
|
10
|
+
|
11
|
+
included do
|
12
|
+
include RestResource
|
13
|
+
|
14
|
+
resource :pets
|
15
|
+
|
16
|
+
def pets_filterable_attributes
|
17
|
+
KB::Pet::FIELDS.map { |k| k.to_s.camelize(:lower) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_pets_create(_version)
|
21
|
+
resource = JSON.parse(request.body.read)
|
22
|
+
resource['ageCategory'] = stage(resource['birthDate'], resource['species'])
|
23
|
+
resource = resource.merge 'key' => SecureRandom.uuid
|
24
|
+
resource_state(:pets) << resource
|
25
|
+
json_response 201, resource
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_pets_update(_version)
|
29
|
+
resource_to_update = find_resource :pets, params['key']
|
30
|
+
|
31
|
+
return json_response 404, {} if resource_to_update.nil?
|
32
|
+
|
33
|
+
partial_resource = JSON.parse(request.body.read)
|
34
|
+
partial_resource['ageCategory'] = stage(partial_resource['birthDate'], resource_to_update['species'])
|
35
|
+
updated_resource = resource_to_update.merge partial_resource
|
36
|
+
|
37
|
+
update_resource_state(:pets, updated_resource)
|
38
|
+
|
39
|
+
json_response 200, updated_resource
|
40
|
+
end
|
41
|
+
|
42
|
+
get '/v1/pets/:key/contracts' do
|
43
|
+
contracts = resource_state(:petcontracts).select { |contract| contract['petKey'] == params['key'] }
|
44
|
+
|
45
|
+
json_response 200, contracts
|
46
|
+
end
|
47
|
+
|
48
|
+
put '/v1/pets' do
|
49
|
+
params = JSON.parse(request.body.read)
|
50
|
+
pet_parent = find_resource(:petparents, params['petParentKey'])
|
51
|
+
|
52
|
+
return json_response 422, {} if pet_parent.nil?
|
53
|
+
|
54
|
+
potential_matches = filter_resources(:pets, params.slice('name', 'petParentKey'))
|
55
|
+
existing_pet = (potential_matches.first if potential_matches.count == 1)
|
56
|
+
|
57
|
+
resource = (existing_pet || { 'key' => SecureRandom.uuid }).merge params
|
58
|
+
|
59
|
+
if existing_pet.present?
|
60
|
+
update_resource_state(:pets, resource)
|
61
|
+
else
|
62
|
+
resource_state(:pets) << resource
|
63
|
+
end
|
64
|
+
|
65
|
+
json_response 200, resource
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def stage(birthdate, species)
|
70
|
+
return nil if birthdate.nil?
|
71
|
+
|
72
|
+
case ((Time.zone.now - Time.zone.parse(birthdate)) / 1.month).to_i
|
73
|
+
when 0..11
|
74
|
+
species == 'cat' ? 'kitten' : 'puppy'
|
75
|
+
when 12..99
|
76
|
+
'adult'
|
77
|
+
else
|
78
|
+
'senior'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# rubocop:enable Metrics/BlockLength
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'kb/fake/bounded_context/rest_resource'
|
2
|
+
|
3
|
+
module BoundedContext
|
4
|
+
module PetFamily
|
5
|
+
module Products
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include RestResource
|
8
|
+
|
9
|
+
included do
|
10
|
+
include RestResource
|
11
|
+
|
12
|
+
resource :products, except: %i[create update destroy]
|
13
|
+
|
14
|
+
def products_filterable_attributes
|
15
|
+
[:country]
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_products_index(_version)
|
19
|
+
return json_response 400, {} if params['country'].nil?
|
20
|
+
|
21
|
+
return json_response 422, {} if ISO3166::Country.search(params['country']).nil?
|
22
|
+
|
23
|
+
json_response 200, filter_resources(:products, params)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# rubocop:disable Metrics/BlockLength
|
2
|
+
module BoundedContext
|
3
|
+
module RestResource
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
def resource_by_key(resource, key)
|
8
|
+
entity = find_resource(resource, key)
|
9
|
+
return json_response 404, {} if entity.nil?
|
10
|
+
|
11
|
+
json_response 200, entity
|
12
|
+
end
|
13
|
+
|
14
|
+
def json_response(response_code, body_content)
|
15
|
+
content_type :json
|
16
|
+
status response_code
|
17
|
+
body body_content.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_index_action(name, version)
|
21
|
+
return send("on_#{name}_index", version) if respond_to? "on_#{name}_index"
|
22
|
+
|
23
|
+
json_response 200, filter_resources(name, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def filter_resources(name, filters)
|
27
|
+
resource_state(name).select do |item|
|
28
|
+
item[:deleted_at].blank? && filters.slice(*filterable_attributes(name)).reduce(true) do |sum, (key, value)|
|
29
|
+
sum && (value.blank? \
|
30
|
+
|| (item.fetch(key, '') || '').downcase.include?(value.downcase))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def filterable_attributes(name)
|
36
|
+
try("#{name}_filterable_attributes") || []
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_show_action(name, version)
|
40
|
+
return send("on_#{name}_show", version) if respond_to? "on_#{name}_show"
|
41
|
+
|
42
|
+
resource_by_key name, params['key']
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_create_action(name, version)
|
46
|
+
return send("on_#{name}_create", version) if respond_to? "on_#{name}_create"
|
47
|
+
|
48
|
+
resource = JSON.parse(request.body.read)
|
49
|
+
resource = resource.merge 'key' => SecureRandom.uuid
|
50
|
+
resource_state(name) << resource
|
51
|
+
json_response 201, resource
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_update_action(name, version)
|
55
|
+
return send("on_#{name}_update", version) if respond_to? "on_#{name}_update"
|
56
|
+
|
57
|
+
resource_to_update = find_resource name, params['key']
|
58
|
+
|
59
|
+
return json_response 404, {} if resource_to_update.nil?
|
60
|
+
|
61
|
+
partial_resource = JSON.parse(request.body.read)
|
62
|
+
updated_resource = resource_to_update.merge partial_resource
|
63
|
+
|
64
|
+
update_resource_state(name, updated_resource)
|
65
|
+
|
66
|
+
json_response 200, updated_resource
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_destroy_action(name, version)
|
70
|
+
return send("on_#{name}_destroy", version) if respond_to? "on_#{name}_destroy"
|
71
|
+
|
72
|
+
resource_to_delete = find_resource name, params['key']
|
73
|
+
resource_to_delete[:deleted_at] = DateTime.now
|
74
|
+
|
75
|
+
update_resource_state(name, resource_to_delete)
|
76
|
+
|
77
|
+
json_response 204, nil
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def find_resource(name, key)
|
83
|
+
resource_state(name).detect { |resource| resource['key'] == key }
|
84
|
+
end
|
85
|
+
|
86
|
+
def update_resource_state(name, updated_resource)
|
87
|
+
updated_resources = resource_state(name).map do |resource|
|
88
|
+
resource['key'] == updated_resource['key'] ? updated_resource : resource
|
89
|
+
end
|
90
|
+
|
91
|
+
set_resource_state(name, updated_resources)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class_methods do
|
96
|
+
def listen_on_index(name, version)
|
97
|
+
get "/#{version}/#{name}" do
|
98
|
+
on_index_action(name, version)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def listen_on_show(name, version)
|
103
|
+
get "/#{version}/#{name}/:key" do
|
104
|
+
on_show_action(name, version)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def listen_on_create(name, version)
|
109
|
+
post "/#{version}/#{name}" do
|
110
|
+
on_create_action(name, version)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def listen_on_update(name, version)
|
115
|
+
patch "/#{version}/#{name}/:key" do
|
116
|
+
on_update_action(name, version)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def listen_on_destroy(name, version)
|
121
|
+
delete "/#{version}/#{name}/:key" do
|
122
|
+
on_destroy_action(name, version)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def resource(name, version: 'v1', except: [])
|
127
|
+
%i[index show create update destroy].each do |action|
|
128
|
+
send("listen_on_#{action}", name, version) unless except.include?(action)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
# rubocop:enable Metrics/BlockLength
|
data/lib/kb/fake.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'kb/types'
|
2
|
+
|
3
|
+
module KB
|
4
|
+
class Assessment < BaseModel
|
5
|
+
include Findable
|
6
|
+
include Listable
|
7
|
+
|
8
|
+
kb_api :consultation
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def by_pet(pet)
|
12
|
+
all(user: pet.kb_key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def all(filters = {})
|
16
|
+
filters[:locale] ||= I18n.locale
|
17
|
+
filters[:pet_key] = filters[:user] if filters[:user].present?
|
18
|
+
super(filters)
|
19
|
+
end
|
20
|
+
|
21
|
+
def find(key, params = {})
|
22
|
+
params[:locale] ||= I18n.locale
|
23
|
+
super(key, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def attributes_from_response(response)
|
29
|
+
response.transform_keys(&:underscore).transform_keys(&:to_sym).slice(*FIELDS)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Legacy Field Name From Anamnesis
|
34
|
+
alias_attribute :consultation_id, :key
|
35
|
+
alias_attribute :should_stop, :finished
|
36
|
+
alias_attribute :created_at, :date
|
37
|
+
|
38
|
+
attribute :invalid_symptoms, default: [] # Deprecated ?
|
39
|
+
attribute :conditions, :array_of_conditions
|
40
|
+
attribute :symptoms, :array_of_symptoms
|
41
|
+
|
42
|
+
attribute :date, :datetime
|
43
|
+
attribute :finished, :boolean, default: false
|
44
|
+
|
45
|
+
attribute :urgency, :string
|
46
|
+
attribute :key, :string
|
47
|
+
attribute :pet_key, :string
|
48
|
+
|
49
|
+
STRING_FIELDS = %i[key pet_key urgency].freeze
|
50
|
+
FIELDS = [*STRING_FIELDS, :date, :should_stop, :finished, :conditions, :symptoms, :next_question].freeze
|
51
|
+
|
52
|
+
def urgent
|
53
|
+
return false if urgency == 'low'
|
54
|
+
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module KB
|
2
|
+
class BaseModel
|
3
|
+
include Inspectionable
|
4
|
+
include ActiveModel::Model
|
5
|
+
include ActiveModel::Attributes
|
6
|
+
include ActiveModel::Serializers::JSON
|
7
|
+
include ActiveModel::Dirty
|
8
|
+
|
9
|
+
attr_accessor :persisted
|
10
|
+
|
11
|
+
define_model_callbacks :save
|
12
|
+
after_save :persist!
|
13
|
+
|
14
|
+
def initialize(attributes = {})
|
15
|
+
super
|
16
|
+
@persisted = false
|
17
|
+
yield self if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
def persisted?
|
21
|
+
@persisted
|
22
|
+
end
|
23
|
+
|
24
|
+
def persist!
|
25
|
+
changes_applied
|
26
|
+
@persisted = true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.define_attribute_methods(*fields)
|
30
|
+
super
|
31
|
+
fields.each do |field|
|
32
|
+
define_method :"#{field}=" do |value|
|
33
|
+
super(value).tap do
|
34
|
+
public_send "#{field}_will_change!" if public_send("#{field}_changed?")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module KB
|
2
|
+
class Breed < BaseModel
|
3
|
+
include Listable
|
4
|
+
|
5
|
+
DEFAULT_LOCALE = ENV.fetch('KB_BREEDS_DEFAULT_LOCALE', 'es-es')
|
6
|
+
|
7
|
+
kb_api :breed
|
8
|
+
|
9
|
+
def self.all(filters = {})
|
10
|
+
filters[:locale] ||= DEFAULT_LOCALE
|
11
|
+
super(filters)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.dogs(filters = {})
|
15
|
+
filters[:species] = 'dog'
|
16
|
+
all(filters)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cats(filters = {})
|
20
|
+
filters[:species] = 'cat'
|
21
|
+
all(filters)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.attributes_from_response(response)
|
25
|
+
response.transform_keys(&:underscore).transform_keys(&:to_sym).slice(*FIELDS)
|
26
|
+
end
|
27
|
+
|
28
|
+
private_class_method :attributes_from_response
|
29
|
+
|
30
|
+
STRING_FIELDS = %i[key locale name species weight_group external_id].freeze
|
31
|
+
FIELDS = [*STRING_FIELDS].freeze
|
32
|
+
|
33
|
+
define_attribute_methods(*FIELDS)
|
34
|
+
|
35
|
+
STRING_FIELDS.each do |field|
|
36
|
+
attribute field, :string
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|