atomsphere 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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