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