hoalife 0.1.0
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/.gitignore +10 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +62 -0
- data/LICENSE.txt +21 -0
- data/README.md +220 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/hoalife.gemspec +42 -0
- data/lib/hoal_inflector.rb +18 -0
- data/lib/hoalife.rb +47 -0
- data/lib/hoalife/account.rb +18 -0
- data/lib/hoalife/ccr_article.rb +18 -0
- data/lib/hoalife/ccr_violation_type.rb +18 -0
- data/lib/hoalife/client/base.rb +124 -0
- data/lib/hoalife/client/delete.rb +14 -0
- data/lib/hoalife/client/get.rb +14 -0
- data/lib/hoalife/client/post.rb +16 -0
- data/lib/hoalife/client/put.rb +16 -0
- data/lib/hoalife/concern.rb +51 -0
- data/lib/hoalife/error.rb +33 -0
- data/lib/hoalife/escalation.rb +10 -0
- data/lib/hoalife/inspection.rb +6 -0
- data/lib/hoalife/property.rb +18 -0
- data/lib/hoalife/resource.rb +76 -0
- data/lib/hoalife/resources/collection.rb +112 -0
- data/lib/hoalife/resources/has_nested_object.rb +45 -0
- data/lib/hoalife/resources/has_nested_resources.rb +35 -0
- data/lib/hoalife/resources/persistable.rb +87 -0
- data/lib/hoalife/resources/requestable.rb +13 -0
- data/lib/hoalife/upload_url.rb +8 -0
- data/lib/hoalife/user.rb +5 -0
- data/lib/hoalife/version.rb +5 -0
- data/lib/hoalife/violation.rb +24 -0
- metadata +180 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A collection of resources
|
4
|
+
# Usually returned by an index endpoint
|
5
|
+
class HOALife::Resources::Collection
|
6
|
+
include HOALife::Resources::Requestable
|
7
|
+
|
8
|
+
attr_reader :url
|
9
|
+
|
10
|
+
def initialize(url)
|
11
|
+
@url = url
|
12
|
+
@meta = {}
|
13
|
+
@links = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return all pages
|
17
|
+
def all
|
18
|
+
all_resources = resources
|
19
|
+
|
20
|
+
if @meta['current_page'] < @meta['total_pages']
|
21
|
+
all_resources += self.class.new(@links['next']).all
|
22
|
+
end
|
23
|
+
|
24
|
+
all_resources
|
25
|
+
end
|
26
|
+
|
27
|
+
# Just return the first result
|
28
|
+
def first
|
29
|
+
if resources.is_a?(Array)
|
30
|
+
resources.first
|
31
|
+
else
|
32
|
+
resources
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Just return the last result
|
37
|
+
def last
|
38
|
+
all.last
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add query parameters to the URL
|
42
|
+
def where(params = {})
|
43
|
+
self.class.new add_params_to_url!(params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def order(col, dir = :asc)
|
47
|
+
safe_dir = dir.to_s.downcase == 'desc' ? 'desc' : 'asc'
|
48
|
+
self.class.new add_params_to_url!(order: col, order_dir: safe_dir)
|
49
|
+
end
|
50
|
+
|
51
|
+
def total_pages
|
52
|
+
data
|
53
|
+
|
54
|
+
@meta['total_pages']
|
55
|
+
end
|
56
|
+
|
57
|
+
def current_page
|
58
|
+
data
|
59
|
+
|
60
|
+
@meta['current_page']
|
61
|
+
end
|
62
|
+
|
63
|
+
def total
|
64
|
+
data
|
65
|
+
|
66
|
+
@meta['total']
|
67
|
+
end
|
68
|
+
alias count total
|
69
|
+
alias size total
|
70
|
+
|
71
|
+
def reload
|
72
|
+
@data = nil
|
73
|
+
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def request!
|
80
|
+
make_request! do
|
81
|
+
response = HOALife::Client::Get.new(@url)
|
82
|
+
|
83
|
+
@meta = response.json['meta']
|
84
|
+
@links = response.json['links']
|
85
|
+
|
86
|
+
response
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_params_to_url!(new_params)
|
91
|
+
uri = URI(@url)
|
92
|
+
exisiting_params = Hash[URI.decode_www_form(uri.query || '')]
|
93
|
+
new_params.each { |k, v| exisiting_params[k.to_s] = v }
|
94
|
+
uri.query = URI.encode_www_form(exisiting_params)
|
95
|
+
|
96
|
+
uri.to_s
|
97
|
+
end
|
98
|
+
|
99
|
+
def data
|
100
|
+
@data ||= request!.json['data']
|
101
|
+
end
|
102
|
+
|
103
|
+
def resources
|
104
|
+
if data.is_a?(Array)
|
105
|
+
# array of resource objects for each instance
|
106
|
+
data.collect { |instance| HOALife::Resource.new(instance) }
|
107
|
+
else
|
108
|
+
# return a single resource
|
109
|
+
HOALife::Resource.new(data)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Wrap an attribute in an object
|
4
|
+
module HOALife::Resources::HasNestedObject
|
5
|
+
extend HOALife::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
attr_reader :has_nested_objects
|
9
|
+
|
10
|
+
# rubocop:disable Naming/PredicateName
|
11
|
+
def has_nested_object(key, class_name)
|
12
|
+
@has_nested_objects ||= {}
|
13
|
+
|
14
|
+
@has_nested_objects[key] = class_name
|
15
|
+
|
16
|
+
add_nested_object_methods!(key, class_name)
|
17
|
+
end
|
18
|
+
# rubocop:enable Naming/PredicateName
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# rubocop:disable Metrics/MethodLength
|
23
|
+
def add_nested_object_methods!(key, class_name)
|
24
|
+
define_method key do
|
25
|
+
raw_value = super()
|
26
|
+
|
27
|
+
begin
|
28
|
+
klass = Object.const_get("HOALife::#{class_name}")
|
29
|
+
rescue NameError
|
30
|
+
raise HOALife::UndefinedResourceError,
|
31
|
+
"HOALife::#{class_name} not defined"
|
32
|
+
end
|
33
|
+
|
34
|
+
if raw_value.is_a?(Array)
|
35
|
+
raw_value.collect { |value| klass.new(value) }
|
36
|
+
elsif raw_value.is_a?(Hash)
|
37
|
+
klass.new(raw_value)
|
38
|
+
else
|
39
|
+
raw_value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# rubocop:enable Metrics/MethodLength
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Automatically follow links to related resources
|
4
|
+
module HOALife::Resources::HasNestedResources
|
5
|
+
extend HOALife::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
attr_reader :has_nested_resources
|
9
|
+
|
10
|
+
# rubocop:disable Naming/PredicateName
|
11
|
+
def has_nested(key)
|
12
|
+
@has_nested_resources ||= []
|
13
|
+
|
14
|
+
@has_nested_resources.push(key)
|
15
|
+
|
16
|
+
add_nested_resources_methods!(key)
|
17
|
+
end
|
18
|
+
# rubocop:enable Naming/PredicateName
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def add_nested_resources_methods!(key)
|
23
|
+
define_method key do
|
24
|
+
raw_value = super()
|
25
|
+
if raw_value.is_a?(Array)
|
26
|
+
raw_value.collect do |value|
|
27
|
+
HOALife::Resources::Collection.new(value['link']).all
|
28
|
+
end.flatten
|
29
|
+
else
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Persist an object
|
4
|
+
module HOALife::Resources::Persistable
|
5
|
+
include HOALife::Resources::Requestable
|
6
|
+
extend HOALife::Concern
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
def create(attrs = {})
|
10
|
+
new(attrs).tap(&:save)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def save
|
15
|
+
self.errors = nil
|
16
|
+
|
17
|
+
if !persisted?
|
18
|
+
create!
|
19
|
+
else
|
20
|
+
update!
|
21
|
+
end
|
22
|
+
|
23
|
+
errors.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def persisted?
|
27
|
+
!id.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def update(attrs = {})
|
31
|
+
return false unless persisted?
|
32
|
+
|
33
|
+
attrs.each do |key, value|
|
34
|
+
send("#{key}=", value)
|
35
|
+
end
|
36
|
+
|
37
|
+
save
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
make_request! do
|
42
|
+
response = HOALife::Client::Delete.new(update_url)
|
43
|
+
|
44
|
+
response.status == 202
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def create_url
|
51
|
+
HOALife.api_base + self.class.base_path
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_url
|
55
|
+
HOALife.api_base + self.class.base_path + "/#{id}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def create!
|
59
|
+
make_request! do
|
60
|
+
response = HOALife::Client::Post.new(create_url, to_json)
|
61
|
+
|
62
|
+
assign_updated_data!(response.json)
|
63
|
+
end
|
64
|
+
rescue HOALife::BadRequestError => e
|
65
|
+
assign_errors!(e)
|
66
|
+
end
|
67
|
+
|
68
|
+
def update!
|
69
|
+
make_request! do
|
70
|
+
response = HOALife::Client::Put.new(update_url, to_json)
|
71
|
+
|
72
|
+
assign_updated_data!(response.json)
|
73
|
+
end
|
74
|
+
rescue HOALife::BadRequestError => e
|
75
|
+
assign_errors!(e)
|
76
|
+
end
|
77
|
+
|
78
|
+
def assign_updated_data!(data)
|
79
|
+
@obj = cast_attrs(data.dig('data', 'attributes'))
|
80
|
+
|
81
|
+
data.dig('data', 'attributes').each { |k, v| send("#{k}=", v) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def assign_errors!(err)
|
85
|
+
self.errors = OpenStruct.new(err.details.dig('data', 'attributes'))
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Client request convenience methods
|
4
|
+
module HOALife::Resources::Requestable
|
5
|
+
def make_request!(&blk)
|
6
|
+
blk.call
|
7
|
+
rescue HOALife::RateLimitError => e
|
8
|
+
raise e unless HOALife.sleep_when_rate_limited
|
9
|
+
|
10
|
+
sleep HOALife.sleep_when_rate_limited.to_f
|
11
|
+
retry
|
12
|
+
end
|
13
|
+
end
|
data/lib/hoalife/user.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc
|
4
|
+
class HOALife::Violation < HOALife::Resource
|
5
|
+
include HOALife::Resources::HasNestedObject
|
6
|
+
include HOALife::Resources::Persistable
|
7
|
+
|
8
|
+
self.base_path = '/violations'
|
9
|
+
|
10
|
+
has_nested_object :upload_urls, 'UploadUrl'
|
11
|
+
has_nested_object :inspector, 'User'
|
12
|
+
|
13
|
+
def as_json
|
14
|
+
h = super
|
15
|
+
|
16
|
+
h.dig('data', 'relationships').merge!(
|
17
|
+
'property' => { 'data' => { 'id' => property_id } },
|
18
|
+
'ccr_violation_type' => { 'data' => { 'id' => ccr_violation_type_id } },
|
19
|
+
'inspector' => { 'data' => { 'email' => inspector_email } }
|
20
|
+
)
|
21
|
+
|
22
|
+
h
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hoalife
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Westendorf
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-09-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: zeitwerk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: listen
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.74'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.74'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.6'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.6'
|
111
|
+
description: Interface for the HOALife.com HTTP API.
|
112
|
+
email:
|
113
|
+
- daniel@prowestech.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rubocop.yml"
|
120
|
+
- ".travis.yml"
|
121
|
+
- Gemfile
|
122
|
+
- Gemfile.lock
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/console
|
127
|
+
- bin/setup
|
128
|
+
- hoalife.gemspec
|
129
|
+
- lib/hoal_inflector.rb
|
130
|
+
- lib/hoalife.rb
|
131
|
+
- lib/hoalife/account.rb
|
132
|
+
- lib/hoalife/ccr_article.rb
|
133
|
+
- lib/hoalife/ccr_violation_type.rb
|
134
|
+
- lib/hoalife/client/base.rb
|
135
|
+
- lib/hoalife/client/delete.rb
|
136
|
+
- lib/hoalife/client/get.rb
|
137
|
+
- lib/hoalife/client/post.rb
|
138
|
+
- lib/hoalife/client/put.rb
|
139
|
+
- lib/hoalife/concern.rb
|
140
|
+
- lib/hoalife/error.rb
|
141
|
+
- lib/hoalife/escalation.rb
|
142
|
+
- lib/hoalife/inspection.rb
|
143
|
+
- lib/hoalife/property.rb
|
144
|
+
- lib/hoalife/resource.rb
|
145
|
+
- lib/hoalife/resources/collection.rb
|
146
|
+
- lib/hoalife/resources/has_nested_object.rb
|
147
|
+
- lib/hoalife/resources/has_nested_resources.rb
|
148
|
+
- lib/hoalife/resources/persistable.rb
|
149
|
+
- lib/hoalife/resources/requestable.rb
|
150
|
+
- lib/hoalife/upload_url.rb
|
151
|
+
- lib/hoalife/user.rb
|
152
|
+
- lib/hoalife/version.rb
|
153
|
+
- lib/hoalife/violation.rb
|
154
|
+
homepage: https://docs.hoalife.com
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata:
|
158
|
+
homepage_uri: https://docs.hoalife.com
|
159
|
+
source_code_uri: https://github.com/hoalife/hoalife-ruby
|
160
|
+
changelog_uri: https://github.com/hoalife/hoalife-ruby/master/CHANGELOG.md
|
161
|
+
post_install_message:
|
162
|
+
rdoc_options: []
|
163
|
+
require_paths:
|
164
|
+
- lib
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
requirements: []
|
176
|
+
rubygems_version: 3.0.3
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Ruby API Client for the HOALife.com API
|
180
|
+
test_files: []
|