afasgem 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 +11 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +230 -0
- data/Rakefile +6 -0
- data/afasgem.gemspec +32 -0
- data/bin/connector_format.rb +177 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/afasgem.rb +46 -0
- data/lib/afasgem/configuration.rb +24 -0
- data/lib/afasgem/getconnector.rb +279 -0
- data/lib/afasgem/operators.rb +17 -0
- data/lib/afasgem/updateconnector.rb +91 -0
- data/lib/afasgem/version.rb +3 -0
- metadata +202 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c5bf46bef866cc1a2121ae0a52298e6beba6d9dd
|
4
|
+
data.tar.gz: 056bf5b73c04c3c8f03060763e5ea10e21b791b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c14c4274605b912888249c0d08b0a8b3c35f60bdce9bfb012e9cfa2c81126807bab61822ee4f155e83bcaf7251bc4c1911528b6f0c664d54c214f4668087e30e
|
7
|
+
data.tar.gz: 72541628f918b44920f72e8613f171ecd1a0e456d83d1f25ff6240364a0980c91e29d341780ad350e1b1ecb4dc24ba92d6bad83aad1e907b56cf2abf92fe9be8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sprint ICT, Subhi Dweik
|
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,230 @@
|
|
1
|
+
# Afasgem
|
2
|
+
|
3
|
+
This very creatively named get wraps communication with AFAS get and updateconnectors
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'afasgem'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install afasgem
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### General config
|
24
|
+
|
25
|
+
This gem can be configured using the well known ruby configure block
|
26
|
+
|
27
|
+
```
|
28
|
+
# Start the config block
|
29
|
+
Afasgem.configuration do |config|
|
30
|
+
# The WSDL url of the AFAS getconnector
|
31
|
+
# Probable format: https://<Environment number>.afasonlineconnector.nl/ProfitServices/AppConnectorGet.asmx?WSDL
|
32
|
+
config.getconnector_url = 'getconnectorurl'
|
33
|
+
|
34
|
+
# The WSDL url of the AFAS updateconnector
|
35
|
+
# Probable format: https://<Environment number>.afasonlineconnector.nl/ProfitServices/AppConnectorUpdate.asmx?WSDL
|
36
|
+
config.updateconnector_url = 'updateconnectorurl'
|
37
|
+
|
38
|
+
# The WSDL url of the AFAS updateconnector
|
39
|
+
# Probable format: ?
|
40
|
+
config.dataconnector_url = 'dataconnectorurl'
|
41
|
+
|
42
|
+
# The token to use
|
43
|
+
config.token = 'token'
|
44
|
+
|
45
|
+
# The number of rows to fetch when not specified
|
46
|
+
config.default_results = 150
|
47
|
+
|
48
|
+
# Whether to log all requests to the console
|
49
|
+
config.debug = true
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
To start communicating with AFAS you need to construct a connector using the
|
54
|
+
`Afasgem.getconnector_factory` and `Afasgem.updateconnector_factory`. Both take
|
55
|
+
the connectorId (the name of the connector, for example `Profit_Debtor`) as an
|
56
|
+
argument
|
57
|
+
|
58
|
+
This will return a configured get or updateconnector instance that is ready to communicate.
|
59
|
+
|
60
|
+
### Getconnector
|
61
|
+
|
62
|
+
Create a getconnector using the factory after configuring afasgem
|
63
|
+
|
64
|
+
```
|
65
|
+
conn = Afasgem.getconnector_factory('Profit_Debtor')
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Fetching data
|
69
|
+
|
70
|
+
The easiest way to get data out of a connector is to simply call `get_data`.
|
71
|
+
This will return an array of results, each in a hash. This hash will have the
|
72
|
+
AFAS field names as keys.
|
73
|
+
|
74
|
+
```
|
75
|
+
conn.get_data # [{result 1}, {result 2}]
|
76
|
+
```
|
77
|
+
|
78
|
+
The data xml is available using `get_data_xml`. This is the xml that contains
|
79
|
+
the data itself. Not the full SOAP request
|
80
|
+
|
81
|
+
`get_result` will return the full response as a hash. This also is not the full
|
82
|
+
SOAP request but just the interesting part of the response
|
83
|
+
|
84
|
+
When using `get_result`, `get_data`, or `get_data_xml`, the response
|
85
|
+
is cached and new requests will only be done when something was changed using
|
86
|
+
the pagination handlers below.
|
87
|
+
|
88
|
+
Calling `execute` issues a new request, even if nothing was changed
|
89
|
+
|
90
|
+
To get all data at once, the `get_all_results` method is available. This will
|
91
|
+
fetch all rows in a connector. Sadly there is no way to tell how many records
|
92
|
+
there are in total before fetching them all.
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
#### Handling pagination
|
97
|
+
|
98
|
+
```
|
99
|
+
conn.take(n) # Configures the connector to fetch n records at a time
|
100
|
+
conn.skip(n) # Configures the connector to skip the first n records
|
101
|
+
conn.page(n) # Provides a simple way to get the nth page of results, 1 indexed
|
102
|
+
conn.next # Gets the next page of results
|
103
|
+
conn.previous # Gets the previous page of results
|
104
|
+
```
|
105
|
+
|
106
|
+
All of the above methods provide fluent interfaced, meaning they can be chained.
|
107
|
+
|
108
|
+
```
|
109
|
+
# Will fetch result 15-25 since we are fetching 10 results a page,
|
110
|
+
# skipping the first 5 and then going to page 2
|
111
|
+
conn.take(10).skip(5).next.get_data
|
112
|
+
```
|
113
|
+
|
114
|
+
#### Filtering
|
115
|
+
|
116
|
+
This gem also wraps the filter functionality of the AFAS api. When adding a filter it is added with an and respective to the filters already in place. To filter using an OR you have to explicitly call `add_or`
|
117
|
+
|
118
|
+
```
|
119
|
+
# Filter where Field == 'val'
|
120
|
+
conn.add_filter('Field', FilterOperators::EQUAL, 'val')
|
121
|
+
|
122
|
+
# Filter where Field == 'val' && Field2 == 'val2'
|
123
|
+
conn.add_filter('Field', FilterOperators::EQUAL, 'val')
|
124
|
+
.add_filter('Field2', FilterOperators::EQUAL, 'val2')
|
125
|
+
|
126
|
+
# Filter where Field == 'val' || Field2 == 'val2'
|
127
|
+
conn.add_filter('Field', FilterOperators::EQUAL, 'val')
|
128
|
+
.add_or
|
129
|
+
.add_filter('Field2', FilterOperators::EQUAL, 'val2')
|
130
|
+
|
131
|
+
# Filter where (Field == 'val' && Field2 == 'val2') || (Field3 == 'val3')
|
132
|
+
conn.add_filter('Field', FilterOperators::EQUAL, 'val')
|
133
|
+
.add_filter('Field2', FilterOperators::EQUAL, 'val2')
|
134
|
+
.add_or
|
135
|
+
.add_filter('Field3', FilterOperators::EQUAL, 'val3')
|
136
|
+
```
|
137
|
+
|
138
|
+
To clear the filters in place use `clear_filters`
|
139
|
+
|
140
|
+
Available operators:
|
141
|
+
```
|
142
|
+
EQUAL # Value is exactly equal
|
143
|
+
LARGER_OR_EQUAL # Value is larger than or equal
|
144
|
+
SMALLER_OR_EQUAL # Value is smaller than or equal
|
145
|
+
LARGER_THAN # Value is larger than
|
146
|
+
SMALLER_THAN # Value is smaller than
|
147
|
+
LIKE # Text contains value
|
148
|
+
NOT_EQUAL # Value is not equal
|
149
|
+
EMPTY # Field is null
|
150
|
+
NOT_EMPTY # Field is not null
|
151
|
+
STARTS_WITH # Text starts with
|
152
|
+
NOT_LIKE # Text does not contain
|
153
|
+
NOT_STARTS_WITH # Text does not start with
|
154
|
+
ENDS_WITH # Text ends with
|
155
|
+
NOT_ENDS_WITH # Text does not end with
|
156
|
+
```
|
157
|
+
|
158
|
+
## Updateconnector data
|
159
|
+
|
160
|
+
To view the fields an updateconnector accepts, there is `bin/connector_format`. This script takes a few params and then lists the fields the passed updateconnector would accept
|
161
|
+
|
162
|
+
```
|
163
|
+
Usage: connector_format [options]
|
164
|
+
-u, --username NAME AFAS username
|
165
|
+
-p, --password PASSWORD AFAS password
|
166
|
+
-c, --connector CONNECTOR Name of the UpdateConnector
|
167
|
+
-e, --environment ENVIRONMENT Name of the environment
|
168
|
+
-h, --help Show this message
|
169
|
+
```
|
170
|
+
|
171
|
+
## Updateconnector
|
172
|
+
|
173
|
+
To Actually write data to the AFAS api you can use the `updateconnector_factory`. This factory will return an `UpdateConnector` object that has the following methods:
|
174
|
+
```
|
175
|
+
# Create a connector for the FbItemArticle updateconnector
|
176
|
+
connector = Afasgem.updateconnector_factory('FbItemArticle')
|
177
|
+
connector.insert(hash) # Insert data
|
178
|
+
connector.update(hash) # Update existing data
|
179
|
+
connector.delete(hash) # Delete existing data
|
180
|
+
```
|
181
|
+
|
182
|
+
The methods all take a hash that represents the object. Keys in this hash are expected to be fieldnames, while their values are treated like the field's values.
|
183
|
+
|
184
|
+
```
|
185
|
+
hash = { A: 'b', C: 5 } # => <A>b</A><C>5</C>
|
186
|
+
```
|
187
|
+
|
188
|
+
The wrapping xml is inferred using the updateconnector name and some constrant data.
|
189
|
+
|
190
|
+
Some objects accept nested objects as well as the usual fields. Those should be stored in the Objects key of the passed hash.
|
191
|
+
|
192
|
+
```
|
193
|
+
# <A>b</A><C>5</C>
|
194
|
+
# <Objects>
|
195
|
+
# <X>
|
196
|
+
# <Element>
|
197
|
+
# <Fields action='someaction'>
|
198
|
+
# <D>1</D>
|
199
|
+
# <E>2</E>
|
200
|
+
# </Fields>
|
201
|
+
# </Element>
|
202
|
+
# </X>
|
203
|
+
# <Y>
|
204
|
+
# <Element>
|
205
|
+
# <Fields action='someaction'>
|
206
|
+
# <F>3</F>
|
207
|
+
# <G>4</G>
|
208
|
+
# </Fields>
|
209
|
+
# </Element>
|
210
|
+
# </Y>
|
211
|
+
# </Objects>
|
212
|
+
# etc...
|
213
|
+
hash = { A: 'b', C: 5, Objects: { X: { D: 1, E: 2}, Y: { F: 3, G: 4} }
|
214
|
+
```
|
215
|
+
|
216
|
+
## Development
|
217
|
+
|
218
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
219
|
+
|
220
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
221
|
+
|
222
|
+
## Contributing
|
223
|
+
|
224
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Bonemind/Afasgem.
|
225
|
+
|
226
|
+
|
227
|
+
## License
|
228
|
+
|
229
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
230
|
+
|
data/Rakefile
ADDED
data/afasgem.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'afasgem/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "afasgem"
|
8
|
+
spec.version = Afasgem::VERSION
|
9
|
+
spec.authors = ["Subhi Dweik"]
|
10
|
+
spec.email = ["subhime@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A gem that wraps basic afas api functionality}
|
13
|
+
spec.homepage = "https://github.com/Bonemind/Afasgem"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'savon', '>= 2.11.1'
|
22
|
+
spec.add_dependency 'httpclient'
|
23
|
+
spec.add_dependency 'rubyntlm', '~> 0.3.2'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency 'pry'
|
29
|
+
spec.add_development_dependency 'pry-nav'
|
30
|
+
spec.add_development_dependency 'pry-stack_explorer'
|
31
|
+
spec.add_development_dependency 'pry-doc'
|
32
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'pp'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# Parse xml to a hash
|
6
|
+
def from_xml(xml_io)
|
7
|
+
begin
|
8
|
+
result = Nokogiri::XML(xml_io)
|
9
|
+
return { result.root.name.to_sym => xml_node_to_hash(result.root)}
|
10
|
+
rescue Exception => e
|
11
|
+
puts e.backtrace
|
12
|
+
raise
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Parse each node to a hash
|
17
|
+
def xml_node_to_hash(node)
|
18
|
+
# If we are at the root of the document, start the hash
|
19
|
+
if node.element?
|
20
|
+
result_hash = {}
|
21
|
+
if node.attributes != {}
|
22
|
+
attributes = {}
|
23
|
+
node.attributes.keys.each do |key|
|
24
|
+
attributes[node.attributes[key].name.to_sym] = node.attributes[key].value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
if node.children.size > 0
|
28
|
+
node.children.each do |child|
|
29
|
+
result = xml_node_to_hash(child)
|
30
|
+
|
31
|
+
if child.name == "text"
|
32
|
+
unless child.next_sibling || child.previous_sibling
|
33
|
+
return result unless attributes
|
34
|
+
result_hash[child.name.to_sym] = result
|
35
|
+
end
|
36
|
+
elsif result_hash[child.name.to_sym]
|
37
|
+
|
38
|
+
if result_hash[child.name.to_sym].is_a?(Object::Array)
|
39
|
+
result_hash[child.name.to_sym] << result
|
40
|
+
else
|
41
|
+
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << result
|
42
|
+
end
|
43
|
+
else
|
44
|
+
result_hash[child.name.to_sym] = result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
if attributes
|
48
|
+
#add code to remove non-data attributes e.g. xml schema, namespace here
|
49
|
+
#if there is a collision then node content supersets attributes
|
50
|
+
result_hash = attributes.merge(result_hash)
|
51
|
+
end
|
52
|
+
return result_hash
|
53
|
+
else
|
54
|
+
return attributes
|
55
|
+
end
|
56
|
+
else
|
57
|
+
return node.content.to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# The dataconnector url, will probably not need to change
|
63
|
+
dataconnector_url = 'https://profitweb.afasonline.nl/profitservices/DataConnector.asmx?WSDL'
|
64
|
+
|
65
|
+
# The username to use
|
66
|
+
username = nil
|
67
|
+
|
68
|
+
# The password to use
|
69
|
+
password = nil
|
70
|
+
|
71
|
+
# The connector we want a description of
|
72
|
+
connector_name = nil
|
73
|
+
|
74
|
+
# The AFAS environment, probably in the format: 'X12345XX'
|
75
|
+
environment_id = nil
|
76
|
+
|
77
|
+
# Create an optionparser
|
78
|
+
OptionParser.new do |opts|
|
79
|
+
# Set username
|
80
|
+
opts.on('-u', '--username NAME', 'AFAS username') { |v| username = v }
|
81
|
+
|
82
|
+
# Set password
|
83
|
+
opts.on('-p', '--password PASSWORD', 'AFAS password') { |v| password = v }
|
84
|
+
|
85
|
+
# Set connector name
|
86
|
+
opts.on('-c', '--connector CONNECTOR', 'Name of the UpdateConnector') { |v| connector_name = v }
|
87
|
+
|
88
|
+
# Set environment
|
89
|
+
opts.on('-e', '--environment ENVIRONMENT', 'Name of the environment') { |v| environment_id = v }
|
90
|
+
|
91
|
+
# Display help
|
92
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
93
|
+
puts opts
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
# Parse
|
97
|
+
end.parse!
|
98
|
+
|
99
|
+
# All params are required, fail is one is missing
|
100
|
+
fail ArgumentError.new('Username is required') unless username
|
101
|
+
fail ArgumentError.new('Password is required') unless password
|
102
|
+
fail ArgumentError.new('Connector name is required') unless connector_name
|
103
|
+
fail ArgumentError.new('Environment name is required') unless environment_id
|
104
|
+
|
105
|
+
# Setup Savon with the credentials the user supplied
|
106
|
+
client = Savon.client(wsdl: dataconnector_url, basic_auth: [username, password])
|
107
|
+
resp = client.call(:execute, {
|
108
|
+
message: {
|
109
|
+
environmentId: environment_id,
|
110
|
+
userId: username,
|
111
|
+
password: password,
|
112
|
+
dataID: 'GetXmlSchema',
|
113
|
+
parametersXml: "<Parameters><UpdateConnectorId>#{connector_name}</UpdateConnectorId></Parameters>"
|
114
|
+
}
|
115
|
+
})
|
116
|
+
|
117
|
+
# Get response xml out of wrapper
|
118
|
+
xml = resp.hash[:envelope][:body][:execute_response][:execute_result]
|
119
|
+
|
120
|
+
|
121
|
+
# Get the schema xml out of the response
|
122
|
+
schemaxml = from_xml(xml)[:AfasDataConnector][:ConnectorData][:Schema]
|
123
|
+
|
124
|
+
# Parse it ignoring namespaces. This because we only need the data and will not construct responses from the data
|
125
|
+
schema = Nokogiri::XML(schemaxml).remove_namespaces!
|
126
|
+
|
127
|
+
# Xpath to get the fields array of the main object
|
128
|
+
main_object_xpath = '//*[@name="Fields" and not(ancestor::*[@name="Objects"])]'
|
129
|
+
|
130
|
+
# Xpath to get the nested objects
|
131
|
+
nested_objects_xpath = '//*[@name="Objects"]/complexType/sequence/*'
|
132
|
+
|
133
|
+
# Xpath to get the fields of the nested objects
|
134
|
+
nested_objects_fields_xpath = '*//*[@name="Fields"]/complexType/sequence'
|
135
|
+
|
136
|
+
|
137
|
+
# Array of properties of the main object, contains comment and xml element alternating
|
138
|
+
main = schema.xpath(main_object_xpath)[0].children.children.children
|
139
|
+
nested = schema.xpath(nested_objects_xpath)
|
140
|
+
|
141
|
+
# Prints the fields in a field array
|
142
|
+
def print_fields(field_array)
|
143
|
+
field_array.each do |el|
|
144
|
+
if el.is_a?(Nokogiri::XML::Comment)
|
145
|
+
puts '-' * 80
|
146
|
+
puts el
|
147
|
+
end
|
148
|
+
if el.is_a?(Nokogiri::XML::Element)
|
149
|
+
puts el.attributes['name'].value
|
150
|
+
puts 'Optional' if el.attributes['nillable']
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Output the main connector name
|
156
|
+
puts '*' * 8
|
157
|
+
puts connector_name
|
158
|
+
puts '*' * 80
|
159
|
+
|
160
|
+
# Output the fields of the main object
|
161
|
+
print_fields(main)
|
162
|
+
|
163
|
+
# Iterate over nested objects
|
164
|
+
nested.each do |el|
|
165
|
+
|
166
|
+
# PRint the name of the nested object
|
167
|
+
puts '=' * 80
|
168
|
+
puts el.attributes['name'].value
|
169
|
+
puts '=' * 80
|
170
|
+
|
171
|
+
# Get the fields for this object
|
172
|
+
fields = el.xpath(nested_objects_fields_xpath).children
|
173
|
+
|
174
|
+
# Print the fields for this object
|
175
|
+
print_fields(fields)
|
176
|
+
end
|
177
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "afasgem"
|
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
|
data/bin/setup
ADDED
data/lib/afasgem.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "afasgem/version"
|
2
|
+
require 'afasgem/configuration'
|
3
|
+
require 'afasgem/getconnector'
|
4
|
+
require 'afasgem/updateconnector'
|
5
|
+
require 'afasgem/operators'
|
6
|
+
require 'savon'
|
7
|
+
require 'nokogiri'
|
8
|
+
|
9
|
+
module Afasgem
|
10
|
+
# Make the gem configurable
|
11
|
+
# See afasgem/configuration.rb for code origin
|
12
|
+
extend Configuration
|
13
|
+
|
14
|
+
# The WSDL url of the getconnector
|
15
|
+
define_setting :getconnector_url
|
16
|
+
|
17
|
+
# The WSDL url of the updateconnector
|
18
|
+
define_setting :updateconnector_url
|
19
|
+
|
20
|
+
# The WSDL url of the dataconnector
|
21
|
+
define_setting :dataconnector_url
|
22
|
+
# The token, this is only the actual token, not the whole xml thing
|
23
|
+
define_setting :token
|
24
|
+
|
25
|
+
|
26
|
+
# The number of results to request by default
|
27
|
+
define_setting :default_results, 100
|
28
|
+
|
29
|
+
# Defines whether the requests and responses should be printed
|
30
|
+
define_setting :debug, false
|
31
|
+
|
32
|
+
# Constructs a getconnect for the passed connector name
|
33
|
+
def self.getconnector_factory(name)
|
34
|
+
return GetConnector.new(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Constructs an updateconnector for the passed connector name
|
38
|
+
def self.updateconnector_factory(name)
|
39
|
+
return UpdateConnector.new(name)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Builds the token xml from the configured token
|
43
|
+
def self.get_token
|
44
|
+
return "<token><version>1</version><data>#{Afasgem::token}</data></token>"
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Provides module configuration
|
2
|
+
# # Source: https://viget.com/extend/easy-gem-configuration-variables-with-defaults
|
3
|
+
module Configuration
|
4
|
+
def configuration
|
5
|
+
yield self
|
6
|
+
end
|
7
|
+
|
8
|
+
def define_setting(name, default = nil)
|
9
|
+
class_variable_set("@@#{name}", default)
|
10
|
+
define_class_method "#{name}=" do |value|
|
11
|
+
class_variable_set("@@#{name}", value)
|
12
|
+
end
|
13
|
+
define_class_method name do
|
14
|
+
class_variable_get("@@#{name}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def define_class_method(name, &block)
|
20
|
+
(class << self; self; end).instance_eval do
|
21
|
+
define_method name, &block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
# Implements communication with getconnectors
|
2
|
+
class GetConnector
|
3
|
+
|
4
|
+
# Constructor, takes the name of the connector
|
5
|
+
def initialize(name)
|
6
|
+
@connectorname = name
|
7
|
+
@filters = []
|
8
|
+
if Afasgem::debug
|
9
|
+
# Build a debug client if the debug flag is set
|
10
|
+
@client = Savon.client(
|
11
|
+
wsdl: Afasgem::getconnector_url,
|
12
|
+
log: true,
|
13
|
+
log_level: :debug,
|
14
|
+
pretty_print_xml: true
|
15
|
+
)
|
16
|
+
else
|
17
|
+
# Build a normal client otherwise
|
18
|
+
@client = Savon.client(wsdl: Afasgem::getconnector_url)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set the number of results we want to have
|
23
|
+
# Provides a fluent interface
|
24
|
+
def take(count)
|
25
|
+
fail ArgumentError.new("Count cannot be lower than 1, #{count} given") unless count > 0
|
26
|
+
@result = nil
|
27
|
+
@resultcount = count
|
28
|
+
return self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set the number of results we want to skip
|
32
|
+
# Provides a fluent interface
|
33
|
+
def skip(count)
|
34
|
+
fail ArgumentError.new("Count cannot be lower than 1, #{count} given") unless count > 0
|
35
|
+
@result = nil
|
36
|
+
@skip = count
|
37
|
+
return self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set the page we want to fetch
|
41
|
+
# 1 indexed (i.e. page 1 will fetch result 0 to x)
|
42
|
+
# Provides a fluent interface
|
43
|
+
def page(number)
|
44
|
+
fail ArgumentError.new("Page number cannot be lower than 1, #{number} given") unless number > 0
|
45
|
+
@result = nil
|
46
|
+
@skip = (number - 1) * get_resultcount
|
47
|
+
return self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Fetch the next page
|
51
|
+
# Provides a fluent interface
|
52
|
+
def next
|
53
|
+
@skip = (@skip || 0) + get_resultcount
|
54
|
+
@result = nil
|
55
|
+
return self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Fetch the previous page
|
59
|
+
# Provides a fluent interface
|
60
|
+
def previous
|
61
|
+
@result = nil
|
62
|
+
@skip = (@skip || 0) - get_resultcount
|
63
|
+
@skip = [0, @skip].max
|
64
|
+
return self
|
65
|
+
end
|
66
|
+
|
67
|
+
# execute the request
|
68
|
+
# Provides a fluent interface
|
69
|
+
def execute
|
70
|
+
result = execute_request(get_resultcount, @skip)
|
71
|
+
|
72
|
+
@data_xml = result[0]
|
73
|
+
@result = result[1]
|
74
|
+
return self
|
75
|
+
end
|
76
|
+
|
77
|
+
# Fetches all results
|
78
|
+
# Data is not cached
|
79
|
+
def get_all_results
|
80
|
+
result_array = []
|
81
|
+
skip = 0
|
82
|
+
take = 1000
|
83
|
+
loop do
|
84
|
+
current_result = get_data_from_result(execute_request(take, skip)[1])
|
85
|
+
result_array.concat(current_result)
|
86
|
+
skip = skip + take
|
87
|
+
break if current_result.size != take
|
88
|
+
end
|
89
|
+
return result_array
|
90
|
+
end
|
91
|
+
|
92
|
+
# Adds a filter to the current filter list
|
93
|
+
# Provides a fluent interface
|
94
|
+
def add_filter(field, operator, value = nil)
|
95
|
+
if @filters.size == 0
|
96
|
+
@filters.push([])
|
97
|
+
end
|
98
|
+
|
99
|
+
# Only the EMPTY and NOT_EMPTY filters should accept a nil value
|
100
|
+
if !value
|
101
|
+
unless operator == FilterOperators::EMPTY || operator == FilterOperators::NOT_EMPTY
|
102
|
+
raise ArgumentError.new('Value can only be empty when using FilterOperator::EMPTY or FilterOperator::NOT_EMPTY')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@filters.last.push({field: field, operator: operator, value: value})
|
106
|
+
return self
|
107
|
+
end
|
108
|
+
|
109
|
+
# Adds an OR to the current filter list
|
110
|
+
# Provides a fluent interface
|
111
|
+
def add_or
|
112
|
+
@filters.push([]) if @filters.last && @filters.last.size > 0
|
113
|
+
return self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Clears the filters in place
|
117
|
+
# Provides a fluent interface
|
118
|
+
def clear_filters
|
119
|
+
@filters = []
|
120
|
+
return self
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the result as a hash
|
124
|
+
# This includes the type definition
|
125
|
+
def get_result
|
126
|
+
execute unless @result
|
127
|
+
return @result
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the actual data as a hash
|
131
|
+
def get_data
|
132
|
+
execute unless @result
|
133
|
+
return get_data_from_result(@result)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns the raw xml
|
137
|
+
def get_data_xml
|
138
|
+
execute unless @data_xml
|
139
|
+
return @data_xml
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Actually fires the request
|
145
|
+
def execute_request(take, skip = nil)
|
146
|
+
message = {
|
147
|
+
token: Afasgem.get_token,
|
148
|
+
connectorId: @connectorname,
|
149
|
+
take: take
|
150
|
+
}
|
151
|
+
|
152
|
+
message[:skip] = skip if skip
|
153
|
+
filter_string = get_filter_string
|
154
|
+
message[:filtersXml] = filter_string if filter_string
|
155
|
+
|
156
|
+
resp = @client.call(:get_data, message: message)
|
157
|
+
xml_string = resp.hash[:envelope][:body][:get_data_response][:get_data_result]
|
158
|
+
return [xml_string, from_xml(xml_string)]
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns the filter xml in string format
|
162
|
+
def get_filter_string
|
163
|
+
return nil if @filters.size == 0
|
164
|
+
filters = []
|
165
|
+
|
166
|
+
# Loop over each filtergroup
|
167
|
+
# All conditions in a filtergroup are combined using AND
|
168
|
+
# All filtergroups are combined using OR
|
169
|
+
@filters.each_with_index do |filter, index|
|
170
|
+
fields = []
|
171
|
+
|
172
|
+
# Loop over all conditions in a filter group
|
173
|
+
filter.each do |condition|
|
174
|
+
field = condition[:field]
|
175
|
+
operator = condition[:operator]
|
176
|
+
value = condition[:value]
|
177
|
+
|
178
|
+
# Some filters operate on strings and need wildcards
|
179
|
+
# Transform value if needed
|
180
|
+
case operator
|
181
|
+
when FilterOperators::LIKE
|
182
|
+
value = "%#{value}%"
|
183
|
+
when FilterOperators::STARTS_WITH
|
184
|
+
value = "#{value}%"
|
185
|
+
when FilterOperators::NOT_LIKE
|
186
|
+
value = "%#{value}%"
|
187
|
+
when FilterOperators::NOT_STARTS_WITH
|
188
|
+
value = "#{value}%"
|
189
|
+
when FilterOperators::ENDS_WITH
|
190
|
+
value = "%#{value}"
|
191
|
+
when FilterOperators::NOT_ENDS_WITH
|
192
|
+
value = "%#{value}"
|
193
|
+
when FilterOperators::EMPTY
|
194
|
+
# EMPTY and NOT_EMPTY operators require the filter to be in a different format
|
195
|
+
# This because they take no value
|
196
|
+
fields.push("<Field FieldId=\"#{field}\" OperatorType=\"#{operator}\" />")
|
197
|
+
next
|
198
|
+
when FilterOperators::NOT_EMPTY
|
199
|
+
fields.push("<Field FieldId=\"#{field}\" OperatorType=\"#{operator}\" />")
|
200
|
+
next
|
201
|
+
end
|
202
|
+
|
203
|
+
# Add this filterstring to filters
|
204
|
+
fields.push("<Field FieldId=\"#{field}\" OperatorType=\"#{operator}\">#{value}</Field>")
|
205
|
+
end
|
206
|
+
|
207
|
+
# Make sure all filtergroups are OR'ed and add them
|
208
|
+
filters.push("<Filter FilterId=\"Filter #{index}\">#{fields.join}</Filter>")
|
209
|
+
end
|
210
|
+
|
211
|
+
# Return the whole filterstring
|
212
|
+
return "<Filters>#{filters.join}</Filters>"
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns the number of results we want to fetch
|
216
|
+
def get_resultcount
|
217
|
+
return @resultcount || Afasgem.default_results
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the actual rows from a parsed response hash
|
221
|
+
def get_data_from_result(result)
|
222
|
+
return result[:AfasGetConnector][@connectorname.to_sym] || []
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
# Source of code below: https://gist.github.com/huy/819999
|
227
|
+
def from_xml(xml_io)
|
228
|
+
begin
|
229
|
+
result = Nokogiri::XML(xml_io)
|
230
|
+
return { result.root.name.to_sym => xml_node_to_hash(result.root)}
|
231
|
+
rescue Exception => e
|
232
|
+
# raise your custom exception here
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def xml_node_to_hash(node)
|
237
|
+
# If we are at the root of the document, start the hash
|
238
|
+
if node.element?
|
239
|
+
result_hash = {}
|
240
|
+
if node.attributes != {}
|
241
|
+
attributes = {}
|
242
|
+
node.attributes.keys.each do |key|
|
243
|
+
attributes[node.attributes[key].name.to_sym] = node.attributes[key].value
|
244
|
+
end
|
245
|
+
end
|
246
|
+
if node.children.size > 0
|
247
|
+
node.children.each do |child|
|
248
|
+
result = xml_node_to_hash(child)
|
249
|
+
|
250
|
+
if child.name == "text"
|
251
|
+
unless child.next_sibling || child.previous_sibling
|
252
|
+
return result unless attributes
|
253
|
+
result_hash[child.name.to_sym] = result
|
254
|
+
end
|
255
|
+
elsif result_hash[child.name.to_sym]
|
256
|
+
|
257
|
+
if result_hash[child.name.to_sym].is_a?(Object::Array)
|
258
|
+
result_hash[child.name.to_sym] << result
|
259
|
+
else
|
260
|
+
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << result
|
261
|
+
end
|
262
|
+
else
|
263
|
+
result_hash[child.name.to_sym] = result
|
264
|
+
end
|
265
|
+
end
|
266
|
+
if attributes
|
267
|
+
#add code to remove non-data attributes e.g. xml schema, namespace here
|
268
|
+
#if there is a collision then node content supersets attributes
|
269
|
+
result_hash = attributes.merge(result_hash)
|
270
|
+
end
|
271
|
+
return result_hash
|
272
|
+
else
|
273
|
+
return attributes
|
274
|
+
end
|
275
|
+
else
|
276
|
+
return node.content.to_s
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This module maps constants to AFAS filter ints
|
2
|
+
module FilterOperators
|
3
|
+
EQUAL = 1
|
4
|
+
LARGER_OR_EQUAL = 2
|
5
|
+
SMALLER_OR_EQUAL = 3
|
6
|
+
LARGER_THAN = 4
|
7
|
+
SMALLER_THAN = 5
|
8
|
+
LIKE = 6
|
9
|
+
NOT_EQUAL = 7
|
10
|
+
EMPTY = 8
|
11
|
+
NOT_EMPTY = 9
|
12
|
+
STARTS_WITH = 10
|
13
|
+
NOT_LIKE = 11
|
14
|
+
NOT_STARTS_WITH = 12
|
15
|
+
ENDS_WITH = 13
|
16
|
+
NOT_ENDS_WITH = 14
|
17
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
class UpdateConnector
|
2
|
+
|
3
|
+
# Constructor, takes the connector name
|
4
|
+
def initialize(name)
|
5
|
+
@connectorname = name
|
6
|
+
if Afasgem::debug
|
7
|
+
# Build a debug client if the debug flag is set
|
8
|
+
@client = Savon.client(
|
9
|
+
wsdl: Afasgem::updateconnector_url,
|
10
|
+
log: true,
|
11
|
+
log_level: :debug,
|
12
|
+
pretty_print_xml: true
|
13
|
+
)
|
14
|
+
else
|
15
|
+
# Build a normal client otherwise
|
16
|
+
@client = Savon.client(wsdl: Afasgem::updateconnector_url)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Method to return the savon client for this constructor
|
21
|
+
def client
|
22
|
+
return @client
|
23
|
+
end
|
24
|
+
|
25
|
+
# Executes an insert action using the passed object hash
|
26
|
+
def insert(objecthash)
|
27
|
+
xml = build_xml(objecthash, 'insert')
|
28
|
+
return execute(xml)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Executes an update action using the passed object hash
|
32
|
+
def update(objecthash)
|
33
|
+
xml = build_xml(objecthash, 'update')
|
34
|
+
return execute(xml)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Executes a delete action using the passed object hash
|
38
|
+
def delete(objecthash)
|
39
|
+
xml = build_xml(objecthash, 'delete')
|
40
|
+
return execute(xml)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Builds the inner xml to send to the afas api from the passed hash and action
|
46
|
+
def build_xml(objecthash, action)
|
47
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
48
|
+
xml.send(@connectorname.to_sym, 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance") {
|
49
|
+
xml.Element {
|
50
|
+
xml.Fields(Action: action) {
|
51
|
+
objecthash.each do |k, v|
|
52
|
+
xml.send(k.to_sym, v) unless k.to_s == 'Objects'
|
53
|
+
build_nested_xml(xml, v, action) if k.to_s == 'Objects'
|
54
|
+
end
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
end
|
59
|
+
return builder.to_xml.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
# Builds the xml for nested objects
|
63
|
+
def build_nested_xml(xml, objects, action)
|
64
|
+
xml.Objects {
|
65
|
+
objects.each do |obj, values|
|
66
|
+
|
67
|
+
xml.send(obj) {
|
68
|
+
xml.Element {
|
69
|
+
xml.Fields(Action: action) {
|
70
|
+
values.each do |k, v|
|
71
|
+
xml.send(k, v)
|
72
|
+
end
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
# Actually calls the afas api
|
81
|
+
def execute(xml)
|
82
|
+
message = {
|
83
|
+
token: Afasgem.get_token,
|
84
|
+
connectorType: @connectorname,
|
85
|
+
connectorVersion: 1,
|
86
|
+
dataXml: xml
|
87
|
+
}
|
88
|
+
resp = @client.call(:execute, message: message)
|
89
|
+
return resp
|
90
|
+
end
|
91
|
+
end
|
metadata
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: afasgem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Subhi Dweik
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: savon
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.11.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.11.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httpclient
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubyntlm
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.3.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.3.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-nav
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-stack_explorer
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry-doc
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description:
|
154
|
+
email:
|
155
|
+
- subhime@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- ".rspec"
|
162
|
+
- ".travis.yml"
|
163
|
+
- Gemfile
|
164
|
+
- LICENSE.txt
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- afasgem.gemspec
|
168
|
+
- bin/connector_format.rb
|
169
|
+
- bin/console
|
170
|
+
- bin/setup
|
171
|
+
- lib/afasgem.rb
|
172
|
+
- lib/afasgem/configuration.rb
|
173
|
+
- lib/afasgem/getconnector.rb
|
174
|
+
- lib/afasgem/operators.rb
|
175
|
+
- lib/afasgem/updateconnector.rb
|
176
|
+
- lib/afasgem/version.rb
|
177
|
+
homepage: https://github.com/Bonemind/Afasgem
|
178
|
+
licenses:
|
179
|
+
- MIT
|
180
|
+
metadata: {}
|
181
|
+
post_install_message:
|
182
|
+
rdoc_options: []
|
183
|
+
require_paths:
|
184
|
+
- lib
|
185
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
requirements: []
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 2.4.8
|
198
|
+
signing_key:
|
199
|
+
specification_version: 4
|
200
|
+
summary: A gem that wraps basic afas api functionality
|
201
|
+
test_files: []
|
202
|
+
has_rdoc:
|