vng 2.4.0 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eaf5c18372847d998d4e0d4c25e7bfe79ce17a11df1e573c66771cd963b3cb0a
4
- data.tar.gz: 3cb76db925bd75bc8568607e3375ee18c6ed41f1c689b0624e2fc6de642e4be2
3
+ metadata.gz: 15e3e4b9f188fa73d3cdea696d1fac21c02ce00f1f67ada372fd328e0b1f1fac
4
+ data.tar.gz: 5d12461918e68ef048dc8ac0b7111d8a1337000c1815d2273fbe15409b0fd732
5
5
  SHA512:
6
- metadata.gz: 527b1ced6a89489422f020b7745b6b38026d8b8187c9f3fd36abd9b55fffc21f9247a7af492c957419fe48bef126a0a3bc2894304fc23ebdb77e950446de9109
7
- data.tar.gz: 86024f32fa8d9c432225d7b0a655336e5894e0ebfc13c11b4f39f18ce5cb9df2836ca06cb056135a86f7e52253f096cc2a0607a305d38241e4992799d87e6a00
6
+ metadata.gz: 3610cb024f1fcfaddd1d26fcfa82052bd43431a1890d2bed429c9eb0c8e1a7622a4be507bd57cec0c14c0cb08c03eda72f0d45a4acf97884b13c8b57004ed7f6
7
+ data.tar.gz: a0c5144d0e2458ec4830814d0689cf24a8cc3ce00915ba2c6649795fc3a45e6c5325c2f8a52ab650af03b522d73a92e1aca2efe93ffb11ded2b80855216704df
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [3.0.1] - 2025-01-10
2
+
3
+ - Make Contact.edited_since lazy
4
+
5
+ ## [3.0.0] - 2025-01-09
6
+
7
+ - Add Contact.edited_since(timestamp)
8
+
9
+ **Breaking changes**
10
+
11
+ - Remove Contact.all
12
+
1
13
  ## [2.4.0] - 2025-01-09
2
14
 
3
15
  - Add Contact.all
data/lib/vng/contact.rb CHANGED
@@ -1,38 +1,65 @@
1
1
  require 'vng/resource'
2
2
 
3
+ require ENV['VNG_MOCK'] ? 'vng/mock_request' : 'vng/http_request'
4
+ require 'vng/relation'
5
+
3
6
  module Vng
4
7
  # Provides methods to interact with Vonigo contacts.
5
8
  class Contact < Resource
6
9
  PATH = '/api/v1/data/Contacts/'
7
10
 
8
- attr_reader :id, :first_name, :last_name, :email, :phone, :client_id
11
+ # @param [Hash<Symbol, String>] data the options to initialize a resource.
12
+ # @option data [String] :object_id The unique ID of a Vonigo resource.
13
+ # @option data [Array] :fields The fields of a Vonigo resource.
14
+ def initialize(data = {})
15
+ @data = data
16
+ end
17
+
18
+ # @return [String] the resource’s unique ID.
19
+ def id
20
+ @data['objectID']
21
+ end
22
+
23
+ def active?
24
+ @data['isActive'] != 'false'
25
+ end
26
+
27
+ def first_name
28
+ self.class.value_for_field @data, 127
29
+ end
30
+
31
+ def last_name
32
+ self.class.value_for_field @data, 128
33
+ end
9
34
 
10
- def initialize(id:, first_name:, last_name:, email:, phone:, client_id:)
11
- @id = id
12
- @first_name = first_name
13
- @last_name = last_name
14
- @email = email
15
- @phone = phone
16
- @client_id = client_id
35
+ def email
36
+ self.class.value_for_field @data, 97
17
37
  end
18
38
 
19
- def self.all # TODO: add (edited_after: param)
20
- body = { isCompleteObject: 'true' }
39
+ def phone
40
+ self.class.value_for_field @data, 96
41
+ end
21
42
 
22
- data = request path: PATH, body: body, returning: 'Contacts'
43
+ def client_id
44
+ self.class.value_for_relation @data, 'client'
45
+ end
23
46
 
24
- data.filter_map do |body|
25
- next unless body['isActive']
47
+ def edited_at
48
+ Time.at Integer(@data['dateLastEdited']), in: 'UTC'
49
+ end
26
50
 
27
- id = body['objectID']
28
- first_name = value_for_field body, 127
29
- last_name = value_for_field body, 128
30
- email = value_for_field body, 97
31
- phone = value_for_field body, 96
32
- client_id = value_for_relation body, 'client'
51
+ # @return [Vng::Relation] the resources matching the conditions.
52
+ def self.where(conditions = {})
53
+ @where ||= Relation.new
54
+ @where.where conditions
55
+ end
33
56
 
34
- new id: id, first_name: first_name, last_name: last_name, email: email, phone: phone, client_id: client_id
35
- end
57
+ def self.edited_since(timestamp)
58
+ contacts = where isCompleteObject: 'true', dateStart: timestamp.to_i, dateMode: 2
59
+ # TODO: select should accept sub-hash, e.g.
60
+ # .select :date_last_edited, fields: [134, 1036], relations: ['client']
61
+ contacts = contacts.select 'dateLastEdited', 'Fields', 'Relations'
62
+ contacts.lazy.filter(&:active?)
36
63
  end
37
64
 
38
65
  def self.create(first_name:, last_name:, email:, phone:, client_id:)
@@ -48,14 +75,7 @@ module Vng
48
75
  }
49
76
 
50
77
  data = request path: PATH, body: body
51
-
52
- id = data['Contact']['objectID']
53
- first_name = value_for_field data, 127
54
- last_name = value_for_field data, 128
55
- email = value_for_field data, 97
56
- phone = value_for_field data, 96
57
-
58
- new id: id, first_name: first_name, last_name: last_name, email: email, phone: phone, client_id: client_id
78
+ new data['Contact']
59
79
  end
60
80
  end
61
81
  end
@@ -123,7 +123,7 @@ module Vng
123
123
  when '/api/v1/data/Contacts/'
124
124
  if @body[:pageNo].eql? 1
125
125
  {"Contacts" => [
126
- {"objectID" => "2201007", "isActive" => "true", "Fields" => [
126
+ {"objectID" => "2201007", "dateLastEdited" => "1736479080", "isActive" => "true", "Fields" => [
127
127
  {"fieldID"=>127, "fieldValue"=>"Vng" },
128
128
  {"fieldID"=>128, "fieldValue"=>"Example" },
129
129
  {"fieldID"=>97, "fieldValue"=>"vng@example.com" },
@@ -0,0 +1,89 @@
1
+ module Vng
2
+ # Provides methods to iterate through collections of Vonigo resources.
3
+ # @private
4
+ class Relation
5
+ include Enumerable
6
+
7
+ # @yield [Hash] the options to change which items to iterate through.
8
+ def initialize(options = {}, &item_block)
9
+ @options = {parts: ['objectID', 'isActive'], next_page: 1}
10
+ @options.merge! options
11
+ @item_block = item_block
12
+ end
13
+
14
+ # Specifies which items to fetch when hitting the data API.
15
+ # @param [Hash<Symbol, String>] conditions The conditions for the items.
16
+ # @return [Vng::Relation] itself.
17
+ def where(conditions = {})
18
+ if @options[:conditions] != conditions
19
+ @items = []
20
+ @options.merge! conditions: conditions
21
+ end
22
+ self
23
+ end
24
+
25
+ # Specifies which parts of the resource to fetch when hitting the data API.
26
+ # @param [Array<Symbol>] parts The parts to fetch.
27
+ # @return [Vng::Relation] itself.
28
+ def select(*parts)
29
+ if @options[:parts] != parts + ['objectID', 'isActive']
30
+ @items = nil
31
+ @options.merge! parts: (parts + ['objectID', 'isActive'])
32
+ end
33
+ self
34
+ end
35
+
36
+ def each
37
+ @last_index = 0
38
+ while next_item = find_next
39
+ yield next_item
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def request(path:, body: {}, query: {}, include_security_token: true)
46
+ if query.none? && include_security_token
47
+ body = body.merge securityToken: Vng.configuration.security_token
48
+ end
49
+
50
+ response_for path:, body:, query:
51
+ end
52
+
53
+ def response_for(path:, body: {}, query: {})
54
+ instrument do |data|
55
+ Request.new(host: Vng.configuration.host, path: path, query: query, body: body).run
56
+ end
57
+ end
58
+
59
+ def find_next
60
+ @items ||= []
61
+ if @items[@last_index].nil? && more_pages?
62
+ body = @options[:conditions].merge pageSize: 500, pageNo: @options[:next_page], sortMode: 3, sortDirection: 0
63
+
64
+ response_body = request path: '/api/v1/data/Contacts/', body: body
65
+
66
+ more_items = response_body['Contacts'].map do |contact_data|
67
+ Vng::Contact.new contact_data.slice(*@options[:parts])
68
+ end
69
+ @options.merge! next_page: (more_items.size == 500 ? @options[:next_page] + 1 : 1)
70
+ @items.concat more_items
71
+ end
72
+ @items[(@last_index +=1) -1]
73
+ end
74
+
75
+ def more_pages?
76
+ @last_index.zero? || @options[:next_page] > 1
77
+ end
78
+
79
+ # Provides instrumentation to ActiveSupport listeners
80
+ def instrument(&block)
81
+ data = { class_name: 'Vng::Contact' }
82
+ if defined?(ActiveSupport::Notifications)
83
+ ActiveSupport::Notifications.instrument 'Vng.request', data, &block
84
+ else
85
+ block.call data
86
+ end
87
+ end
88
+ end
89
+ end
data/lib/vng/resource.rb CHANGED
@@ -29,7 +29,7 @@ module Vng
29
29
  end
30
30
 
31
31
  def self.response_for(path:, body: {}, query: {})
32
- instrument do |data|
32
+ instrument do
33
33
  Request.new(host: host, path: path, query: query, body: body).run
34
34
  end
35
35
  end
@@ -55,10 +55,10 @@ module Vng
55
55
  # Provides instrumentation to ActiveSupport listeners
56
56
  def self.instrument(&block)
57
57
  data = { class_name: name }
58
- if defined?(ActiveSupport::Notifications)
58
+ if defined? ActiveSupport::Notifications
59
59
  ActiveSupport::Notifications.instrument 'Vng.request', data, &block
60
60
  else
61
- block.call data
61
+ block.call
62
62
  end
63
63
  end
64
64
  end
data/lib/vng/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vng
2
- VERSION = '2.4.0'
2
+ VERSION = '3.0.1'
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vng
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-10 00:00:00.000000000 Z
10
+ date: 2025-01-11 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: simplecov
@@ -83,6 +83,7 @@ files:
83
83
  - lib/vng/price_block.rb
84
84
  - lib/vng/price_item.rb
85
85
  - lib/vng/price_list.rb
86
+ - lib/vng/relation.rb
86
87
  - lib/vng/resource.rb
87
88
  - lib/vng/route.rb
88
89
  - lib/vng/security_token.rb