atomsphere 0.1.7 → 0.1.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bb21b9a66774a9fee3486b96ce9d8f52e7ed633013c828f391bc9cafa56c4d3
4
- data.tar.gz: 7f849cfd2473ada55b2cec071583d114658a8b403295dc9c9a26423d077f5351
3
+ metadata.gz: e78f1312bd07e2b8624c0aae53b83463bf877134d6c9b3d0253f2256528e3441
4
+ data.tar.gz: 9f34dccf99636cb840a89f48fd256f92944ad55f5e6eec7e3c1d1ad200c0c9d6
5
5
  SHA512:
6
- metadata.gz: 632193c167af5174b7c050714c9bb05c844ae863eab4a6330daba8c9a372603e2414e77ce0acd61fe41536ba1032398af536af1ae41963326af0bc95c9881824
7
- data.tar.gz: 3f4c067af23f0b447dd9692eff618a6107f901025e2ce253db119d744febe119729046d03296df660a02a5b429f0447fd719986362b6ce7b619e57f251f55ffa
6
+ metadata.gz: 571d407b997b509a116397fce8ee74d32819dab8890575cfa19b5eaff4c02c4a542fb41a3657fe1df0747a74934f429e5a0427d92ee8efba193dc2c31b01586a
7
+ data.tar.gz: 84f4c92a54014a100e2f33c4021167e085e1ca90291cb07c4d18896c5fe1423145b40013dbb4b303d07834c3b5d79c9277d2d2f34cb64f67f9ff78bb34da32d8
data/.gitignore CHANGED
@@ -3,3 +3,6 @@
3
3
  /.bundle
4
4
  /tmp
5
5
  Gemfile.lock
6
+ *.gem
7
+ doc/
8
+ .yardoc
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Boomi Atomsphere API client for Ruby
2
2
 
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Gem Version](https://badge.fury.io/rb/atomsphere.svg)](https://badge.fury.io/rb/atomsphere)
5
+ [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/atomsphere)
6
+
3
7
  Unofficial Ruby client for the Dell Boomi Atomsphere API. Implements the JSON flavour of Boomi's "RESTish" API.
4
8
 
5
9
  ## Status
@@ -40,35 +44,58 @@ Alternatively, environment variables may be used:
40
44
 
41
45
  ### Querying
42
46
 
47
+ Generate a query for all _"Processes"_ that start with _"Production"_ and
48
+ contain _"NetSuite"_ or _"Salesforce"_:
49
+
50
+ ```ruby
51
+ query = Atomsphere.query('Process') do
52
+ group :and do
53
+ name.like 'Production%'
54
+ group :or do
55
+ name.like '%NetSuite%'
56
+ name.like '%Salesforce%'
57
+ end
58
+ end
59
+ end
60
+ ```
61
+
62
+ Generate a query for all online Atoms:
63
+
64
+ ```ruby
65
+ query = Atomsphere.query('Atom') do
66
+ status.equals 'ONLINE'
67
+ type.equals 'CLOUD'
68
+ end
69
+ ```
70
+
71
+ Inspect the query filter:
72
+
73
+ ```ruby
74
+ query.to_hash
75
+ query.to_json
76
+ ```
77
+
78
+ Run the query:
79
+
43
80
  ```ruby
44
- # create a new query
45
- query = Atomsphere::Query.new
46
-
47
- # specify the object type to query
48
- query.object_type = 'Process'
49
-
50
- # filter for query names starting with 'Netsuite'
51
- query.filter = Atomsphere::Query::GroupingExpression.new(
52
- operator: :and,
53
- nested_expression: [
54
- Atomsphere::Query::SimpleExpression.new(
55
- operator: :equals,
56
- property: :name,
57
- argument: ['Netsuite%']
58
- )
59
- ]
60
- )
61
-
62
- # run the query (fetches first page)
63
81
  query.run
82
+ ```
83
+
84
+ See results from all pages that have been fetched:
64
85
 
65
- # see results from all pages that have been fetched
86
+ ```ruby
66
87
  query.results
88
+ ```
89
+
90
+ Fetch the next page (returns `false` if `last_page?` is `true`):
67
91
 
68
- # fetch the next page (returns `false` if `last_page?` is `true`)
92
+ ```ruby
69
93
  query.next_page
94
+ ```
95
+
96
+ Iterate over `next_page` until `last_page?` is `true` and see all results:
70
97
 
71
- # fetch and show all pages of results (warning: loops over `next_page`)
98
+ ```ruby
72
99
  query.all_results
73
100
  ```
74
101
 
data/atomsphere.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'atomsphere'
3
- s.version = '0.1.7'
3
+ s.version = '0.1.8'
4
4
  s.licenses = ['MIT']
5
5
  s.summary = "Unofficial Ruby client for the Dell Boomi Atomsphere API"
6
6
  s.authors = ["Warren Guy"]
data/lib/atomsphere.rb CHANGED
@@ -1,5 +1,6 @@
1
+ # @author Warren Guy
1
2
  module Atomsphere
2
- VERSION = '0.1.7'
3
+ VERSION = '0.1.8'
3
4
  ROOT = "#{File.expand_path(__dir__)}/atomsphere"
4
5
 
5
6
  %w(configuration query api action).each{ |m| require "#{ROOT}/#{m}" }
@@ -96,12 +96,24 @@ module Atomsphere
96
96
  'response code was nil'
97
97
  ) if response.code.nil?
98
98
 
99
- raise ApiError.new(
100
- request,
101
- response,
102
- e,
103
- "API responded with error #{response.code}: #{response.message}"
104
- ) if response.code >= 400
99
+ if response.code >= 400
100
+ begin
101
+ json = JSON.parse(response.response.body)
102
+ if json['@type'].downcase.eql?('error')
103
+ message = json['message']
104
+ end
105
+ rescue JSON::ParserError
106
+ ensure
107
+ message ||= "API responded with error #{response.code}: #{response.message}"
108
+ end
109
+
110
+ raise ApiError.new(
111
+ request,
112
+ response,
113
+ e,
114
+ message
115
+ )
116
+ end
105
117
  end
106
118
 
107
119
  response
@@ -1,15 +1,40 @@
1
1
  module Atomsphere
2
+
3
+ # @attr [String] object_type name of the object to query
4
+ # @attr [GroupingExpression] filter top level {GroupingExpression} for query
5
+ # @attr_reader [Integer] page the number of pages retrieved
6
+ # @attr_reader [Array<Api::Response>] result_pages array of api responses for each page retrieved
2
7
  class Query
3
8
  attr_accessor :object_type, :filter
4
9
  attr_reader :query_token, :result_pages, :page
5
10
 
6
- def initialize object_type=nil
7
- @object_type ||= object_type
8
- @page = 0
9
- @result_pages = []
10
- @filter = GroupingExpression.new
11
+ # accepts either a string of the name of the object to query, or a hash of options
12
+ # @param [String] params name of the object to query
13
+ # @param [Hash] params parameters to initialize query with
14
+ # @option params [String] :object_type name of the object to query
15
+ # @option params [GroupingExpression] :filter top level {GroupingExpression}
16
+ def initialize(params={})
17
+ case params
18
+ when String
19
+ params = {object_type: params}
20
+ end
21
+
22
+ params = {
23
+ object_type: nil,
24
+ page: 0,
25
+ result_pages: [],
26
+ filter: GroupingExpression.new
27
+ }.merge(Hash[params.select{|k,v| [:object_type, :filter].include? k}])
28
+
29
+ %w(object_type page result_pages filter).each do |v|
30
+ instance_variable_set :"@#{v}", params[v.to_sym]
31
+ end
32
+
33
+ self
11
34
  end
12
35
 
36
+ # run all `validate_*!` private methods to ensure validity of query parameters
37
+ # @return [true, false]
13
38
  def validate!
14
39
  private_methods.select{ |m| m =~ /^validate_[a-z0-9_]+\!$/ }.each{ |v| send(v) }
15
40
  filter.validate!
@@ -17,23 +42,33 @@ module Atomsphere
17
42
  true
18
43
  end
19
44
 
45
+ # @see #next_page
20
46
  def run
21
47
  next_page
22
48
  end
23
-
49
+
50
+ # returns rows from {#result_pages} that have been retrieved
51
+ # @return [Array<Hash>] Array of returned rows as hashes
24
52
  def results
25
53
  result_pages.map(&:to_hash).map{ |h| h['result'] }.map(&:compact).flatten(1)
26
54
  end
27
55
 
56
+ # runs {#next_page} to retrieve all {#result_pages} until {#last_page?} is `false`,
57
+ # and then returns all rows
58
+ # @return [Array<Hash>] Array of returned rows as hashes
28
59
  def all_results
29
60
  next_page until last_page?
30
61
  results
31
62
  end
32
63
 
64
+ # returns `true` when any pages have been retrieved the value of {#query_token} is `nil`
65
+ # @return [true, false]
33
66
  def last_page?
34
67
  !page.eql?(0) && query_token.nil?
35
68
  end
36
69
 
70
+ # retrieve the next page for the query
71
+ # @return [Api::Response, false] returns the response, or `false` if {#last_page?} is `true`
37
72
  def next_page
38
73
  return false if last_page?
39
74
 
@@ -52,12 +87,19 @@ module Atomsphere
52
87
  result_pages[page-1] = response
53
88
  end
54
89
 
90
+ # validates all parameters with {#validate!} and returns a hash of the query
91
+ # that will be sent to the boomi api
92
+ # @see #to_json
93
+ # @return [Hash] hash representation of query that will be sent to the boomi api
55
94
  def to_hash
56
95
  validate!
57
96
 
58
97
  { QueryFilter: filter.to_hash }
59
98
  end
60
99
 
100
+ # query json that will be sent to the boomi api
101
+ # @see #to_hash
102
+ # @return [String] JSON query string
61
103
  def to_json
62
104
  JSON.pretty_generate to_hash
63
105
  end
@@ -73,10 +115,15 @@ module Atomsphere
73
115
  end
74
116
  end
75
117
 
118
+ # an instance of the API client
119
+ # @return [Api::Client]
76
120
  def api_client
77
121
  Api::Client.new
78
122
  end
79
123
 
124
+ # if any pages have been retrieved, the value of `queryToken` from the
125
+ # last response
126
+ # @return [String, nil] value of `queryToken`, or `nil`
80
127
  def query_token
81
128
  if result_pages.last.nil? || !result_pages.last.to_hash.keys.include?('queryToken')
82
129
  nil
@@ -86,5 +133,6 @@ module Atomsphere
86
133
  end
87
134
  end
88
135
 
89
- %w(grouping_expression simple_expression).each{ |m| require "#{ROOT}/query/#{m}" }
136
+ require "#{ROOT}/query/builder"
137
+ require "#{ROOT}/query/expression"
90
138
  end
@@ -0,0 +1,39 @@
1
+ module Atomsphere
2
+ class Query
3
+ class Builder
4
+ attr_reader :query
5
+
6
+ def initialize(object_type)
7
+ @query = object_type.nil? ? Query.new : Query.new(object_type)
8
+ end
9
+
10
+ def group operator, &block
11
+ new_group = GroupingExpression.new(operator)
12
+ Group.new(new_group).instance_eval(&block)
13
+
14
+ if @query.filter
15
+ @query.filter.nested_expression << new_group
16
+ else
17
+ @query.filter = new_group
18
+ end
19
+ end
20
+
21
+ def method_missing m, *args, &block
22
+ @query.filter = GroupingExpression.new(:and) unless @query.filter
23
+ Group.new(@query.filter).instance_eval do
24
+ send(m, *args, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.query(object_type=nil, &block)
31
+ q = Query::Builder.new(object_type)
32
+ q.instance_eval(&block) if block_given?
33
+
34
+ q.query
35
+ end
36
+
37
+ require "#{ROOT}/query/builder/property"
38
+ require "#{ROOT}/query/builder/group"
39
+ end
@@ -0,0 +1,26 @@
1
+ module Atomsphere
2
+ class Query
3
+ class Builder
4
+ class Group
5
+ def initialize expression
6
+ @expression = expression
7
+ end
8
+
9
+ def group operator, &block
10
+ new_group = GroupingExpression.new(operator)
11
+ Group.new(new_group).instance_eval(&block)
12
+ @expression.nested_expression << new_group
13
+ end
14
+
15
+ def method_missing m, *args, &block
16
+ __property(@expression, m)
17
+ end
18
+
19
+ private
20
+ def __property(expression, property)
21
+ Property.new(expression, property)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Atomsphere
2
+ class Query
3
+ class Builder
4
+ class Property
5
+ def initialize(expression, property)
6
+ @expression = expression
7
+ @property = property
8
+ end
9
+
10
+ def method_missing m, *args, &block
11
+ __operator(m, *args) if SimpleExpression::OPERATORS.keys.include? m
12
+ end
13
+
14
+ private
15
+ def __operator(operator, args)
16
+ @expression.nested_expression << SimpleExpression.new(
17
+ property: @property,
18
+ operator: operator,
19
+ argument: args
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+
3
+ module Atomsphere
4
+ class Query
5
+
6
+ # @see GroupingExpression
7
+ # @see SimpleExpression
8
+ class Expression
9
+ end
10
+ end
11
+
12
+ Dir["#{ROOT}/query/expression/*.rb"].each{ |f| require f }
13
+ end
@@ -2,12 +2,24 @@ require 'json'
2
2
 
3
3
  module Atomsphere
4
4
  class Query
5
- class GroupingExpression
5
+
6
+ # @see http://help.boomi.com/atomsphere/GUID-4CAE5616-76EB-4C58-B2E3-4173B65EA7EC.html
7
+ class GroupingExpression < Expression
6
8
  attr_accessor :operator, :nested_expression
7
9
 
10
+ # allowed values for {#operator=}
8
11
  OPERATORS = :and, :or
9
12
 
13
+ # @param [Hash] params
14
+ # @option params [:and, :or] :operator query operator
15
+ # @option params [Array<Expression>] :nested_expression one or more {Expression}s
10
16
  def initialize(params={})
17
+ case params
18
+ when String
19
+ when Symbol
20
+ params = {operator: params}
21
+ end
22
+
11
23
  params = {
12
24
  operator: :and,
13
25
  nested_expression: []
@@ -17,6 +29,16 @@ module Atomsphere
17
29
  @nested_expression = params[:nested_expression]
18
30
  end
19
31
 
32
+ def operator= arg
33
+ unless OPERATORS.include? arg.to_sym
34
+ raise ArgumentError, "operator must be one of: #{OPERATORS.join(', ')}"
35
+ end
36
+
37
+ instance_variable_set :@operator, arg.to_sym
38
+ end
39
+
40
+ # run all `validate_*!` private methods to ensure validity of expression parameters
41
+ # @return [true, false]
20
42
  def validate!
21
43
  private_methods.select{ |m| m =~ /^validate_[a-z0-9_]+\!$/ }.each{ |v| "#{v}"; send(v) }
22
44
  @nested_expression.each(&:validate!)
@@ -24,6 +46,9 @@ module Atomsphere
24
46
  true
25
47
  end
26
48
 
49
+ # returns a hash of the expression that will be sent to the boomi api with {Query#to_hash}
50
+ # @see #to_json
51
+ # @return [Hash] hash representation of query that will be sent to the boomi api
27
52
  def to_hash
28
53
  {
29
54
  expression: {
@@ -35,10 +60,6 @@ module Atomsphere
35
60
  }
36
61
  end
37
62
 
38
- def to_json
39
- JSON.pretty_generate to_hash
40
- end
41
-
42
63
  private
43
64
  def validate_operators!
44
65
  unless OPERATORS.include? @operator
@@ -49,13 +70,13 @@ module Atomsphere
49
70
  def validate_expressions!
50
71
  raise ArgumentError, "nested_expression must be an array" unless @nested_expression.is_a?(Array)
51
72
 
52
- not_expressions = @nested_expression.map(&:class).reject do |k|
53
- [GroupingExpression, SimpleExpression].include? k
73
+ not_expressions = @nested_expression.map(&:class).map(&:ancestors).reject do |k|
74
+ k.include? Atomsphere::Query::Expression
54
75
  end
55
76
 
56
77
  if not_expressions.size > 0
57
78
  raise ArgumentError,
58
- "invalid expression class(es): #{not_expressions.map(&:class).join(', ')}"
79
+ "Expressions must be an object of a subclass of Atomsphere::Query::Expression"
59
80
  end
60
81
  end
61
82
 
@@ -2,9 +2,12 @@ require 'json'
2
2
 
3
3
  module Atomsphere
4
4
  class Query
5
- class SimpleExpression
5
+
6
+ # @see http://help.boomi.com/atomsphere/GUID-4CAE5616-76EB-4C58-B2E3-4173B65EA7EC.html
7
+ class SimpleExpression < Expression
6
8
  attr_accessor :operator, :property, :argument
7
9
 
10
+ # allowed values for {#operator=}
8
11
  OPERATORS = {
9
12
  equals: 1,
10
13
  like: 1,
@@ -19,6 +22,10 @@ module Atomsphere
19
22
  less_than_or_equal: 1
20
23
  }
21
24
 
25
+ # @param [Hash] params
26
+ # @option params [String] :property the property/field to query
27
+ # @option params [:equals,:like,:not_equals,:is_null,:is_not_null,:starts_with,:between,:greater_than,:less_than,:greater_than_or_equal,:less_than_or_equal] :operator query operator
28
+ # @option params [Array] :argument array containing the number of arguments specified in the {OPERATORS} constant, as arguments to the query {#operator}
22
29
  def initialize(params={})
23
30
  params = {
24
31
  operator: :equals,
@@ -31,25 +38,26 @@ module Atomsphere
31
38
  end
32
39
  end
33
40
 
41
+ # run all `validate_*!` private methods to ensure validity of expression parameters
42
+ # @return [true, false]
34
43
  def validate!
35
44
  private_methods.select{ |m| m =~ /^validate_[a-z0-9_]+\!$/ }.each{ |v| send(v) }
36
45
  true
37
46
  end
38
47
 
48
+ # returns a hash of the expression that will be sent to the boomi api with {Query#to_hash}
49
+ # @see #to_json
50
+ # @return [Hash] hash representation of query that will be sent to the boomi api
39
51
  def to_hash
40
52
  {
41
53
  expression: {
42
- operator: operator.upcase,
43
- property: property,
44
- argument: [*argument]
54
+ operator: operator.to_s.upcase,
55
+ property: property.to_s,
56
+ argument: [*argument].map(&:to_s)
45
57
  }
46
58
  }
47
59
  end
48
60
 
49
- def to_json
50
- to_hash.to_json
51
- end
52
-
53
61
  def operator= arg
54
62
  unless OPERATORS.keys.include? arg.to_sym
55
63
  raise ArgumentError, "operator must be one of: #{OPERATORS.keys.join(', ')}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atomsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Warren Guy
@@ -59,8 +59,12 @@ files:
59
59
  - lib/atomsphere/api/response.rb
60
60
  - lib/atomsphere/configuration.rb
61
61
  - lib/atomsphere/query.rb
62
- - lib/atomsphere/query/grouping_expression.rb
63
- - lib/atomsphere/query/simple_expression.rb
62
+ - lib/atomsphere/query/builder.rb
63
+ - lib/atomsphere/query/builder/group.rb
64
+ - lib/atomsphere/query/builder/property.rb
65
+ - lib/atomsphere/query/expression.rb
66
+ - lib/atomsphere/query/expression/grouping_expression.rb
67
+ - lib/atomsphere/query/expression/simple_expression.rb
64
68
  homepage: https://github.com/warrenguy/atomsphere-ruby
65
69
  licenses:
66
70
  - MIT