scb 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 +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +131 -0
- data/Rakefile +15 -0
- data/lib/scb.rb +28 -0
- data/lib/scb/api.rb +77 -0
- data/lib/scb/api/config.rb +32 -0
- data/lib/scb/db.rb +55 -0
- data/lib/scb/db/level.rb +41 -0
- data/lib/scb/db/table.rb +105 -0
- data/lib/scb/db/variable.rb +41 -0
- data/lib/scb/http.rb +53 -0
- data/lib/scb/version.rb +5 -0
- data/scb.gemspec +28 -0
- data/spec/fixtures/sv.json +6 -0
- data/spec/fixtures/sv/ssd.json +107 -0
- data/spec/fixtures/sv/ssd/BO.json +57 -0
- data/spec/fixtures/sv/ssd/BO/BO0102.json +47 -0
- data/spec/fixtures/sv/ssd/BO/BO0102/LagenhetOmbAkBpAtAr.json +148 -0
- data/spec/scb/api/config_spec.rb +50 -0
- data/spec/scb/api_spec.rb +101 -0
- data/spec/scb/db/level_spec.rb +39 -0
- data/spec/scb/db/table_spec.rb +102 -0
- data/spec/scb/db/variable_spec.rb +54 -0
- data/spec/scb/db_spec.rb +53 -0
- data/spec/scb/http_spec.rb +20 -0
- data/spec/scb/version_spec.rb +11 -0
- data/spec/scb_spec.rb +59 -0
- data/spec/spec_helper.rb +52 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a73a1fdb7a6724a94a2721049039fbf08d737fd
|
4
|
+
data.tar.gz: 6272df8f28e9a96cf2211a15a2c2e8f361c828ce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c540e8ea2c2539410f591505121f47d086d5d8d952ac56e72d05c0d6f310dc6dddfbf97a81e4588a1ed510ed3875d2f74eac5ac997e91cc8e25eca2212a53278
|
7
|
+
data.tar.gz: ee308c40c529f41eb3e696214d148ea30c4fd3ba89eac01f3e7a5e0df32208ff8f7122311fd9ab9de14846e9ed972efcec36052580a3ed474405a1383b317bd4
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Peter Hellberg
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# SCB
|
2
|
+
|
3
|
+
A small API client for the SCB API.
|
4
|
+
|
5
|
+
You probably want to read the [API\_beskrivning.pdf](http://www.scb.se/Grupp/OmSCB/Dokument/API_beskrivning.pdf) (in Swedish)
|
6
|
+
|
7
|
+
[](https://travis-ci.org/peterhellberg/scb)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'scb'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install scb
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
It is probably a good idea to take a look in `specs`
|
26
|
+
|
27
|
+
Configuration of the API client is done automatically, but it is also possible to manually compose the objects:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# Manual composition
|
31
|
+
config = SCB::API.config.new
|
32
|
+
api = SCB::API.new(config)
|
33
|
+
db = SCB::DB.new(api)
|
34
|
+
table = db.table('ProdbrEl')
|
35
|
+
|
36
|
+
# Short form
|
37
|
+
table = SCB.table('ProdbrEl')
|
38
|
+
|
39
|
+
# Liquid renewable energy in 2009
|
40
|
+
table.query Bransle: 925, Tid: 2009
|
41
|
+
```
|
42
|
+
|
43
|
+
### Configuration
|
44
|
+
|
45
|
+
Nothing needs to be configured out of the box, but you can change the
|
46
|
+
`api_host`, `api_name`, `api_version`, `language`, `database`,
|
47
|
+
`http_client` and `json_parser` settings like this:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# English config
|
51
|
+
config = SCB::API::Config.new do |c|
|
52
|
+
c.language = 'en'
|
53
|
+
end
|
54
|
+
|
55
|
+
# You can also pass a block straight to SCB.api
|
56
|
+
SCB.api { |c| c.api_host = 'scb.test' }
|
57
|
+
```
|
58
|
+
|
59
|
+
### Database
|
60
|
+
|
61
|
+
The database is divided into levels/sub-levels and tables.
|
62
|
+
|
63
|
+
The default language is 'sv' but there is also some data unde 'en'
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
db = SCB.db
|
67
|
+
|
68
|
+
# The names of All the top levels
|
69
|
+
db.levels.map(&:name)
|
70
|
+
|
71
|
+
# English levels under
|
72
|
+
db.level(BO0303')
|
73
|
+
|
74
|
+
# The English title of LonArb07Privat
|
75
|
+
SCB.db.en.table('LonArb07Privat').title
|
76
|
+
```
|
77
|
+
|
78
|
+
### Level
|
79
|
+
|
80
|
+
The database levels can contain sub-levels or tables. You are probably
|
81
|
+
more interested in the actual tables and their data.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# All the levels below BO
|
85
|
+
SCB.level('BO').levels
|
86
|
+
|
87
|
+
# All the tables below HE0110A
|
88
|
+
SCB.level('HE0110A').tables
|
89
|
+
```
|
90
|
+
|
91
|
+
### Table
|
92
|
+
|
93
|
+
This is probably where you want to spend most of your time.
|
94
|
+
|
95
|
+
You can ask the table for possible variables in order to construct your query. I’ve implemented a simplified query format along the lines: `Key: value` where value is automatically turned into an Array if you only want a single value.
|
96
|
+
|
97
|
+
*Note:* Each value is also turned into a string.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
# Database table containing data on electricity production
|
101
|
+
table = SCB.table('EltillfM')
|
102
|
+
|
103
|
+
# URI to the API endpoint for the table
|
104
|
+
table.uri
|
105
|
+
|
106
|
+
# The variable codes for the table
|
107
|
+
table.variables.map(&:code)
|
108
|
+
|
109
|
+
# Query: Wind production in January and February of 2013
|
110
|
+
table.query Prodslag: "Vind", Tid: ["2013M01", "2013M02"]
|
111
|
+
|
112
|
+
# Usage of the Internet
|
113
|
+
table = SCB.table('LE0108T05')
|
114
|
+
|
115
|
+
table.query Tid: 2012, Dem: "25-34"
|
116
|
+
|
117
|
+
# You can also get the result as a png
|
118
|
+
filename = '/tmp/internet_usage_2011.png'
|
119
|
+
query = { AnvOmr: 80, Tid: 2011, ContentsCode: "LE0108A2" }
|
120
|
+
|
121
|
+
table.write_png_query(filename, query)
|
122
|
+
```
|
123
|
+
*Note:* `write_png_query` will not overwrite existing files.
|
124
|
+
|
125
|
+
## Contributing
|
126
|
+
|
127
|
+
1. Fork it
|
128
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
129
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
130
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
131
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "rake/testtask"
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
Rake::TestTask.new(:spec) do |t|
|
9
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Console"
|
13
|
+
task :console do
|
14
|
+
exec 'pry -r./lib/scb'
|
15
|
+
end
|
data/lib/scb.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "scb/api"
|
4
|
+
require "scb/db"
|
5
|
+
require "scb/http"
|
6
|
+
require "scb/version"
|
7
|
+
|
8
|
+
module SCB
|
9
|
+
class << self
|
10
|
+
def api(config = nil)
|
11
|
+
API.new(config).tap do |a|
|
12
|
+
yield(a.config) if block_given?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def db(api = nil)
|
17
|
+
@db ||= DB.new(api)
|
18
|
+
end
|
19
|
+
|
20
|
+
def level(name, text = nil, api = nil)
|
21
|
+
DB::Level.new(name, text, api = nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
def table(name, api = nil)
|
25
|
+
DB::Table.new(name, api)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/scb/api.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require_relative "api/config"
|
6
|
+
|
7
|
+
module SCB
|
8
|
+
class API
|
9
|
+
attr_accessor :config
|
10
|
+
|
11
|
+
def initialize(config = nil)
|
12
|
+
@config = config || API::Config.new
|
13
|
+
|
14
|
+
yield(@config) if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(path = nil)
|
18
|
+
response = http_get(path)
|
19
|
+
|
20
|
+
if response && response.body
|
21
|
+
response.body.force_encoding('UTF-8')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_and_parse(path = nil)
|
26
|
+
load_json get(path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def post(path, query)
|
30
|
+
response = http_post path, dump_json(query)
|
31
|
+
response_body_without_utf8_bom(query, response)
|
32
|
+
end
|
33
|
+
|
34
|
+
def post_and_parse(path, query)
|
35
|
+
query.merge!({ response: { format: "json" }})
|
36
|
+
load_json post(path, query)
|
37
|
+
end
|
38
|
+
|
39
|
+
def base_url
|
40
|
+
config.base_url
|
41
|
+
end
|
42
|
+
|
43
|
+
def uri(endpoint = nil)
|
44
|
+
URI.parse("#{base_url}/#{endpoint}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_json(doc)
|
48
|
+
config.json_parser.load(doc)
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump_json(obj)
|
52
|
+
config.json_parser.dump(obj)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def response_body_without_utf8_bom(query, response)
|
58
|
+
if query[:response] && query[:response][:format] == "json"
|
59
|
+
# Force the response body to be UTF-8
|
60
|
+
body = response.body.force_encoding('UTF-8')
|
61
|
+
|
62
|
+
# Return the body, stripped of the BOM
|
63
|
+
body.sub!(/^\xEF\xBB\xBF/, '')
|
64
|
+
else
|
65
|
+
response.body
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def http_get(path)
|
70
|
+
config.http_client.get(uri(path))
|
71
|
+
end
|
72
|
+
|
73
|
+
def http_post(path, payload)
|
74
|
+
config.http_client.post(uri(path), payload)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module SCB
|
6
|
+
class API
|
7
|
+
class Config
|
8
|
+
attr_accessor :api_host, :api_name, :api_version,
|
9
|
+
:language, :database, :http_client, :json_parser
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@api_host = 'api.scb.se'
|
13
|
+
@api_name = 'OV0104'
|
14
|
+
@api_version = 'v1/doris'
|
15
|
+
@language = 'sv'
|
16
|
+
@database = 'ssd'
|
17
|
+
@http_client = SCB::HTTP
|
18
|
+
@json_parser = JSON
|
19
|
+
|
20
|
+
yield self if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_url
|
24
|
+
"http://#{api_host}/#{api_name}/#{api_version}/#{language}/#{database}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.language(language)
|
28
|
+
new { |c| c.language = language }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/scb/db.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative "db/level"
|
4
|
+
require_relative "db/table"
|
5
|
+
require_relative "db/variable"
|
6
|
+
|
7
|
+
module SCB
|
8
|
+
class DB
|
9
|
+
attr_accessor :api
|
10
|
+
|
11
|
+
def initialize(api = nil)
|
12
|
+
@api = api || SCB.api
|
13
|
+
end
|
14
|
+
|
15
|
+
def levels(klass = Level)
|
16
|
+
@levels ||= data.map do |l|
|
17
|
+
klass.new(l["id"], l["text"], api)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def level(name, text = nil, klass = Level)
|
22
|
+
klass.new(name, text, api)
|
23
|
+
end
|
24
|
+
|
25
|
+
def table(name, klass = Table)
|
26
|
+
klass.new(name, api)
|
27
|
+
end
|
28
|
+
|
29
|
+
def uri
|
30
|
+
api.uri
|
31
|
+
end
|
32
|
+
|
33
|
+
def en
|
34
|
+
language('en')
|
35
|
+
end
|
36
|
+
|
37
|
+
def sv
|
38
|
+
language('sv')
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def data
|
44
|
+
api.get_and_parse
|
45
|
+
end
|
46
|
+
|
47
|
+
def language(language_code)
|
48
|
+
api.config.language = language_code
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
class InvalidQuery < RuntimeError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/scb/db/level.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative '../db'
|
4
|
+
|
5
|
+
module SCB
|
6
|
+
class DB
|
7
|
+
class Level
|
8
|
+
attr_reader :name, :text, :api
|
9
|
+
|
10
|
+
def initialize(name, text = nil, api = nil)
|
11
|
+
@name = name
|
12
|
+
@text = text
|
13
|
+
@api = api || SCB.api
|
14
|
+
end
|
15
|
+
|
16
|
+
def levels(klass = Level)
|
17
|
+
@levels ||= objects_for_type(klass, "l")
|
18
|
+
end
|
19
|
+
|
20
|
+
def tables(klass = Table)
|
21
|
+
@tables ||= objects_for_type(klass, "t")
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
name
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def objects_for_type(klass, type)
|
31
|
+
data.map { |d|
|
32
|
+
klass.new(d["id"], api) if d["type"] == type
|
33
|
+
}.compact
|
34
|
+
end
|
35
|
+
|
36
|
+
def data
|
37
|
+
@data ||= api.get_and_parse(name) || []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|