close 0.1.0 → 0.1.2

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: 9aa1bc5d8124785414823311b95736c9ddde2ca4c5f2746e6308443f313ace7a
4
- data.tar.gz: e3eac1f1c53b1da521845eb66bd3a8ec6cd342c608cf216b2cef62e7b0cea410
3
+ metadata.gz: 4ae57ff51e41efeb5bcf5464bca8b5e23a6388806e71fc73378d389be7d652a1
4
+ data.tar.gz: 61eec10200545f071801b978090b9c43e8608e2dc3230207ecbe07bb903106ce
5
5
  SHA512:
6
- metadata.gz: 0a5b9a3e0ee10bced5cccad33bc838c8b156fad65c821f332f548a94d0a6eff47847a340b946b5e91b12c0503bc36c0af883347cca12aa95887ad4d62e3d3144
7
- data.tar.gz: 991f361451aedaf253e9d602f3f8975deb3495202fb2f294c058b32b4ba83ecd20a9d262e7ab2d23aff1ba0d64dea314cfe9c0c05c8773beac094dfdcc218e64
6
+ metadata.gz: 84e59c4ef43627a67343d39f93ef6cf888aa5c038dfa54ee65d23ee3d38d54422788ce44ea6b8b9410e57a0a4bcb7527671d3ef20a5723232895127c177b8509
7
+ data.tar.gz: 776e2d4bedb0051203e458e200ee6e45b016904dbb3d1b6cdaf180988bd3c482ff43408eb981c678389cc1db1cdefd8f2d9dd1cb25a16f8e724a64484bd06a34
data/Gemfile CHANGED
@@ -12,3 +12,7 @@ gem "rspec", "~> 3.0"
12
12
  gem "rubocop", "~> 1.21"
13
13
 
14
14
  gem "faraday"
15
+
16
+ gem "webmock"
17
+
18
+ gem "sinatra"
data/Gemfile.lock CHANGED
@@ -1,24 +1,35 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- close (0.1.0)
4
+ close (0.1.1)
5
5
  faraday
6
6
  ostruct
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
+ addressable (2.8.1)
12
+ public_suffix (>= 2.0.2, < 6.0)
11
13
  ast (2.4.2)
14
+ crack (0.4.5)
15
+ rexml
12
16
  diff-lcs (1.5.0)
13
17
  faraday (2.6.0)
14
18
  faraday-net_http (>= 2.0, < 3.1)
15
19
  ruby2_keywords (>= 0.0.4)
16
20
  faraday-net_http (3.0.1)
21
+ hashdiff (1.0.1)
17
22
  json (2.6.2)
23
+ mustermann (3.0.0)
24
+ ruby2_keywords (~> 0.0.1)
18
25
  ostruct (0.5.5)
19
26
  parallel (1.22.1)
20
27
  parser (3.1.2.1)
21
28
  ast (~> 2.4.1)
29
+ public_suffix (5.0.0)
30
+ rack (2.2.4)
31
+ rack-protection (3.0.2)
32
+ rack
22
33
  rainbow (3.1.1)
23
34
  rake (13.0.6)
24
35
  regexp_parser (2.6.0)
@@ -50,10 +61,21 @@ GEM
50
61
  parser (>= 3.1.1.0)
51
62
  ruby-progressbar (1.11.0)
52
63
  ruby2_keywords (0.0.5)
64
+ sinatra (3.0.2)
65
+ mustermann (~> 3.0)
66
+ rack (~> 2.2, >= 2.2.4)
67
+ rack-protection (= 3.0.2)
68
+ tilt (~> 2.0)
69
+ tilt (2.0.11)
53
70
  unicode-display_width (2.3.0)
71
+ webmock (3.18.1)
72
+ addressable (>= 2.8.0)
73
+ crack (>= 0.3.2)
74
+ hashdiff (>= 0.4.0, < 2.0.0)
54
75
 
55
76
  PLATFORMS
56
77
  arm64-darwin-21
78
+ ruby
57
79
 
58
80
  DEPENDENCIES
59
81
  close!
@@ -61,6 +83,8 @@ DEPENDENCIES
61
83
  rake (~> 13.0)
62
84
  rspec (~> 3.0)
63
85
  rubocop (~> 1.21)
86
+ sinatra
87
+ webmock
64
88
 
65
89
  BUNDLED WITH
66
90
  2.3.7
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Close
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/close.svg)](https://badge.fury.io/rb/close) [![Test Coverage](https://api.codeclimate.com/v1/badges/d83380e81bfb459ea027/test_coverage)](https://codeclimate.com/github/joynerd/close/test_coverage)
4
+
3
5
  This a ruby gem that provides a robust way to interact with the Close
4
6
  CRM API.
5
7
 
@@ -59,17 +61,39 @@ leads = Close::Lead.list
59
61
  # Get a single lead
60
62
  lead = Close::Lead.retrieve('lead_id')
61
63
 
62
- # Update the name
64
+ # Update the name (and other attributes) of a lead. These are not persisted to the API until you call save.
63
65
  lead.name = 'New Name'
64
66
 
65
67
  # Save the changes
66
68
  lead.save
67
69
 
68
-
69
70
  ```
70
71
 
71
72
  ## Supported Resources
72
73
 
74
+ ### Advanced Filters
75
+ [Close API Docs](https://developer.close.com/resources/leads/)
76
+
77
+ Advanced Filters are a clever way to open up search to the API, with the caveat that they are very dense and appear to be written in search DSL (Elastic, Solr, etc).
78
+
79
+ I have tried to encapsulate the complexity of the DSL into a simple interface that is easy to use. This is mostly by defining queries before
80
+ they are run and then running them with parameters when they are needed.
81
+
82
+ An example of an advanced filter query:
83
+
84
+ ```ruby
85
+ # Run a prebuilt query
86
+ Close::AdvancedFilter.run('find_leads_by_email', {email: 'buster.bluth@gmail.com'})
87
+
88
+ # Add a new query
89
+ Close::AdvancedFilter.add('find_leads_by_phone_number', {phone_number: '%PHONE_NUMBER%'})
90
+
91
+ # Run the new query
92
+ Close::AdvancedFilter.run('find_leads_by_phone_number', {phone_number: '555-555-5555'})
93
+ ```
94
+
95
+ If you think you have a common query or one that would be useful to others, please open an issue with a new query and I will add it to the gem. Or you can submit a PR with the JSON for the query added to the repo.
96
+
73
97
  ### Leads
74
98
  [Close API Docs](https://developer.close.com/resources/leads/)
75
99
 
data/close-0.1.0.gem ADDED
Binary file
data/close-0.1.1.gem ADDED
Binary file
@@ -0,0 +1,60 @@
1
+ {
2
+ "limit": null,
3
+ "query": {
4
+ "negate": false,
5
+ "queries": [
6
+ {
7
+ "negate": false,
8
+ "object_type": "lead",
9
+ "type": "object_type"
10
+ },
11
+ {
12
+ "negate": false,
13
+ "queries": [
14
+ {
15
+ "negate": false,
16
+ "related_object_type": "contact",
17
+ "related_query": {
18
+ "negate": false,
19
+ "queries": [
20
+ {
21
+ "negate": false,
22
+ "related_object_type": "contact_email",
23
+ "related_query": {
24
+ "negate": false,
25
+ "queries": [
26
+ {
27
+ "condition": {
28
+ "mode": "full_words",
29
+ "type": "text",
30
+ "value": "%EMAIL%"
31
+ },
32
+ "field": {
33
+ "field_name": "email",
34
+ "object_type": "contact_email",
35
+ "type": "regular_field"
36
+ },
37
+ "negate": false,
38
+ "type": "field_condition"
39
+ }
40
+ ],
41
+ "type": "and"
42
+ },
43
+ "this_object_type": "contact",
44
+ "type": "has_related"
45
+ }
46
+ ],
47
+ "type": "and"
48
+ },
49
+ "this_object_type": "lead",
50
+ "type": "has_related"
51
+ }
52
+ ],
53
+ "type": "and"
54
+ }
55
+ ],
56
+ "type": "and"
57
+ },
58
+ "results_limit": null,
59
+ "sort": []
60
+ }
data/lib/close/errors.rb CHANGED
@@ -3,4 +3,6 @@ module Close
3
3
  class InvalidRequestError < StandardError; end
4
4
  class AuthenticationError < StandardError; end
5
5
  class APIError < StandardError; end
6
+ class QueryNotFoundError < StandardError; end
7
+ class MissingParameterError < StandardError; end
6
8
  end
@@ -0,0 +1,99 @@
1
+ # This class attempts to abstract away the Advanced Filter API.
2
+ # It is very powerful and fast, but building the queries is very tedious.
3
+ # It allows to store preset queries as JSON for common queries that
4
+ # can be commited to the repo and validated. It also lets you
5
+ # define queries on the fly which can then be reused across the
6
+ # codebase without having to copy and paste the query all the time.
7
+ module Close
8
+ class Filter
9
+ extend APIOperations
10
+
11
+ @@queries = {}
12
+
13
+ # Executes a raw query against the Close API.
14
+ # @param [Hash] query The query to execute.
15
+ # @return [Array] An array of results.
16
+ def self.execute(query = {})
17
+ response = request(:post, 'api/v1/data/search/', query)
18
+ response['data']
19
+ end
20
+
21
+ # Executes a query by name.
22
+ # @param [String] name The name of the query to execute.
23
+ # @param [Hash] params The parameters to pass to the query.
24
+ # @return [Array] An array of results.
25
+ def self.run(name, params = {})
26
+ query_string = load_query_from_file(name)
27
+ expected_params = find_params(query_string)
28
+ preflight_params(params, expected_params)
29
+ parameterized_query = apply_params(query_string, params)
30
+ execute(parameterized_query)
31
+ end
32
+
33
+ # Loads a query from a file or from memory.
34
+ # @param [String] name The name of the query.
35
+ # @return [String] A stringified JSON query.
36
+ def self.load_query(name)
37
+ if @@queries[name.to_s]
38
+ @@queries[name.to_s]
39
+ else
40
+ load_query_from_file(name)
41
+ end
42
+ end
43
+
44
+ # This method is used to defined a query at run time.
45
+ # If a name collision occurs, the query will be overwritten.
46
+ # @param [String] name The name of the query.
47
+ # @param [Hash] query_body A hash with placeholders in keys.
48
+ # @return [Void]
49
+ def self.add_query(name, query_body)
50
+ @@queries[name.to_s] = query_body.to_json
51
+ end
52
+
53
+ # Applies the params to the query string.
54
+ # @param [String] query_string The stringified JSON query.
55
+ # @param [Hash] params The parameters to apply.
56
+ # @return [String] The stringified JSON query with the parameters applied.
57
+ def self.apply_params(query_string, params)
58
+ qs = query_string.dup
59
+ params.each do |key, value|
60
+ qs.gsub!(/%#{key.upcase}%/, value)
61
+ end
62
+ qs
63
+ end
64
+
65
+ # Check that all of the params are present in expected_params.
66
+ # @param [Hash] params The parameters to check.
67
+ # @param [Array] expected_params The expected parameters.
68
+ # @return [Void]
69
+ # @raise [Close::MissingParameterError] if a parameter is missing.
70
+ def self.preflight_params(params, expected_params)
71
+ expected_params.each do |param|
72
+ if !params.transform_keys(&:to_s).has_key?(param.to_s)
73
+ raise Close::MissingParameterError, "Missing parameter: #{param}"
74
+ end
75
+ end
76
+ end
77
+
78
+ # Loads a predefined query from a file.
79
+ # @param [String] name The name of the query.
80
+ # @return [String] A stringified JSON query.
81
+ # @raise [Close::QueryNotFoundError] if the file does not exist.
82
+ def self.load_query_from_file(name)
83
+ begin
84
+ file = File.read("lib/close/data/filters/#{name}.json")
85
+ rescue Errno::ENOENT
86
+ raise Close::QueryNotFoundError.new("Query #{name} not found.")
87
+ end
88
+ end
89
+
90
+ # Scans a string a returns the parameters it will expect
91
+ # when executed.
92
+ # @param [String] str The string to scan.
93
+ # @return [Array] An array of parameters.
94
+ def self.find_params(str)
95
+ str.scan(/%[A-Z]+(?:_[A-Z]+)*%/).map{ |x| x[1..-2].downcase }.uniq
96
+ end
97
+
98
+ end
99
+ end
data/lib/close/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Close
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/close.rb CHANGED
@@ -5,6 +5,7 @@ require "faraday"
5
5
  require_relative "close/close_object"
6
6
  require_relative "close/api_operations"
7
7
  require_relative "close/api_resource"
8
+ require_relative "close/filter"
8
9
  require_relative "close/resources"
9
10
  require_relative "close/errors"
10
11
  require_relative "close/version"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: close
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - JoyNerd LLC
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-18 00:00:00.000000000 Z
11
+ date: 2022-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ostruct
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 2.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 2.0.0
41
41
  description: A ruby wrapper for the close.com API that offers caching.
42
42
  email:
43
43
  - developers@joynerd.io
@@ -54,11 +54,15 @@ files:
54
54
  - LICENSE.txt
55
55
  - README.md
56
56
  - Rakefile
57
+ - close-0.1.0.gem
58
+ - close-0.1.1.gem
57
59
  - lib/close.rb
58
60
  - lib/close/api_operations.rb
59
61
  - lib/close/api_resource.rb
60
62
  - lib/close/close_object.rb
63
+ - lib/close/data/filters/find_lead_by_contact_email.json
61
64
  - lib/close/errors.rb
65
+ - lib/close/filter.rb
62
66
  - lib/close/resource/contact.rb
63
67
  - lib/close/resource/custom_activity_type.rb
64
68
  - lib/close/resource/lead.rb
@@ -89,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
93
  - !ruby/object:Gem::Version
90
94
  version: '0'
91
95
  requirements: []
92
- rubygems_version: 3.2.3
96
+ rubygems_version: 3.0.9
93
97
  signing_key:
94
98
  specification_version: 4
95
99
  summary: A ruby wrapper for the close.com API