atdis 0.3.11 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +46 -0
- data/.ruby-version +1 -1
- data/.travis.yml +0 -4
- data/Gemfile +9 -7
- data/Guardfile +4 -3
- data/Rakefile +4 -2
- data/atdis.gemspec +10 -5
- data/lib/atdis.rb +2 -0
- data/lib/atdis/feed.rb +32 -24
- data/lib/atdis/model.rb +108 -95
- data/lib/atdis/models/address.rb +10 -4
- data/lib/atdis/models/application.rb +12 -9
- data/lib/atdis/models/authority.rb +11 -6
- data/lib/atdis/models/document.rb +8 -6
- data/lib/atdis/models/event.rb +10 -8
- data/lib/atdis/models/info.rb +73 -49
- data/lib/atdis/models/land_title_ref.rb +15 -7
- data/lib/atdis/models/location.rb +9 -7
- data/lib/atdis/models/page.rb +36 -21
- data/lib/atdis/models/pagination.rb +91 -32
- data/lib/atdis/models/person.rb +7 -5
- data/lib/atdis/models/reference.rb +7 -5
- data/lib/atdis/models/response.rb +5 -3
- data/lib/atdis/models/torrens_title.rb +9 -7
- data/lib/atdis/separated_url.rb +17 -15
- data/lib/atdis/validators.rb +46 -39
- data/lib/atdis/version.rb +3 -1
- data/spec/atdis/feed_spec.rb +128 -34
- data/spec/atdis/model_spec.rb +124 -51
- data/spec/atdis/models/address_spec.rb +18 -9
- data/spec/atdis/models/application_spec.rb +222 -155
- data/spec/atdis/models/authority_spec.rb +45 -15
- data/spec/atdis/models/document_spec.rb +10 -4
- data/spec/atdis/models/event_spec.rb +23 -11
- data/spec/atdis/models/info_spec.rb +197 -113
- data/spec/atdis/models/land_title_ref_spec.rb +32 -16
- data/spec/atdis/models/location_spec.rb +75 -60
- data/spec/atdis/models/page_spec.rb +244 -135
- data/spec/atdis/models/pagination_spec.rb +177 -77
- data/spec/atdis/models/person_spec.rb +8 -4
- data/spec/atdis/models/reference_spec.rb +29 -16
- data/spec/atdis/models/response_spec.rb +2 -1
- data/spec/atdis/models/torrens_title_spec.rb +24 -18
- data/spec/atdis/separated_url_spec.rb +14 -15
- data/spec/spec_helper.rb +14 -10
- metadata +62 -33
data/lib/atdis/models/address.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ATDIS
|
2
4
|
module Models
|
3
5
|
class Address < Model
|
4
|
-
|
6
|
+
field_mappings(
|
5
7
|
street: String,
|
6
8
|
suburb: String,
|
7
9
|
postcode: String,
|
8
10
|
state: String
|
9
|
-
|
11
|
+
)
|
10
12
|
|
11
13
|
# Mandatory parameters
|
12
|
-
validates :street, :suburb, :postcode, :state,
|
14
|
+
validates :street, :suburb, :postcode, :state,
|
15
|
+
presence_before_type_cast: { spec_section: "4.3.3" }
|
13
16
|
|
14
|
-
validates :postcode, format: {
|
17
|
+
validates :postcode, format: {
|
18
|
+
with: /\A[0-9]{4}\z/,
|
19
|
+
message: ATDIS::ErrorMessage.new("is not a valid postcode", "4.3.3")
|
20
|
+
}
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "atdis/models/info"
|
2
4
|
require "atdis/models/reference"
|
3
5
|
require "atdis/models/location"
|
@@ -8,21 +10,22 @@ require "atdis/models/person"
|
|
8
10
|
module ATDIS
|
9
11
|
module Models
|
10
12
|
class Application < Model
|
11
|
-
|
12
|
-
info:
|
13
|
+
field_mappings(
|
14
|
+
info: Info,
|
13
15
|
reference: Reference,
|
14
16
|
locations: Location,
|
15
|
-
events:
|
17
|
+
events: Event,
|
16
18
|
documents: Document,
|
17
|
-
people:
|
18
|
-
extended:
|
19
|
-
|
19
|
+
people: Person,
|
20
|
+
extended: Object
|
21
|
+
)
|
20
22
|
|
21
23
|
# Mandatory attributes
|
22
|
-
validates :info, :reference, :locations, :events, :documents,
|
24
|
+
validates :info, :reference, :locations, :events, :documents,
|
25
|
+
presence_before_type_cast: { spec_section: "4.3" }
|
23
26
|
|
24
|
-
validates :people, array: {spec_section: "4.3"}
|
25
|
-
validates :locations, :events, filled_array: {spec_section: "4.3"}
|
27
|
+
validates :people, array: { spec_section: "4.3" }
|
28
|
+
validates :locations, :events, filled_array: { spec_section: "4.3" }
|
26
29
|
|
27
30
|
# This model is only valid if the children are valid
|
28
31
|
validates :info, :reference, :locations, :events, :documents, :people, valid: true
|
@@ -1,19 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ATDIS
|
2
4
|
module Models
|
3
5
|
class Authority < Model
|
4
|
-
|
5
|
-
ref:
|
6
|
+
field_mappings(
|
7
|
+
ref: URI,
|
6
8
|
name: String
|
7
|
-
|
9
|
+
)
|
8
10
|
|
9
11
|
# ref is a "Unique Authority Identifier" and should have the form http://www.council.nsw.gov.au/atdis/1.0
|
10
12
|
# It should also be consistent for each council.
|
11
13
|
|
12
14
|
# Mandatory attributes
|
13
|
-
validates :ref, :name, presence_before_type_cast: {spec_section: "4.3.1"}
|
15
|
+
validates :ref, :name, presence_before_type_cast: { spec_section: "4.3.1" }
|
14
16
|
|
15
|
-
validates :ref, http_url: {spec_section: "4.3.1"}
|
16
|
-
validates :ref, format: {
|
17
|
+
validates :ref, http_url: { spec_section: "4.3.1" }
|
18
|
+
validates :ref, format: {
|
19
|
+
with: %r{atdis\/1.0\z},
|
20
|
+
message: ATDIS::ErrorMessage.new("is not a valid Unique Authority Identifier", "4.3.1")
|
21
|
+
}
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
@@ -1,16 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ATDIS
|
2
4
|
module Models
|
3
5
|
class Document < Model
|
4
|
-
|
5
|
-
ref:
|
6
|
-
title:
|
6
|
+
field_mappings(
|
7
|
+
ref: String,
|
8
|
+
title: String,
|
7
9
|
document_url: URI
|
8
|
-
|
10
|
+
)
|
9
11
|
|
10
12
|
# Mandatory parameters
|
11
|
-
validates :ref, :title, :document_url, presence_before_type_cast: {spec_section: "4.3.5"}
|
13
|
+
validates :ref, :title, :document_url, presence_before_type_cast: { spec_section: "4.3.5" }
|
12
14
|
# Other validations
|
13
|
-
validates :document_url, http_url: {spec_section: "4.3.5"}
|
15
|
+
validates :document_url, http_url: { spec_section: "4.3.5" }
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
data/lib/atdis/models/event.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ATDIS
|
2
4
|
module Models
|
3
5
|
class Event < Model
|
4
|
-
|
5
|
-
id:
|
6
|
-
timestamp:
|
6
|
+
field_mappings(
|
7
|
+
id: String,
|
8
|
+
timestamp: DateTime,
|
7
9
|
description: String,
|
8
|
-
event_type:
|
9
|
-
status:
|
10
|
-
|
10
|
+
event_type: String,
|
11
|
+
status: String
|
12
|
+
)
|
11
13
|
|
12
14
|
# Mandatory parameters
|
13
|
-
validates :id, :timestamp, :description, presence_before_type_cast: {spec_section: "4.3.4"}
|
15
|
+
validates :id, :timestamp, :description, presence_before_type_cast: { spec_section: "4.3.4" }
|
14
16
|
|
15
|
-
validates :timestamp, date_time: {spec_section: "4.3.8"}
|
17
|
+
validates :timestamp, date_time: { spec_section: "4.3.8" }
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/atdis/models/info.rb
CHANGED
@@ -1,91 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "atdis/models/authority"
|
2
4
|
|
3
5
|
module ATDIS
|
4
6
|
module Models
|
5
7
|
class Info < Model
|
6
|
-
|
7
|
-
dat_id:
|
8
|
-
development_type:
|
9
|
-
application_type:
|
10
|
-
last_modified_date:
|
11
|
-
description:
|
12
|
-
authority:
|
13
|
-
lodgement_date:
|
14
|
-
determination_date:
|
15
|
-
determination_type:
|
16
|
-
status:
|
8
|
+
field_mappings(
|
9
|
+
dat_id: String,
|
10
|
+
development_type: String,
|
11
|
+
application_type: String,
|
12
|
+
last_modified_date: DateTime,
|
13
|
+
description: String,
|
14
|
+
authority: Authority,
|
15
|
+
lodgement_date: DateTime,
|
16
|
+
determination_date: DateTime,
|
17
|
+
determination_type: String,
|
18
|
+
status: String,
|
17
19
|
notification_start_date: DateTime,
|
18
|
-
notification_end_date:
|
19
|
-
officer:
|
20
|
-
estimated_cost:
|
21
|
-
related_apps:
|
22
|
-
|
20
|
+
notification_end_date: DateTime,
|
21
|
+
officer: String,
|
22
|
+
estimated_cost: String,
|
23
|
+
related_apps: URI
|
24
|
+
)
|
23
25
|
|
24
26
|
# Mandatory parameters
|
25
27
|
# determination_date is not in this list because even though it is mandatory
|
26
28
|
# it can be null if there is no value
|
27
29
|
validates :dat_id, :development_type, :last_modified_date, :description,
|
28
|
-
|
29
|
-
|
30
|
+
:authority, :lodgement_date, :status,
|
31
|
+
presence_before_type_cast: { spec_section: "4.3.1" }
|
30
32
|
# Other validations
|
31
|
-
validates :application_type,
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
validates :application_type,
|
34
|
+
inclusion: {
|
35
|
+
in: %w[DA CDC S96 Review Appeal Other],
|
36
|
+
message: ATDIS::ErrorMessage.new(
|
37
|
+
"does not have one of the allowed types",
|
38
|
+
"4.3.1"
|
39
|
+
)
|
40
|
+
}
|
35
41
|
validates :last_modified_date, :lodgement_date, :determination_date,
|
36
|
-
|
37
|
-
|
42
|
+
:notification_start_date, :notification_end_date,
|
43
|
+
date_time: { spec_section: "4.3.1" }
|
38
44
|
# We don't need to separately validate presence because this covers it
|
39
|
-
validates :determination_type,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
validates :determination_type,
|
46
|
+
inclusion: {
|
47
|
+
in: [
|
48
|
+
"Pending", "Refused by Council", "Refused under delegation", "Withdrawn",
|
49
|
+
"Approved by Council", "Approved under delegation", "Rejected"
|
50
|
+
],
|
51
|
+
message: ATDIS::ErrorMessage.new(
|
52
|
+
"does not have one of the allowed types",
|
53
|
+
"4.3.1"
|
54
|
+
)
|
55
|
+
}
|
45
56
|
validate :notification_dates_consistent!
|
46
|
-
validates :related_apps, array: {spec_section: "4.3.1"}
|
47
|
-
validates :related_apps, array_http_url: {spec_section: "4.3.1"}
|
57
|
+
validates :related_apps, array: { spec_section: "4.3.1" }
|
58
|
+
validates :related_apps, array_http_url: { spec_section: "4.3.1" }
|
48
59
|
validate :related_apps_url_format
|
49
60
|
validate :dat_id_is_url_encoded!
|
50
61
|
|
51
62
|
# This model is only valid if the children are valid
|
52
63
|
validates :authority, valid: true
|
53
64
|
|
54
|
-
# TODO Validate contents of estimated_cost
|
65
|
+
# TODO: Validate contents of estimated_cost
|
55
66
|
|
56
67
|
def dat_id_is_url_encoded!
|
57
|
-
|
58
|
-
|
59
|
-
|
68
|
+
return unless dat_id && !Info.url_encoded?(dat_id)
|
69
|
+
|
70
|
+
errors.add(:dat_id, ErrorMessage.new("should be url encoded", "4.3.1"))
|
60
71
|
end
|
61
72
|
|
62
|
-
def self.url_encoded?(
|
73
|
+
def self.url_encoded?(str)
|
63
74
|
url_encoded = true
|
64
|
-
|
75
|
+
str.each_char do |c|
|
65
76
|
# These characters are the valid ones in a url encoded string
|
66
|
-
unless c =~ /[a-zA-Z0-9\-_.~%+]/
|
67
|
-
url_encoded = false
|
68
|
-
end
|
77
|
+
url_encoded = false unless c =~ /[a-zA-Z0-9\-_.~%+]/
|
69
78
|
end
|
70
79
|
url_encoded
|
71
80
|
end
|
72
81
|
|
73
82
|
def related_apps_url_format
|
74
|
-
|
75
|
-
|
76
|
-
|
83
|
+
return unless related_apps.respond_to?(:all?) &&
|
84
|
+
!related_apps.all? { |url| url.to_s =~ %r{atdis\/1.0\/[^\/]+\.json} }
|
85
|
+
|
86
|
+
errors.add(
|
87
|
+
:related_apps,
|
88
|
+
ErrorMessage.new("contains url(s) not in the expected format", "4.3.1")
|
89
|
+
)
|
77
90
|
end
|
78
91
|
|
79
92
|
def notification_dates_consistent!
|
80
93
|
if notification_start_date_before_type_cast && notification_end_date_before_type_cast.blank?
|
81
|
-
errors.add(
|
94
|
+
errors.add(
|
95
|
+
:notification_end_date,
|
96
|
+
ErrorMessage["can not be blank if notification_start_date is set", "4.3.1"]
|
97
|
+
)
|
82
98
|
end
|
83
99
|
if notification_start_date_before_type_cast.blank? && notification_end_date_before_type_cast
|
84
|
-
errors.add(
|
85
|
-
|
86
|
-
|
87
|
-
|
100
|
+
errors.add(
|
101
|
+
:notification_start_date,
|
102
|
+
ErrorMessage["can not be blank if notification_end_date is set", "4.3.1"]
|
103
|
+
)
|
88
104
|
end
|
105
|
+
return unless notification_start_date &&
|
106
|
+
notification_end_date &&
|
107
|
+
notification_start_date > notification_end_date
|
108
|
+
|
109
|
+
errors.add(
|
110
|
+
:notification_end_date,
|
111
|
+
ErrorMessage["can not be earlier than notification_start_date", "4.3.1"]
|
112
|
+
)
|
89
113
|
end
|
90
114
|
end
|
91
115
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "atdis/models/torrens_title"
|
2
4
|
|
3
5
|
module ATDIS
|
4
6
|
module Models
|
5
7
|
class LandTitleRef < Model
|
6
|
-
|
8
|
+
field_mappings(
|
7
9
|
torrens: TorrensTitle,
|
8
|
-
other:
|
9
|
-
|
10
|
+
other: Hash
|
11
|
+
)
|
10
12
|
|
11
13
|
# This model is only valid if the children are valid
|
12
14
|
validates :torrens, valid: true
|
@@ -15,11 +17,17 @@ module ATDIS
|
|
15
17
|
|
16
18
|
def check_title_presence
|
17
19
|
if torrens.nil? && other.nil?
|
18
|
-
errors.add(
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
errors.add(
|
21
|
+
:torrens,
|
22
|
+
ATDIS::ErrorMessage.new("or other needs be present", "4.3.3")
|
23
|
+
)
|
22
24
|
end
|
25
|
+
return unless torrens && other
|
26
|
+
|
27
|
+
errors.add(
|
28
|
+
:torrens,
|
29
|
+
ATDIS::ErrorMessage.new("and other can't both be present", "4.3.3")
|
30
|
+
)
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "atdis/models/address"
|
2
4
|
require "atdis/models/land_title_ref"
|
3
5
|
require "rgeo/geo_json"
|
4
6
|
|
5
7
|
module ATDIS
|
6
8
|
module Models
|
7
9
|
class Location < Model
|
8
|
-
|
9
|
-
address:
|
10
|
+
field_mappings(
|
11
|
+
address: Address,
|
10
12
|
land_title_ref: LandTitleRef,
|
11
|
-
geometry:
|
12
|
-
|
13
|
+
geometry: RGeo::GeoJSON
|
14
|
+
)
|
13
15
|
|
14
16
|
# Mandatory parameters
|
15
|
-
validates :address, :land_title_ref, presence_before_type_cast: {spec_section: "4.3.3"}
|
17
|
+
validates :address, :land_title_ref, presence_before_type_cast: { spec_section: "4.3.3" }
|
16
18
|
|
17
|
-
validates :geometry, geo_json: {spec_section: "4.3.3"}
|
19
|
+
validates :geometry, geo_json: { spec_section: "4.3.3" }
|
18
20
|
|
19
21
|
# This model is only valid if the children are valid
|
20
22
|
validates :address, :land_title_ref, valid: true
|
data/lib/atdis/models/page.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "atdis/models/response"
|
2
4
|
require "atdis/models/pagination"
|
3
5
|
|
4
6
|
module ATDIS
|
5
7
|
module Models
|
6
8
|
class Page < Model
|
7
|
-
|
8
|
-
response:
|
9
|
-
count:
|
10
|
-
pagination: Pagination
|
11
|
-
|
9
|
+
field_mappings(
|
10
|
+
response: Response,
|
11
|
+
count: Integer,
|
12
|
+
pagination: Pagination
|
13
|
+
)
|
12
14
|
|
13
15
|
# Mandatory parameters
|
14
|
-
validates :response, presence_before_type_cast: {spec_section: "4.3"}
|
15
|
-
# section 6.5 is not explicitly about this but it does contain an example
|
16
|
-
|
16
|
+
validates :response, presence_before_type_cast: { spec_section: "4.3" }
|
17
|
+
# section 6.5 is not explicitly about this but it does contain an example
|
18
|
+
# which should be helpful
|
19
|
+
validates :response, array: { spec_section: "6.4" }
|
17
20
|
validate :count_is_consistent, :all_pagination_is_present
|
18
21
|
|
19
22
|
# This model is only valid if the children are valid
|
@@ -22,38 +25,50 @@ module ATDIS
|
|
22
25
|
|
23
26
|
# If some of the pagination fields are present all of the required ones should be present
|
24
27
|
def all_pagination_is_present
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
return unless pagination && count.nil?
|
29
|
+
|
30
|
+
errors.add(:count, ErrorMessage["should be present if pagination is being used", "6.4"])
|
28
31
|
end
|
29
32
|
|
30
33
|
def count_is_consistent
|
31
|
-
if count
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
return if count.nil?
|
35
|
+
|
36
|
+
if response.respond_to?(:count)
|
37
|
+
if count != response.count
|
38
|
+
errors.add(
|
39
|
+
:count,
|
40
|
+
ErrorMessage["is not the same as the number of applications returned", "6.4"]
|
41
|
+
)
|
37
42
|
end
|
38
43
|
end
|
44
|
+
return unless pagination.respond_to?(:per_page) && pagination.per_page
|
45
|
+
|
46
|
+
return unless count > pagination.per_page
|
47
|
+
|
48
|
+
errors.add(
|
49
|
+
:count,
|
50
|
+
ErrorMessage["should not be larger than the number of results per page", "6.4"]
|
51
|
+
)
|
39
52
|
end
|
40
53
|
|
41
54
|
def previous_url
|
42
55
|
raise "Can't use previous_url when loaded with read_json" if url.nil?
|
43
|
-
|
56
|
+
|
57
|
+
ATDIS::SeparatedURL.merge(url, page: pagination.previous) if pagination&.previous
|
44
58
|
end
|
45
59
|
|
46
60
|
def next_url
|
47
61
|
raise "Can't use next_url when loaded with read_json" if url.nil?
|
48
|
-
|
62
|
+
|
63
|
+
ATDIS::SeparatedURL.merge(url, page: pagination.next) if pagination&.next
|
49
64
|
end
|
50
65
|
|
51
66
|
def previous_page
|
52
|
-
Page.read_url(previous_url) if previous_url
|
67
|
+
Page.read_url(previous_url, timezone) if previous_url
|
53
68
|
end
|
54
69
|
|
55
70
|
def next_page
|
56
|
-
Page.read_url(next_url) if next_url
|
71
|
+
Page.read_url(next_url, timezone) if next_url
|
57
72
|
end
|
58
73
|
end
|
59
74
|
end
|