georeferencer 0.1.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/.gitignore +8 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +51 -0
- data/LICENSE.txt +21 -0
- data/README.md +94 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/georeferencer.gemspec +33 -0
- data/lib/georeferencer.rb +68 -0
- data/lib/georeferencer/engine.rb +13 -0
- data/lib/georeferencer/middleware/headers.rb +14 -0
- data/lib/georeferencer/middleware/parser.rb +27 -0
- data/lib/georeferencer/mixins/base.rb +18 -0
- data/lib/georeferencer/mixins/collection_cache.rb +46 -0
- data/lib/georeferencer/mixins/collection_iterator.rb +41 -0
- data/lib/georeferencer/mixins/object_cache.rb +95 -0
- data/lib/georeferencer/models/contributor.rb +11 -0
- data/lib/georeferencer/models/image.rb +28 -0
- data/lib/georeferencer/models/progress.rb +16 -0
- data/lib/georeferencer/version.rb +3 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c474fda4cb96db637cd8444f3b103cc71bf0080b43d5fd8d4b8773f2f2a28841
|
4
|
+
data.tar.gz: b3a1fb73beb3341bdd5d0aa77585278536991319b831b8a4966da90d9971b680
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cde9684b35356cf528226493ce44a5ebf41bad40ed71a52338b1c06394fc36c4134877fe067334f3a1c91a5810e249c283298881dc2f736443c386a377aaf685
|
7
|
+
data.tar.gz: 628249df275022300f26e424253bdfca8cf21f8c50e6234b5f7cd879542094e4ee41f59a7a037c1c2634e19979041d5ac8af268138aedd07a1c24fb616507919
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
georeferencer
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.3
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
georeferencer (0.1.0)
|
5
|
+
activesupport
|
6
|
+
faraday_middleware
|
7
|
+
her
|
8
|
+
oj
|
9
|
+
require_all
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
activemodel (5.2.2.1)
|
15
|
+
activesupport (= 5.2.2.1)
|
16
|
+
activesupport (5.2.2.1)
|
17
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
18
|
+
i18n (>= 0.7, < 2)
|
19
|
+
minitest (~> 5.1)
|
20
|
+
tzinfo (~> 1.1)
|
21
|
+
concurrent-ruby (1.1.5)
|
22
|
+
faraday (0.15.4)
|
23
|
+
multipart-post (>= 1.2, < 3)
|
24
|
+
faraday_middleware (0.13.1)
|
25
|
+
faraday (>= 0.7.4, < 1.0)
|
26
|
+
her (1.1.0)
|
27
|
+
activemodel (>= 4.2.1)
|
28
|
+
faraday (>= 0.8, < 1.0)
|
29
|
+
multi_json (~> 1.7)
|
30
|
+
i18n (1.6.0)
|
31
|
+
concurrent-ruby (~> 1.0)
|
32
|
+
minitest (5.11.3)
|
33
|
+
multi_json (1.13.1)
|
34
|
+
multipart-post (2.0.0)
|
35
|
+
oj (3.7.9)
|
36
|
+
rake (10.5.0)
|
37
|
+
require_all (2.0.0)
|
38
|
+
thread_safe (0.3.6)
|
39
|
+
tzinfo (1.2.5)
|
40
|
+
thread_safe (~> 0.1)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
bundler (~> 1.16)
|
47
|
+
georeferencer!
|
48
|
+
rake (~> 10.0)
|
49
|
+
|
50
|
+
BUNDLED WITH
|
51
|
+
1.16.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Error Agency
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Georeferencer - a Ruby client for [Georeferencer](http://www.georeferencer.com)
|
2
|
+
This is a Ruby library which allows you to get data from Georeferencer about images you've submitted to be georeferenced, along with progress data and contributors.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'georeferencer'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install georeferencer
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
You need at least the subdomain of your Georeferencer account. Here's a full list of all the configurable options with their defaults:
|
23
|
+
|
24
|
+
```
|
25
|
+
Georeferencer.configure do |config|
|
26
|
+
config.proxy = nil
|
27
|
+
# Configure your proxy address here - e.g.
|
28
|
+
# config.proxy = "https://localhost:9998"
|
29
|
+
|
30
|
+
config.ssl_options = nil
|
31
|
+
# options passed to ssl_options will be passed on to Faraday - e.g.
|
32
|
+
# config.ssl_options = {
|
33
|
+
# verify: false
|
34
|
+
# }
|
35
|
+
config.subdomain = 'yoursubdomain'
|
36
|
+
config.perform_caching = false
|
37
|
+
config.cache = ActiveSupport::Cache.lookup_store(:memory_store)
|
38
|
+
config.logger = Logger.new(STDOUT)
|
39
|
+
config.user_agent = "Georeferencer Ruby Client #{Georeferencer::VERSION} (https://github.com/layersoflondon/georeferencer-ruby)"
|
40
|
+
end
|
41
|
+
|
42
|
+
```
|
43
|
+
|
44
|
+
A minimal example would be :
|
45
|
+
|
46
|
+
```
|
47
|
+
Georeferencer.configure do |config|
|
48
|
+
config.subdomain = 'yoursubdomain'
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
If you're using this gem in Rails, the logger and caching settings will follow those you've set in your Rails configuration.
|
53
|
+
|
54
|
+
## Usage
|
55
|
+
|
56
|
+
### Images
|
57
|
+
Get a list of images:
|
58
|
+
|
59
|
+
```
|
60
|
+
Georeferencer::Image.all
|
61
|
+
|
62
|
+
```
|
63
|
+
|
64
|
+
There is a scope defined for unreferenced images:
|
65
|
+
|
66
|
+
```
|
67
|
+
Georeferencer::Image.unreferenced
|
68
|
+
```
|
69
|
+
|
70
|
+
And you can pass in a collection name:
|
71
|
+
|
72
|
+
```
|
73
|
+
Georeferencer::Image.where(collection: 'my-collection')
|
74
|
+
```
|
75
|
+
|
76
|
+
There is no endpoint to get a list of collections but Klokan can provide them.
|
77
|
+
|
78
|
+
## Contributors
|
79
|
+
|
80
|
+
Contributors work in the same way, although there is no 'detail' page for contributors.
|
81
|
+
|
82
|
+
```
|
83
|
+
Georeferencer::Contributor.all
|
84
|
+
|
85
|
+
```
|
86
|
+
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/layersoflondon/georeferencer.
|
91
|
+
|
92
|
+
## License
|
93
|
+
|
94
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "georeferencer"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "georeferencer/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "georeferencer"
|
8
|
+
spec.version = Georeferencer::VERSION
|
9
|
+
spec.authors = ["Ed Jones", "Paul Hendrick"]
|
10
|
+
spec.email = ["ed@error.agency", "paul@error.agency"]
|
11
|
+
|
12
|
+
spec.summary = %q{A Ruby client for Georeferencer}
|
13
|
+
spec.homepage = "https://github.com/layersoflondon/georeferencer-ruby"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
# Specify which files should be added to the gem when it is released.
|
17
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
18
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
19
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
end
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
|
28
|
+
spec.add_dependency 'her'
|
29
|
+
spec.add_dependency 'faraday_middleware'
|
30
|
+
spec.add_dependency 'require_all'
|
31
|
+
spec.add_dependency 'oj'
|
32
|
+
spec.add_dependency 'activesupport'
|
33
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'her'
|
2
|
+
require 'oj'
|
3
|
+
require 'require_all'
|
4
|
+
require "active_support/all"
|
5
|
+
require 'digest'
|
6
|
+
|
7
|
+
|
8
|
+
module Georeferencer
|
9
|
+
|
10
|
+
API_PATH = 'api/v1'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :configuration
|
14
|
+
def configure
|
15
|
+
self.configuration ||= Configuration.new
|
16
|
+
yield(configuration)
|
17
|
+
self.configuration.configure_connection
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Configuration
|
22
|
+
attr_accessor :proxy, :ssl_options, :perform_caching, :cache, :subdomain, :logger, :user_agent
|
23
|
+
attr_reader :connection, :user_agent
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@connection ||= Her::API.new
|
27
|
+
@ssl_options = {}
|
28
|
+
@proxy = nil
|
29
|
+
@user_agent = "Georeferencer Ruby Client #{Georeferencer::VERSION} (https://github.com/layersoflondon/georeferencer-ruby)"
|
30
|
+
@cache = ActiveSupport::Cache.lookup_store(:memory_store)
|
31
|
+
@perform_caching = false
|
32
|
+
@logger = Logger.new(STDOUT)
|
33
|
+
end
|
34
|
+
|
35
|
+
def configure_connection
|
36
|
+
raise ArgumentError, "you need to specify a georeferencer subdomain" unless @subdomain.present?
|
37
|
+
@connection.setup url: "https://#{@subdomain}.georeferencer.com/#{Georeferencer::API_PATH}", ssl: @ssl_options, proxy: @proxy do |c|
|
38
|
+
|
39
|
+
# Request
|
40
|
+
c.use Georeferencer::Headers
|
41
|
+
|
42
|
+
c.use Faraday::Request::UrlEncoded
|
43
|
+
|
44
|
+
# Response
|
45
|
+
c.use Georeferencer::Parser
|
46
|
+
|
47
|
+
# Adapter
|
48
|
+
c.use Faraday::Adapter::NetHttp
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
class Error < StandardError
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
require 'georeferencer/version'
|
60
|
+
require_rel 'georeferencer/mixins'
|
61
|
+
require_rel 'georeferencer/middleware'
|
62
|
+
require_rel 'georeferencer/models'
|
63
|
+
if defined?(Rails)
|
64
|
+
require 'georeferencer/engine'
|
65
|
+
end
|
66
|
+
|
67
|
+
Her::Model::Relation.prepend(Georeferencer::CollectionIterator)
|
68
|
+
Her::Model::Relation.prepend(Georeferencer::CollectionCache)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
isolate_namespace Georeferencer
|
4
|
+
|
5
|
+
config.after_initialize do
|
6
|
+
Georeferencer.configuration.logger ||= Rails.logger
|
7
|
+
Georeferencer.configuration.cache ||= Rails.cache
|
8
|
+
Georeferencer.configuration.perform_caching ||= Rails.configuration.action_controller.perform_caching
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
class Headers < Faraday::Middleware
|
3
|
+
def call(env)
|
4
|
+
# Add custom UA String
|
5
|
+
env[:request_headers]["User-Agent"] = Georeferencer.configuration.user_agent
|
6
|
+
|
7
|
+
|
8
|
+
# Fix url-encoded percent signs
|
9
|
+
env.url.query = env.url.query.gsub(/%25/,'%')
|
10
|
+
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
class Parser < Faraday::Response::Middleware
|
3
|
+
def on_complete(env)
|
4
|
+
json = Oj.load(env[:body], symbolize_keys: true)
|
5
|
+
if json.has_key?("@list")
|
6
|
+
start = nil
|
7
|
+
|
8
|
+
if json["next"].present?
|
9
|
+
query = URI.parse(json["next"]).query
|
10
|
+
start = query.scan(/start=([^$]+)/).flatten.first
|
11
|
+
end
|
12
|
+
|
13
|
+
body = {
|
14
|
+
data: json["@list"]
|
15
|
+
}
|
16
|
+
|
17
|
+
body.merge!({metadata: {start: start}})
|
18
|
+
env[:body] = body
|
19
|
+
else
|
20
|
+
env[:body] = {
|
21
|
+
data: json.with_indifferent_access
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
module Base
|
3
|
+
def self.included(base)
|
4
|
+
base.include Her::Model
|
5
|
+
base.include Georeferencer::ObjectCache
|
6
|
+
base.send(:use_api, ->{Georeferencer.configuration.connection})
|
7
|
+
|
8
|
+
base.extend ClassMethods
|
9
|
+
base.preload_resources = false
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
attr_accessor :preload_resources
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
module CollectionCache
|
3
|
+
def fetch
|
4
|
+
raise ArgumentError, "You need to configure Georeferencer before you make requests" unless Georeferencer.configuration.present?
|
5
|
+
if Georeferencer.configuration.perform_caching
|
6
|
+
# Sort the arguments - reduces the number of different argument hashes.
|
7
|
+
# Note that 2 different arg hashes might actually be the same, with child arrays
|
8
|
+
# in a different order. But we won't mess with the order of the child arrays
|
9
|
+
# because sometimes that's important.
|
10
|
+
args = @params.sort_by {|k,v| k.to_s}.to_h
|
11
|
+
# Generate a hash for keying the cache of the results
|
12
|
+
args_hash = Digest::MD5.hexdigest(args.to_s)
|
13
|
+
cache_key = "#{@parent.cache_key_base}/collection_query/#{args_hash}"
|
14
|
+
# first see if we have a collection which matches the args
|
15
|
+
cached_collection = Georeferencer.configuration.cache.read(cache_key)
|
16
|
+
# if it's present, then we can return it directly.
|
17
|
+
if cached_collection.present?
|
18
|
+
Georeferencer.configuration.logger.debug("Returning cached Georeferencer collection for #{cache_key}")
|
19
|
+
cached_collection.each {|o| o.run_callbacks :find}
|
20
|
+
return cached_collection
|
21
|
+
else
|
22
|
+
# If not, then we need to call super to get it from the API
|
23
|
+
collection = super
|
24
|
+
# and write it into the cache
|
25
|
+
Georeferencer.configuration.cache.write(cache_key,collection)
|
26
|
+
# We also iterate over the collection and cache each object, and cache the argument hash against each object
|
27
|
+
collection.each do |object|
|
28
|
+
# We store an array of hashes for queries to which this object belongs.
|
29
|
+
# If the object cache needs to be removed, we can iterate through those hashes and clear the collection caches too.
|
30
|
+
collection_query_hash_key = "#{object.cache_key}/collection_hashes"
|
31
|
+
collection_hashes = Georeferencer.configuration.cache.read(collection_query_hash_key) || []
|
32
|
+
collection_hashes << args_hash
|
33
|
+
Georeferencer.configuration.cache.write(collection_query_hash_key, collection_hashes)
|
34
|
+
# this is the object cache - i.e. it'll respond with a cache lookup for Georeferencer::Image.find(1234) or whatever
|
35
|
+
Georeferencer.configuration.cache.write(object.cache_key,object)
|
36
|
+
Georeferencer.configuration.logger.debug("Written cached georeferencer collection for #{object.cache_key}")
|
37
|
+
end
|
38
|
+
collection
|
39
|
+
end
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
# This is mixed into Her::Model::Relation and redefines how `fetch()` works, iterating over pages from the GR endpoint
|
3
|
+
module CollectionIterator
|
4
|
+
|
5
|
+
def fetch
|
6
|
+
# only invoke this is the parent is a Georeferencer class
|
7
|
+
if @parent.ancestors.include?(Georeferencer::Base)
|
8
|
+
# get the collection
|
9
|
+
@_collection = super
|
10
|
+
metadata = @_collection.metadata.except(:start)
|
11
|
+
|
12
|
+
# check the params don't specifically include a :start argument (in which case we don't need to loop),
|
13
|
+
# and that the response metadata includes a :start key
|
14
|
+
if !(@params.keys.include?(:start) || @params.keys.include?("start")) && @_collection.metadata[:start].present?
|
15
|
+
@params.merge!(start: @_collection.metadata[:start])
|
16
|
+
loop do
|
17
|
+
clear_fetch_cache!
|
18
|
+
new_collection = super
|
19
|
+
@_collection += new_collection
|
20
|
+
if new_collection.metadata[:start].present? && new_collection.metadata[:start] != @params[:start]
|
21
|
+
@params.merge!(start: new_collection.metadata[:start])
|
22
|
+
else
|
23
|
+
break
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if @parent.preload_resources == true
|
29
|
+
Her::Collection.new(@_collection.collect(&:reload), metadata)
|
30
|
+
else
|
31
|
+
Her::Collection.new(@_collection, metadata)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
# This mixin adds object caching when you call find(). It overloads the find() method to cache the result, and read that instead if possible.
|
3
|
+
module ObjectCache
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Utility method to get the cache key for the instance.
|
9
|
+
def cache_key
|
10
|
+
"#{self.class.cache_key_base}/#{self.id}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def expire_cache!
|
14
|
+
self.class.send(:expire_cache_for, self.id)
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :expire!, :expire_cache!
|
18
|
+
|
19
|
+
def reload
|
20
|
+
if Georeferencer.configuration.perform_caching
|
21
|
+
expire_cache!
|
22
|
+
end
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
|
28
|
+
# Base of the cache key for this class.
|
29
|
+
def cache_key_base
|
30
|
+
"georeferencer/#{Georeferencer::VERSION}/#{self.to_s.underscore}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Redeclare the find() method, with caching. Only pass uncached keys to the super method.
|
34
|
+
def find(*ids)
|
35
|
+
if Georeferencer.configuration.perform_caching
|
36
|
+
ids.uniq!
|
37
|
+
uncached_ids = ids.reject {|i| Georeferencer.configuration.cache.read("#{cache_key_base}/#{i}").present?}
|
38
|
+
[super(*uncached_ids)].flatten.reject(&:blank?).collect do |object|
|
39
|
+
Georeferencer.configuration.logger.debug("Caching #{cache_key_base}/#{object.id}")
|
40
|
+
Georeferencer.configuration.cache.write(object.cache_key, object)
|
41
|
+
end
|
42
|
+
all_objects = ids.collect do |id|
|
43
|
+
Georeferencer.configuration.cache.read("#{cache_key_base}/#{id}")
|
44
|
+
end
|
45
|
+
|
46
|
+
all_objects.each {|o| o.run_callbacks(:find)}
|
47
|
+
all_objects.length == 1 ? all_objects.first : all_objects
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# A method to expire the relevant caches for a collection of objects or ids
|
55
|
+
# @param args [Array] of either objects which respond to `.id`, or ids themselves
|
56
|
+
def expire_cache_for(*args)
|
57
|
+
args = args.collect {|a| a.respond_to?(:id) ? a.id : a}.flatten
|
58
|
+
# the caches we need to clear are:
|
59
|
+
# - the object cache
|
60
|
+
# - any collection caches which included this object
|
61
|
+
args.each do |id|
|
62
|
+
object_cache_key = "#{cache_key_base}/#{id}"
|
63
|
+
object_collections = Georeferencer.configuration.cache.read("#{object_cache_key}/collection_hashes")
|
64
|
+
if object_collections.present?
|
65
|
+
# this object has a list of collection hashes, each of which we need to remove
|
66
|
+
object_collections.each do |hash|
|
67
|
+
Georeferencer.configuration.cache.delete("#{cache_key_base}/collection_query/#{hash}")
|
68
|
+
end
|
69
|
+
# by implication, the cached object should also be present; clear that too, along with any of its child keys
|
70
|
+
begin
|
71
|
+
Georeferencer.configuration.cache.delete_matched("#{object_cache_key}*")
|
72
|
+
rescue NotImplementedError
|
73
|
+
# rescue to removing the whole cache if delete_matched isn't supported
|
74
|
+
Georeferencer.configuration.cache.clear
|
75
|
+
end
|
76
|
+
|
77
|
+
else
|
78
|
+
# the object isn't in any collections; unfortunately we can't be sure whether this is because the object is old
|
79
|
+
# and uncached, or new and therefore needs to be in collections which currently exist for this class.
|
80
|
+
# Because of that, we'll aggressively remove caches for collections
|
81
|
+
begin
|
82
|
+
Georeferencer.configuration.cache.delete_matched("#{cache_key_base}/collection_query*")
|
83
|
+
rescue NotImplementedError
|
84
|
+
Georeferencer.configuration.cache.clear # rescue to cache.clear for caching methods where delete_matched isn't supported
|
85
|
+
end
|
86
|
+
end
|
87
|
+
# Always remove the object's cache. There's no risk of doing this for nonexistent things.
|
88
|
+
Georeferencer.configuration.cache.delete(object_cache_key)
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
class Image
|
3
|
+
include Georeferencer::Base
|
4
|
+
self.preload_resources = true
|
5
|
+
|
6
|
+
collection_path "display"
|
7
|
+
resource_path "maps/:id"
|
8
|
+
|
9
|
+
default_scope -> {
|
10
|
+
where(format: 'json')
|
11
|
+
}
|
12
|
+
|
13
|
+
scope :unreferenced, -> {
|
14
|
+
where(state: 'waiting')
|
15
|
+
}
|
16
|
+
|
17
|
+
def centroid
|
18
|
+
# Data from the collection endpoint doesn't include the bounding box, so we need to check we have the full data,
|
19
|
+
# or reload (which hits the resource endpoint) if not
|
20
|
+
if respond_to?(:bbox)
|
21
|
+
(wlng, slat, elng, nlat) = bbox
|
22
|
+
else
|
23
|
+
(wlng, slat, elng, nlat) = reload.bbox
|
24
|
+
end
|
25
|
+
{lat: (slat+nlat)/2, lng: (wlng+elng)/2}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Georeferencer
|
2
|
+
class Progress
|
3
|
+
include Georeferencer::Base
|
4
|
+
|
5
|
+
collection_path "progress"
|
6
|
+
resource_path "progress?collection=:id"
|
7
|
+
|
8
|
+
default_scope -> {
|
9
|
+
where(format: 'json')
|
10
|
+
}
|
11
|
+
|
12
|
+
def self.all
|
13
|
+
raise NoMethodError, "Use #find(project_name)"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: georeferencer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ed Jones
|
8
|
+
- Paul Hendrick
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-03-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.16'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.16'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: her
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: faraday_middleware
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: require_all
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: oj
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: activesupport
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
description:
|
113
|
+
email:
|
114
|
+
- ed@error.agency
|
115
|
+
- paul@error.agency
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- ".ruby-gemset"
|
122
|
+
- ".ruby-version"
|
123
|
+
- Gemfile
|
124
|
+
- Gemfile.lock
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- bin/console
|
129
|
+
- bin/setup
|
130
|
+
- georeferencer.gemspec
|
131
|
+
- lib/georeferencer.rb
|
132
|
+
- lib/georeferencer/engine.rb
|
133
|
+
- lib/georeferencer/middleware/headers.rb
|
134
|
+
- lib/georeferencer/middleware/parser.rb
|
135
|
+
- lib/georeferencer/mixins/base.rb
|
136
|
+
- lib/georeferencer/mixins/collection_cache.rb
|
137
|
+
- lib/georeferencer/mixins/collection_iterator.rb
|
138
|
+
- lib/georeferencer/mixins/object_cache.rb
|
139
|
+
- lib/georeferencer/models/contributor.rb
|
140
|
+
- lib/georeferencer/models/image.rb
|
141
|
+
- lib/georeferencer/models/progress.rb
|
142
|
+
- lib/georeferencer/version.rb
|
143
|
+
homepage: https://github.com/layersoflondon/georeferencer-ruby
|
144
|
+
licenses:
|
145
|
+
- MIT
|
146
|
+
metadata: {}
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
requirements: []
|
162
|
+
rubyforge_project:
|
163
|
+
rubygems_version: 2.7.8
|
164
|
+
signing_key:
|
165
|
+
specification_version: 4
|
166
|
+
summary: A Ruby client for Georeferencer
|
167
|
+
test_files: []
|