arcrest 0.0.0.pre → 0.0.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 +4 -4
- data/.rspec +1 -0
- data/.travis.yml +2 -3
- data/Guardfile +13 -0
- data/README.md +98 -4
- data/arcrest.gemspec +3 -0
- data/lib/arcrest/attributable.rb +20 -0
- data/lib/arcrest/catalog.rb +19 -0
- data/lib/arcrest/layer.rb +91 -0
- data/lib/arcrest/server.rb +48 -0
- data/lib/arcrest/service.rb +25 -0
- data/lib/arcrest/version.rb +1 -1
- data/lib/arcrest.rb +6 -3
- metadata +53 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 948887626e3cbf6c38a60ab4d3f3f96f38815a64
|
4
|
+
data.tar.gz: ee36b210de6e5354e2afae62ec6b3ba3bdbb44d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3bfa45f4ea1fa30629e216122fe40783d3519b78e9e592e6e14ea41082b0e88d18bc8e284f101da40a07610ec69154772a99256b9748cf30f62e4905d89edbd
|
7
|
+
data.tar.gz: 736154f7a57441c74bb37234b500a3126c258ce173adc4aa5e0a7b5af2ca2be38f7c55d7aad7952cace2f82337d7529a638538ff238e02cf630b7f578ccf9509
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
notification :gntp
|
2
|
+
|
3
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
4
|
+
watch(%r{^lib/(.+).rb$}) do |m| # watch /lib/ files
|
5
|
+
"spec/#{m[1]}_spec.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
watch(%r{^spec/(.+).rb$}) do |m| # watch /spec/ files
|
9
|
+
"spec/#{m[1]}.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
13
|
+
end
|
data/README.md
CHANGED
@@ -1,19 +1,113 @@
|
|
1
|
-
#
|
1
|
+
# ArcREST
|
2
|
+
[](http://travis-ci.org/MatzFan/ArcREST)
|
3
|
+
[](http://badge.fury.io/rb/arcrest)
|
4
|
+
|
5
|
+
Ruby Gem wrapper around the [ArcGIS REST API](http://services.arcgisonline.com/arcgis/sdk/rest/)
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
bundler
|
10
|
+
|
11
|
+
|
12
|
+
## Current Limitations
|
13
|
+
|
14
|
+
API FeatureServer query capabilities only at present. Unauthenticated calls only (please raise an issue if you wish this to be supported)
|
2
15
|
|
3
|
-
Placeholder for arcrest Ruby Gem
|
4
16
|
|
5
17
|
## Installation
|
6
18
|
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
$ gem 'arcrest'
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
7
29
|
$ gem install arcrest
|
8
30
|
|
31
|
+
|
9
32
|
## Usage
|
10
33
|
|
11
|
-
|
34
|
+
The API defines a [resource heirarchy](http://services.arcgisonline.com/arcgis/sdk/rest/#/Resource_hierarchy) which includes a Catalog of Services (MapServer or FeatureServer). Services have one or more Layers and Layers have Features, which may be queried in various ways, including by spatial coordinates.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'arcrest'
|
38
|
+
|
39
|
+
catalog = ArcREST::Catalog.new('http://rmgsc.cr.usgs.gov/arcgis/rest/services')
|
40
|
+
puts catalog.services
|
41
|
+
#=> {"name"=>"cwqdr_main", "type"=>"MapServer"}
|
42
|
+
#=> {"name"=>"ecosys_Africa", "type"=>"MapServer"}
|
43
|
+
#=> {"name"=>"ecosys_SA", "type"=>"MapServer"}
|
44
|
+
#=> ...
|
45
|
+
|
46
|
+
service = ArcREST::Service.new('http://rmgsc.cr.usgs.gov/arcgis/rest/services/geomac_fires/FeatureServer')
|
47
|
+
puts service.layers
|
48
|
+
#=> {"id"=>1, "name"=>"Large Fire Points"}
|
49
|
+
#=> {"id"=>2, "name"=>"Fire Perimeters"}
|
50
|
+
#=> {"id"=>3, "name"=>"MODIS Thermal Satellite"}
|
51
|
+
#=> {"id"=>4, "name"=>"Inactive Fire Perimeters"}
|
52
|
+
|
53
|
+
layer = ArcREST::Layer.new("#{service.url}/2")
|
54
|
+
puts layer.name
|
55
|
+
#=> Fire Perimeters
|
56
|
+
puts layer.type
|
57
|
+
#=> Feature Layer
|
58
|
+
puts layer.count
|
59
|
+
#=> 14 # count of the layer's features
|
60
|
+
puts layer.object_ids.inspect
|
61
|
+
#=> [681, 682, 688, 690, 614, 618, 619, 653, 683, 684, 685, 686, 687, 689]
|
62
|
+
puts layer.fields
|
63
|
+
#=> {"name"=>"objectid", "type"=>"esriFieldTypeOID", "alias"=>"OBJECTID", "domain"=>nil, "editable"=>false, "nullable"=>false}
|
64
|
+
#=> {"name"=>"agency", "type"=>"esriFieldTypeString", "alias"=>"agency", "domain"=>nil, "editable"=>true, "nullable"=>true, "length"=>15}
|
65
|
+
#=> ...
|
66
|
+
```
|
67
|
+
|
68
|
+
Once you have a Layer object, you can query it's features. The [documention](http://services.arcgisonline.com/arcgis/sdk/rest/index.html#/Query_Feature_Service_Layer/) shows the possibilities. Here is a very simple example:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
features = layer.features(where: "agency='BLM'", returnGeometry: false)
|
72
|
+
puts features.count
|
73
|
+
#=> 2
|
74
|
+
puts features.first
|
75
|
+
#=> {"objectid"=>690, "agency"=>"BLM", "comments"=>" ", "active"=>"Y"...
|
76
|
+
```
|
77
|
+
|
78
|
+
```features``` takes an options hash of API call params. Invalid key values raise an error. Valid params for the server can be listed like this:
|
79
|
+
```ruby
|
80
|
+
puts layer.valid_opts.inspect
|
81
|
+
#=> ["dbVersion", "distance", "geometry", "geometryPrecision"...
|
82
|
+
```
|
83
|
+
or by consulting the [docs](http://services.arcgisonline.com/arcgis/sdk/rest/index.html#/Query_Feature_Service_Layer/). One default is set: ```outFields: '*'``` - which requests data for all fields.
|
84
|
+
|
85
|
+
|
86
|
+
The ```:where``` key is used with any valid SQL to query the layer fields. The default is '1=1' which returns all records (up to the ```@max_record_count``` value, usually 1,000). An InvalidQuery error is raised if the server gives a 400 error of this form:
|
87
|
+
```json
|
88
|
+
{
|
89
|
+
"error": {
|
90
|
+
"code": 400,
|
91
|
+
"message": "Unable to complete operation.",
|
92
|
+
"details": [
|
93
|
+
"Unable to perform query operation.",
|
94
|
+
"Invalid query"
|
95
|
+
]
|
96
|
+
}
|
97
|
+
}
|
98
|
+
```
|
99
|
+
|
100
|
+
|
101
|
+
## Specification & Tests
|
102
|
+
|
103
|
+
Full specification documentation is available for each build at [Travis](https://travis-ci.org/MatzFan/ArcREST). To run the tests yourself clone this repo and run:
|
104
|
+
|
105
|
+
$ rake spec
|
12
106
|
|
13
107
|
|
14
108
|
## Contributing
|
15
109
|
|
16
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
110
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/MatzFan/arcrest
|
17
111
|
|
18
112
|
|
19
113
|
## License
|
data/arcrest.gemspec
CHANGED
@@ -24,4 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
25
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
|
+
spec.add_development_dependency 'guard', '~> 2.14'
|
28
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
29
|
+
spec.add_development_dependency 'ruby_gntp', '~> 0.3' # guard notifications
|
27
30
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# adds ability to dynamically set instance vars & accessors
|
2
|
+
module Attributable
|
3
|
+
def create_method(name, &block)
|
4
|
+
self.class.send(:define_method, name.to_sym, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def create_setter(m)
|
8
|
+
create_method("#{m}=".to_sym) { |v| instance_variable_set("@#{m}", v) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_getter(m)
|
12
|
+
create_method(m.to_sym) { instance_variable_get("@#{m}") }
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_attr(method, value)
|
16
|
+
create_setter(method)
|
17
|
+
send "#{method}=".to_sym, value
|
18
|
+
create_getter(method)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ArcREST
|
2
|
+
# a catalog of services
|
3
|
+
class Catalog < Server
|
4
|
+
attr_reader :folders, :services
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
super
|
8
|
+
@services = services
|
9
|
+
end
|
10
|
+
|
11
|
+
def folders
|
12
|
+
@json['folders']
|
13
|
+
end
|
14
|
+
|
15
|
+
def services
|
16
|
+
@json['services']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module ArcREST
|
2
|
+
class InvalidOption < StandardError; end
|
3
|
+
class InvalidQuery < StandardError; end
|
4
|
+
# a layer
|
5
|
+
class Layer < Server
|
6
|
+
include Attributable
|
7
|
+
|
8
|
+
ERR = 'error'.freeze
|
9
|
+
ATTRIBUTES = %w(id name type drawing_info fields max_record_count).freeze
|
10
|
+
DEFAULT_PARAMS = { where: '1=1', outFields: '*' }.freeze
|
11
|
+
PARAMS = %w(distance geometry geometryType inSR objectIds
|
12
|
+
outFields outSR relationParam returnDistinceValues
|
13
|
+
returnIdsOnly spatialRel time where).freeze
|
14
|
+
PARAMS_SP1 = %w(returnCountOnly).freeze
|
15
|
+
PARAMS_10_1 = %w(dbVersion geometryPrecision groupByFieldsForStatistics
|
16
|
+
maxAllowableOffset multiPatchOption orderByFields
|
17
|
+
outStatistics returnGeometry returnM returnZ).freeze
|
18
|
+
PARAMS_10_3 = %w(returnExtentOnly resultOffset resultRecordCount).freeze
|
19
|
+
|
20
|
+
attr_reader :valid_params # other accessors set in constructor
|
21
|
+
|
22
|
+
def initialize(url)
|
23
|
+
super
|
24
|
+
generate_attributes # dynamically create & assign values to attributes :)
|
25
|
+
end
|
26
|
+
|
27
|
+
def count
|
28
|
+
@version > 10 ? count_only_true : object_ids.count # v10.1 onwards
|
29
|
+
end
|
30
|
+
|
31
|
+
def object_ids # care - must specify outFields to overide default '*'
|
32
|
+
query(outFields: nil, returnIdsOnly: true)['objectIds']
|
33
|
+
end
|
34
|
+
|
35
|
+
def features(options = {})
|
36
|
+
query(options)['features']
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid_opts
|
40
|
+
return PARAMS if @version < 10 || @version == 10.0
|
41
|
+
return (PARAMS + PARAMS_SP1).sort if @version < 10.1
|
42
|
+
return (PARAMS + PARAMS_SP1 + PARAMS_10_1).sort if @version < 10.2
|
43
|
+
(PARAMS + PARAMS_SP1 + PARAMS_10_1 + PARAMS_10_3).sort
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def generate_attributes
|
49
|
+
ATTRIBUTES.each { |name| set_attr(name, json_value(name)) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def json_value(name)
|
53
|
+
@json[camelify(name)]
|
54
|
+
end
|
55
|
+
|
56
|
+
def camelify(name)
|
57
|
+
words = name.split('_')
|
58
|
+
words[1..-1].map(&:capitalize).unshift(words.first).join
|
59
|
+
end
|
60
|
+
|
61
|
+
def query(options)
|
62
|
+
validate(options.keys.map(&:to_s).sort)
|
63
|
+
valid_resp(build_uri, DEFAULT_PARAMS.merge(options))
|
64
|
+
end
|
65
|
+
|
66
|
+
def valid_resp(uri, opts)
|
67
|
+
raise InvalidQuery, m(opts) if (resp = json(uri, opts)).keys.include? ERR
|
68
|
+
resp
|
69
|
+
end
|
70
|
+
|
71
|
+
def m(options)
|
72
|
+
"The following query parameters resulted in a 400 response:\n#{options}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate(keys)
|
76
|
+
keys.all? { |k| raise InvalidOption, msg(k) unless valid_opts.include? k }
|
77
|
+
end
|
78
|
+
|
79
|
+
def msg(key)
|
80
|
+
"'#{key}' is an invalid option, valid query options are:\n#{PARAMS}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def count_only_true
|
84
|
+
query(returnCountOnly: true)['count']
|
85
|
+
end
|
86
|
+
|
87
|
+
def build_uri
|
88
|
+
URI::HTTP.build(host: @uri.host, path: "#{@uri.path}/query")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module ArcREST
|
5
|
+
# adds metadata method
|
6
|
+
class Server
|
7
|
+
REGEX = %r{^\/arcgis\/rest\/services}i
|
8
|
+
BAD_ENDPOINT = 'Invalid ArcGIS endpoint'.freeze
|
9
|
+
|
10
|
+
attr_reader :url, :json, :version
|
11
|
+
|
12
|
+
def initialize(url)
|
13
|
+
@url = url
|
14
|
+
@uri = uri
|
15
|
+
@server_uri = server_uri
|
16
|
+
@json = json(@uri)
|
17
|
+
@version = version
|
18
|
+
end
|
19
|
+
|
20
|
+
def json(uri, options = {})
|
21
|
+
JSON.parse get(uri, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def version
|
25
|
+
json(server_uri)['currentVersion'] # subclasses use server uri
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def uri
|
31
|
+
raise ArgumentError, BAD_ENDPOINT if (URI(@url).path =~ REGEX) != 0
|
32
|
+
URI @url
|
33
|
+
end
|
34
|
+
|
35
|
+
def server_uri
|
36
|
+
URI::HTTP.build(host: @uri.host, path: '/arcgis/rest/services')
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_json_param_to(hash)
|
40
|
+
{ f: 'pjson' }.merge(hash) # 'pjson' guarantees id's unique
|
41
|
+
end
|
42
|
+
|
43
|
+
def get(uri, options = {})
|
44
|
+
uri.query = URI.encode_www_form(add_json_param_to(options))
|
45
|
+
Net::HTTP.get uri
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ArcREST
|
2
|
+
# a FeatureService or a MapService
|
3
|
+
class Service < Server
|
4
|
+
attr_reader :max_record_count, :capabilities, :layers
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
super
|
8
|
+
@max_record_count = max_record_count # may be nil
|
9
|
+
@capabilities = capabilities # may be empty
|
10
|
+
@layers = layers # may be empty
|
11
|
+
end
|
12
|
+
|
13
|
+
def max_record_count
|
14
|
+
@json['maxRecordCount']
|
15
|
+
end
|
16
|
+
|
17
|
+
def capabilities
|
18
|
+
@json['capabilities'] ? @json['capabilities'].split(',') : nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def layers
|
22
|
+
@json['layers']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/arcrest/version.rb
CHANGED
data/lib/arcrest.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
require 'arcrest/attributable' # module
|
1
2
|
require 'arcrest/version'
|
3
|
+
require 'arcrest/server'
|
4
|
+
require 'arcrest/catalog'
|
5
|
+
require 'arcrest/service'
|
6
|
+
require 'arcrest/layer'
|
2
7
|
|
3
8
|
# namespace
|
4
|
-
module
|
5
|
-
# Your code goes here...
|
6
|
-
end
|
9
|
+
module ArcRest; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arcrest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruce Steedman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,48 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.14'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ruby_gntp
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.3'
|
55
97
|
description: Wrapper for ArcGIS REST API
|
56
98
|
email:
|
57
99
|
- bruce.steedman@gmail.com
|
@@ -63,6 +105,7 @@ files:
|
|
63
105
|
- ".rspec"
|
64
106
|
- ".travis.yml"
|
65
107
|
- Gemfile
|
108
|
+
- Guardfile
|
66
109
|
- LICENSE.txt
|
67
110
|
- README.md
|
68
111
|
- Rakefile
|
@@ -70,6 +113,11 @@ files:
|
|
70
113
|
- bin/console
|
71
114
|
- bin/setup
|
72
115
|
- lib/arcrest.rb
|
116
|
+
- lib/arcrest/attributable.rb
|
117
|
+
- lib/arcrest/catalog.rb
|
118
|
+
- lib/arcrest/layer.rb
|
119
|
+
- lib/arcrest/server.rb
|
120
|
+
- lib/arcrest/service.rb
|
73
121
|
- lib/arcrest/version.rb
|
74
122
|
homepage: https://github.com/MatzFan/arcrest
|
75
123
|
licenses:
|
@@ -86,12 +134,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
134
|
version: '0'
|
87
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
136
|
requirements:
|
89
|
-
- - "
|
137
|
+
- - ">="
|
90
138
|
- !ruby/object:Gem::Version
|
91
|
-
version:
|
139
|
+
version: '0'
|
92
140
|
requirements: []
|
93
141
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.
|
142
|
+
rubygems_version: 2.5.1
|
95
143
|
signing_key:
|
96
144
|
specification_version: 4
|
97
145
|
summary: Wrapper for ArcGIS REST API
|