twfy 1.0.1 → 1.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 +17 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/History.txt +6 -0
- data/LICENSE.txt +35 -0
- data/README.md +99 -0
- data/Rakefile +7 -19
- data/lib/twfy/api.rb +47 -0
- data/lib/twfy/client.rb +84 -0
- data/lib/twfy/commands.rb +73 -0
- data/lib/twfy/constituency.rb +15 -0
- data/lib/twfy/data_element.rb +62 -0
- data/lib/twfy/geometry.rb +17 -0
- data/lib/twfy/mp.rb +39 -0
- data/lib/twfy/validation.rb +88 -0
- data/lib/twfy/version.rb +3 -0
- data/lib/twfy.rb +12 -175
- data/test/fixtures/vcr_cassettes/client_test.yml +2723 -0
- data/test/fixtures/vcr_cassettes/data_element_test.yml +240 -0
- data/test/{test_twfy.rb → lib/twfy/client_test.rb} +13 -15
- data/test/{test_twfy_chain.rb → lib/twfy/data_element_test.rb} +12 -16
- data/test/test_helper.rb +38 -0
- data/twfy.gemspec +29 -0
- metadata +156 -76
- data/Manifest.txt +0 -9
- data/README.txt +0 -108
- data/lib/data_element.rb +0 -101
- data/test/api_key +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e4a7122b6b66c6ef20ed5fd0291dfa1f76599fc
|
4
|
+
data.tar.gz: c199d960584b65f80b353e9ba5da4b60a8895abc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c81d7d14a1ce73b2c4f86f501a69afa9299513b1e3d62cd5e82263ed003c0d1c2fff7bfdd1c6313a283a4a0242d6cc37b6ee48fc9a3d5ba18b597d41c4994435
|
7
|
+
data.tar.gz: 1d1b0d34b3be41dfaccefd13e3b856d11fb5f34a6eeaee30797f26ebe332dffdcb529a7c540f40dbe8e7f3c557787cc30a600036ba3366cafdd749860548bfcc
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 1.1.0 / 2013-11-12
|
2
|
+
|
3
|
+
* Modernize source
|
4
|
+
* Support Ruby 1.9, 2.0
|
5
|
+
* Requires >= Ruby 1.9
|
6
|
+
|
1
7
|
== 1.0.1 / 2008-08-02
|
2
8
|
|
3
9
|
* In the near future the TWFY API will require an API Key for all calls. In preparation for this, this binding now requires an API Key. They are available at http://www.theyworkforyou.com/api/key
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
Copyright (c) 2006 - 2013 Bruce Williams, Martin Owen & Tom Hipkin
|
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.
|
23
|
+
|
24
|
+
Data is licensed separately:
|
25
|
+
|
26
|
+
The TheyWorkForYou license statement, from their website
|
27
|
+
(http://www.theyworkforyou.com/api/), is:
|
28
|
+
|
29
|
+
To use parliamentary material yourself (that's data returned from getDebates,
|
30
|
+
getWrans, and getWMS), you will need to get a Parliamentary Licence from
|
31
|
+
the Office of Public Sector Information. Our own data - lists of MPs, Lords,
|
32
|
+
constituencies and so on - is available under the Creative Commons
|
33
|
+
Attribution-ShareAlike license version 2.5.
|
34
|
+
|
35
|
+
Non-commercial use is free, please contact us for commercial use.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# They Work For You
|
2
|
+
|
3
|
+
A Ruby library to interface with the
|
4
|
+
[TheyWorkForYou](http://www.theyworkforyou.com) API.
|
5
|
+
|
6
|
+
[](https://travis-ci.org/bruce/twfy)
|
7
|
+
[](https://codeclimate.com/github/bruce/twfy)
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
The Ruby API closely mirrors that of TWFY, with the exception that the client
|
12
|
+
methods are in lowercase and don't include the `get` prefix.
|
13
|
+
|
14
|
+
Some examples:
|
15
|
+
|
16
|
+
* `getComments` -> `comments`
|
17
|
+
* `getMPs` -> `mps`
|
18
|
+
* `getMPInfo` -> `mp_info`
|
19
|
+
|
20
|
+
## Requirements
|
21
|
+
|
22
|
+
Ruby 1.9+
|
23
|
+
|
24
|
+
* multi_json
|
25
|
+
* paginator
|
26
|
+
|
27
|
+
## Examples
|
28
|
+
|
29
|
+
### Get a Client
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'twfy'
|
33
|
+
client = Twfy::Client.new("YOUR-API-KEY")
|
34
|
+
```
|
35
|
+
|
36
|
+
You can get an API key from http://www.theyworkforyou.com/api/key
|
37
|
+
|
38
|
+
### Call API methods directly on client
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
puts client.constituency(postcode: 'IP6 9PN').name
|
42
|
+
# => Central Suffolk & North Ipswich
|
43
|
+
|
44
|
+
mp = client.mp(postcode: 'IP6 9PN')
|
45
|
+
puts mp.full_name
|
46
|
+
# => Michael Lord
|
47
|
+
|
48
|
+
# Get a *lot* of info about this MP
|
49
|
+
info = client.mp_info(id: mp.person_id)
|
50
|
+
|
51
|
+
# Get a sorted list of all the parties in the House of Lords
|
52
|
+
client.lords.map(&:party).uniq.sort
|
53
|
+
# => ["Bishop", "Conservative", "Crossbench", "DUP", "Green", "Labour", "Liberal Democrat", "Other"]
|
54
|
+
|
55
|
+
# Get number of debates in the House of Commons mentioning 'Iraq'
|
56
|
+
number = client.debates(type: 'commons', search: 'Iraq').info['total_results']
|
57
|
+
```
|
58
|
+
|
59
|
+
### Daisy Chaining
|
60
|
+
|
61
|
+
A few methods on the client return non-OpenStruct instances that
|
62
|
+
support daisy chaining. Using these to access related data more
|
63
|
+
naturally (with caching).
|
64
|
+
|
65
|
+
Here are some examples
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# Get the MP for the last constituency (if you sort them alphabetically)
|
69
|
+
mp = client.constituencies.sort_by(&:name).last.mp
|
70
|
+
# get the geometry information for that constituency (coming from the MP)
|
71
|
+
geometry = mp.constituency.geometry
|
72
|
+
|
73
|
+
# An overkill example showing caching (no services are called here, since
|
74
|
+
# the results have already been cached from above)
|
75
|
+
mp = mp.constituency.mp.constituency.geometry.constituency.mp
|
76
|
+
|
77
|
+
# These return equivalent results (Note how much easier the first is)
|
78
|
+
info1 = mp.info # this is cached for subsequent calls
|
79
|
+
info2 = client.mp_info(id: mp.person_id)
|
80
|
+
|
81
|
+
# Get pages of debates mentioning 'medicine'
|
82
|
+
debates1 = mp.debates(search: 'medicine')
|
83
|
+
debates2 = mp.debates(search: 'medicine', page: 2)
|
84
|
+
```
|
85
|
+
|
86
|
+
See http://www.theyworkforyou.com/api/docs for API documentation.
|
87
|
+
|
88
|
+
## Support
|
89
|
+
|
90
|
+
Please submit issues to https://github.com/bruce/twfy/issues
|
91
|
+
|
92
|
+
Pull requests gratefully accepted.
|
93
|
+
|
94
|
+
## License
|
95
|
+
|
96
|
+
See LICENSE.txt.
|
97
|
+
|
98
|
+
Please note that data pulled from the API is licensed separately from
|
99
|
+
this library.
|
data/Rakefile
CHANGED
@@ -1,22 +1,10 @@
|
|
1
|
-
|
1
|
+
require "bundler/gem_tasks"
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
p.rubyforge_name = 'twfy'
|
9
|
-
p.summary = 'Ruby library to interface with the TheyWorkForYou(.com) API; an information source on Parliament'
|
10
|
-
p.description =<<EOD
|
11
|
-
Ruby library to interface with the TheyWorkForYou API. TheyWorkForYou.com is
|
12
|
-
"a non-partisan, volunteer-run website which aims to make it easy for people to keep
|
13
|
-
tabs on their elected and unelected representatives in Parliament."
|
14
|
-
EOD
|
15
|
-
p.url = "http://twfy.rubyforge.org"
|
16
|
-
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
17
|
-
p.extra_deps = ['json', 'paginator']
|
18
|
-
p.email = %q{bruce@codefluency.com}
|
19
|
-
p.author = ["Bruce Williams", "Martin Owen"]
|
3
|
+
require 'rake/testtask'
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.test_files = FileList['test/**/*_test.rb']
|
7
|
+
t.verbose = true
|
20
8
|
end
|
21
9
|
|
22
|
-
|
10
|
+
task default: :test
|
data/lib/twfy/api.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Twfy
|
2
|
+
|
3
|
+
module API
|
4
|
+
|
5
|
+
VERSION = '1.0.0'
|
6
|
+
|
7
|
+
VALIDATIONS = {
|
8
|
+
convertURL: {require: :url},
|
9
|
+
getConstituency: {require: :postcode},
|
10
|
+
getConstituencies: {allow: [:date, :search, :longitude, :latitude, :distance]},
|
11
|
+
getMP: {allow: [:postcode, :constituency, :id, :always_return]},
|
12
|
+
getMPInfo: {require: :id},
|
13
|
+
getMPs: {allow: [:date, :party, :search]},
|
14
|
+
getLord: {require: :id},
|
15
|
+
getLords: {allow: [:date, :party, :search]},
|
16
|
+
getMLAs: {allow: [:date, :party, :search]},
|
17
|
+
getMSPs: {allow: [:date, :party, :search]},
|
18
|
+
getGeometry: {allow: :name},
|
19
|
+
getCommittee: {require: :name, allow: :date},
|
20
|
+
getDebates: {
|
21
|
+
require: :type,
|
22
|
+
require_one_of: [:date, :person, :search, :gid],
|
23
|
+
allow_dependencies: {
|
24
|
+
search: [:order, :page, :num],
|
25
|
+
person: [:order, :page, :num]
|
26
|
+
}
|
27
|
+
},
|
28
|
+
getWrans: {
|
29
|
+
require_one_of: [:date, :person, :search, :gid],
|
30
|
+
allow_dependencies: {
|
31
|
+
search: [:order, :page, :num],
|
32
|
+
person: [:order, :page, :num]
|
33
|
+
}
|
34
|
+
},
|
35
|
+
getWMS: {
|
36
|
+
require_one_of: [:date, :person, :search, :gid],
|
37
|
+
allow_dependencies: {
|
38
|
+
search: [:order, :page, :num],
|
39
|
+
person: [:order, :page, :num]
|
40
|
+
}
|
41
|
+
},
|
42
|
+
getComments: {allow: [:date, :search, :user_id, :pid, :page, :num]}
|
43
|
+
}
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/twfy/client.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'logger'
|
3
|
+
require 'multi_json'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
module Twfy
|
8
|
+
|
9
|
+
class Client
|
10
|
+
include API
|
11
|
+
include Commands
|
12
|
+
|
13
|
+
class Error < ::StandardError; end
|
14
|
+
class APIError < ::StandardError; end
|
15
|
+
|
16
|
+
def initialize(api_key, log_to=$stderr)
|
17
|
+
@api_key = api_key
|
18
|
+
@logger = Logger.new(log_to)
|
19
|
+
end
|
20
|
+
|
21
|
+
def log(message, level=:info)
|
22
|
+
@logger.send(level, message) if $DEBUG
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def service(name, params = {}, target = OpenStruct, &block)
|
28
|
+
log "Calling service #{name}"
|
29
|
+
url = service_url(name, params)
|
30
|
+
result = MultiJson.load(url.read)
|
31
|
+
log result.inspect
|
32
|
+
unless result.kind_of?(Enumerable)
|
33
|
+
raise Error, "Could not handle result: #{result.inspect}"
|
34
|
+
end
|
35
|
+
if result.kind_of?(Hash) && result['error']
|
36
|
+
raise APIError, result['error'].to_s
|
37
|
+
else
|
38
|
+
structure result, block || target
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def service_url(name, params = {})
|
43
|
+
url = BASE + name.to_s
|
44
|
+
url.query = build_query(validate(params, API::VALIDATIONS[name]))
|
45
|
+
url
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate(params, against)
|
49
|
+
Validation.run(params, against)
|
50
|
+
params
|
51
|
+
end
|
52
|
+
|
53
|
+
def structure(value, target)
|
54
|
+
case value
|
55
|
+
when Array
|
56
|
+
value.map{|r| structure(r, target) }
|
57
|
+
when Hash
|
58
|
+
if target.kind_of?(Proc)
|
59
|
+
target.call(value)
|
60
|
+
elsif target == Hash
|
61
|
+
value
|
62
|
+
else
|
63
|
+
target.ancestors.include?(DataElement) ? target.new(self,value) : target.new(value)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_query(params)
|
71
|
+
params.merge(api_params).map { |set|
|
72
|
+
set.map { |i|
|
73
|
+
CGI.escape(i.to_s)
|
74
|
+
}.join('=')
|
75
|
+
}.join('&')
|
76
|
+
end
|
77
|
+
|
78
|
+
def api_params
|
79
|
+
@api_params ||= {key: @api_key, version: API::VERSION}
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Twfy
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
def convert_url(params = {})
|
5
|
+
service :convertURL, params do |value|
|
6
|
+
URI.parse(value['url'])
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def constituency(params = {})
|
11
|
+
service :getConstituency, params, Constituency
|
12
|
+
end
|
13
|
+
|
14
|
+
def constituencies(params = {})
|
15
|
+
service :getConstituencies, params, Constituency
|
16
|
+
end
|
17
|
+
|
18
|
+
def mp(params = {})
|
19
|
+
service :getMP, params, MP
|
20
|
+
end
|
21
|
+
|
22
|
+
def mp_info(params = {})
|
23
|
+
service :getMPInfo, params
|
24
|
+
end
|
25
|
+
|
26
|
+
def mps(params = {})
|
27
|
+
service :getMPs, params, MP
|
28
|
+
end
|
29
|
+
|
30
|
+
def lord(params = {})
|
31
|
+
service :getLord, params
|
32
|
+
end
|
33
|
+
|
34
|
+
def lords(params = {})
|
35
|
+
service :getLords, params
|
36
|
+
end
|
37
|
+
|
38
|
+
# Members of Legislative Assembly
|
39
|
+
def mlas(params = {})
|
40
|
+
service :getMLAs, params
|
41
|
+
end
|
42
|
+
|
43
|
+
# Member of Scottish parliament
|
44
|
+
def msps(params = {})
|
45
|
+
service :getMSPs, params
|
46
|
+
end
|
47
|
+
|
48
|
+
def geometry(params = {})
|
49
|
+
service :getGeometry, params, Geometry
|
50
|
+
end
|
51
|
+
|
52
|
+
def committee(params = {})
|
53
|
+
service :getCommittee, params
|
54
|
+
end
|
55
|
+
|
56
|
+
def debates(params = {})
|
57
|
+
service :getDebates, params
|
58
|
+
end
|
59
|
+
|
60
|
+
def wrans(params = {})
|
61
|
+
service :getWrans, params
|
62
|
+
end
|
63
|
+
|
64
|
+
def wms(params = {})
|
65
|
+
service :getWMS, params
|
66
|
+
end
|
67
|
+
|
68
|
+
def comments(params = {})
|
69
|
+
service :getComments, params
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Twfy
|
5
|
+
|
6
|
+
class DataElement
|
7
|
+
|
8
|
+
@@conversions = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def convert(*fields,&block)
|
13
|
+
fields.each do |field|
|
14
|
+
@@conversions[field] = block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def convert_to_date(*fields)
|
19
|
+
fields.each do |field|
|
20
|
+
convert field do |d|
|
21
|
+
Date.parse(d)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :client
|
29
|
+
def initialize(client, data={})
|
30
|
+
@client = client
|
31
|
+
update_attributes(data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_attributes(data = {})
|
35
|
+
data.each do |field,value|
|
36
|
+
instance_variable_set("@#{field}", convert(field, value))
|
37
|
+
unless self.respond_to?(field)
|
38
|
+
self.class.send(:define_method, field) do
|
39
|
+
instance_variable_get("@#{field}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def with(data = {})
|
46
|
+
update_attributes(data)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def convert(field, value)
|
51
|
+
if conversion = @@conversions[field.to_sym]
|
52
|
+
args = [value]
|
53
|
+
args.unshift self if conversion.arity == 2
|
54
|
+
conversion.call(*args)
|
55
|
+
else
|
56
|
+
value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/twfy/mp.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Twfy
|
2
|
+
|
3
|
+
class MP < DataElement
|
4
|
+
|
5
|
+
convert_to_date :entered_house, :left_house
|
6
|
+
|
7
|
+
convert :image do |value|
|
8
|
+
URI.parse("http://theyworkforyou.com#{value}")
|
9
|
+
end
|
10
|
+
|
11
|
+
convert :constituency do |source, value|
|
12
|
+
if value.is_a?(Constituency)
|
13
|
+
value
|
14
|
+
else
|
15
|
+
Constituency.new(source.client, name: value, mp: source)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def in_office?
|
20
|
+
@left_reason == 'still_in_office'
|
21
|
+
end
|
22
|
+
|
23
|
+
def info
|
24
|
+
@info ||= @client.mp_info(id: @person_id)
|
25
|
+
end
|
26
|
+
|
27
|
+
def debates(params={})
|
28
|
+
@debates ||= {}
|
29
|
+
@debates[params] ||= @client.debates(params.merge(person: @person_id, type: 'commons'))
|
30
|
+
end
|
31
|
+
|
32
|
+
def comments(params={})
|
33
|
+
@comments ||= {}
|
34
|
+
@comments[params] ||= @client.comments(params.merge(pid: @person_id))
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Twfy
|
2
|
+
|
3
|
+
class Validation
|
4
|
+
|
5
|
+
class ServiceArgumentError < ::ArgumentError; end
|
6
|
+
|
7
|
+
def self.run(params = {}, against = {})
|
8
|
+
new(params, against).check!
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(params = {}, against = {})
|
12
|
+
@params = params
|
13
|
+
@against = against
|
14
|
+
end
|
15
|
+
|
16
|
+
def check!
|
17
|
+
unless missing.empty?
|
18
|
+
raise ServiceArgumentError, "Missing required params #{missing.inspect}"
|
19
|
+
end
|
20
|
+
unless extra.empty?
|
21
|
+
raise ServiceArgumentError, "Unknown params #{extra.inspect}"
|
22
|
+
end
|
23
|
+
check_one_required!
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def required
|
29
|
+
@required ||= list(@against[:require])
|
30
|
+
end
|
31
|
+
|
32
|
+
def allowed
|
33
|
+
@allowed ||= allowed_with_dependencies
|
34
|
+
end
|
35
|
+
|
36
|
+
def one_required
|
37
|
+
@one_required ||= list(@against[:require_one_of])
|
38
|
+
end
|
39
|
+
|
40
|
+
def dependencies_allowed
|
41
|
+
@dependencies_allowed ||= @against[:allow_dependencies] || {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def allowed_with_dependencies
|
45
|
+
base = list(@against[:allow])
|
46
|
+
dependencies_allowed.each_with_object(base) do |(key, dependent_keys), memo|
|
47
|
+
if provided.include?(key)
|
48
|
+
memo.push(*list(dependent_keys))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def provided
|
54
|
+
@provided ||= @params.keys.map(&:to_sym)
|
55
|
+
end
|
56
|
+
|
57
|
+
def list(candidate)
|
58
|
+
Array(candidate).dup.compact
|
59
|
+
end
|
60
|
+
|
61
|
+
def missing
|
62
|
+
@missing ||= required - provided
|
63
|
+
end
|
64
|
+
|
65
|
+
def extra
|
66
|
+
@extra ||= provided - (required + allowed + one_required)
|
67
|
+
end
|
68
|
+
|
69
|
+
def check_one_required!
|
70
|
+
count = one_required_count
|
71
|
+
if count
|
72
|
+
if count < 1
|
73
|
+
raise ServiceArgumentError, "Need exactly one of #{one_required.inspect}"
|
74
|
+
elsif count > 1
|
75
|
+
raise ServiceArgumentError, "Only one of #{one_required.inspect} allowed"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def one_required_count
|
81
|
+
if one_required.any?
|
82
|
+
provided.select { |item| one_required.include?(item) }.size
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/twfy/version.rb
ADDED