yext-api 0.1.5 → 0.1.7

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
  SHA1:
3
- metadata.gz: b00aa1601c943ccd86176b00dbd9d0dc2cfe62ba
4
- data.tar.gz: 3dc9545705404a5c812be0d70e77d57f6f61e8e2
3
+ metadata.gz: f99917453bea7720f49022c02cf64fd132944d33
4
+ data.tar.gz: 89289aa7c0dbcf44ac8d10864ee995c71f0a3d24
5
5
  SHA512:
6
- metadata.gz: 55c0f57e48913eddf4ae516022b76ecc9a44ff5b257280b1aa56d4c28e66df12f8023128ea8d2de1443a07e6713b5a43a0ab16e6ab0bbc7157ee6ad6cf9331bf
7
- data.tar.gz: 01d6deaaaaedac4668c22ad2808c1d39fa7ad5e6f6bc7478c144b34e0726811229f0b84b8cbc83c4628eafbdb6f1e2795882c3c9e2b7f8bcf9a2717722ac7411
6
+ metadata.gz: c43378a81d8ef44bfafdab12deb9fcc05c632dbac4ff9b29d1abb9d0d1f50b5d1aceb7b90975268001b99ca3cbac15fec08177ee1a7fbdc1f299e002f91d17ea
7
+ data.tar.gz: 7d83de65e7fc052f52d129e73ae988359eacc34528e3f460f8483aa0793adb2d7be1e6cfe47785ec119fd2d0dae29d425300dd6dc5c898d33fbc808cc9ec1732
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yext-api (0.1.5)
4
+ yext-api (0.1.7)
5
5
  memoist (~> 0)
6
6
  rails (> 4)
7
7
  spyke (~> 5)
data/README.md CHANGED
@@ -91,6 +91,35 @@ The global configurations can be initialized with ENV values. The following con
91
91
  Wether or not to use the Sandbox API endpoint or the API endpoint. This option cannot be set on a
92
92
  per-call basis. This option is ignored for all objects under the `LiveApi` namespace.
93
93
 
94
+ ### Events
95
+
96
+ Webhooks are implimented as ActiveSupport::Notifications.
97
+
98
+ You can hook into notifications in multiple ways:
99
+
100
+ ```ruby
101
+ # with a class:
102
+ class AddRequestChanged
103
+ def call(name, started, finished, unique_id, data)
104
+ params_hash = { name: name, started: started, finished: finished, unique_id: unique_id, data: data }
105
+ Rails.logger.error "add_request_changed called: #{params_hash}"
106
+ end
107
+ end
108
+
109
+ ActiveSupport::Notifications.subscribe "add_request.changed.yext", AddRequestChanged.new
110
+
111
+ # with a block:
112
+ ActiveSupport::Notifications.subscribe "add_request.changed.yext" do |name, started, finished, unique_id, data|
113
+ end
114
+ ```
115
+
116
+ The following notifications will be
117
+ instrumented with the indicated parameters:
118
+
119
+ * add_request.changed.yext
120
+ * **meta** - The meta information for the webhook
121
+ * **add_request** - A Yext::Api::AdministrativeApi::AddRequest object of the changed AddRequest.
122
+
94
123
  ### General Usage
95
124
 
96
125
  The API namespaces are setup to mimic the structure of the Yext API documentation to make it easier
@@ -141,6 +170,7 @@ The following classes are planned based on that structure:
141
170
  * KnowledgeApi::AccountSettings::User
142
171
  * KnowledgeApi::AccountSettings::Account
143
172
  * KnowledgeApi::OptimizationTasks::OptimizationTask
173
+ * KnowledgeApi::OptimizationTasks::OptimizationLink
144
174
  * LiveApi::Menu
145
175
  * LiveApi::Bio
146
176
  * LiveApi::Product
@@ -162,12 +192,18 @@ end
162
192
 
163
193
  #### Fetching a single object
164
194
 
165
- Use `find`
195
+ Use `find` if you want to raise an exception if it cannot be found
166
196
 
167
197
  ```ruby
168
198
  account = Yext::Api::AdministrativeApi::Account.find("my-id")
169
199
  ```
170
200
 
201
+ Use `where(id: id).get` if you do not want an exception to be raised:
202
+
203
+ ```ruby
204
+ account = Yext::Api::AdministrativeApi::Account.where(id: "my-id").get
205
+ ```
206
+
171
207
  #### Overriding configuration options
172
208
 
173
209
  ```ruby
@@ -19,59 +19,44 @@ module Yext
19
19
  extend Memoist
20
20
 
21
21
  def create
22
- process_add_request_changed
22
+ add_request = Yext::Api::AdministrativeApi::AddRequest.new(add_request_hash[:addRequest])
23
+
24
+ ActiveSupport::Notifications.instrument "add_request.changed.yext",
25
+ meta: add_request_hash[:meta],
26
+ add_request: add_request do
27
+ # do your custom stuff here
28
+ end
23
29
 
24
30
  head :ok
25
31
  end
26
32
 
27
33
  private
28
34
 
29
- def process_add_request_changed
30
- processor = Yext::Api.configuration.get_callback_processor(:add_request_changed)
31
-
32
- return if processor.blank?
33
-
34
- processor.new(processor_args[:meta],
35
- Yext::Api::AdministrativeApi::AddRequest.new(processor_args[:addRequest]),
36
- nil).
37
- add_request_changed
38
- end
39
-
40
- def processor_args
41
- params_hash.convert_epoch :meta, :timestamp
42
- params_hash.convert_time :addRequest, :dateSubmitted
43
- params_hash.convert_time :addRequest, :dateCompleted
44
-
45
- params_hash.params
46
- end
47
-
48
35
  # rubocop:disable MethodLength
49
36
 
50
- def params_hash
51
- Yext::Api::Utils::Params.
52
- new(params.
53
- permit(meta: %i[eventType uuid timestamp accountId actor appSpecificAccountId],
54
- addRequest: [:id,
55
- :locationMode,
56
- :existingLocationId,
57
- :newLocationId,
58
- :newLocationAccountId,
59
- :newAccountParentAccountId,
60
- :newLocationData,
61
- { skus: [] },
62
- :agreementId,
63
- :status,
64
- :dateSubmitted,
65
- :dateCompleted,
66
- :statusDetail]).
67
- to_hash.
68
- with_indifferent_access)
37
+ def add_request_hash
38
+ params.
39
+ permit(meta: %i[eventType uuid timestamp accountId actor appSpecificAccountId],
40
+ addRequest: [:id,
41
+ :locationMode,
42
+ :existingLocationId,
43
+ :newLocationId,
44
+ :newLocationAccountId,
45
+ :newAccountParentAccountId,
46
+ :newLocationData,
47
+ { skus: [] },
48
+ :agreementId,
49
+ :status,
50
+ :dateSubmitted,
51
+ :dateCompleted,
52
+ :statusDetail]).
53
+ to_hash.
54
+ with_indifferent_access
69
55
  end
70
56
 
71
57
  # rubocop:enable MethodLength
72
58
 
73
- memoize :processor_args,
74
- :params_hash
59
+ memoize :add_request_hash
75
60
  end
76
61
  end
77
62
  end
@@ -30,8 +30,6 @@ module Yext
30
30
  class Account < Yext::Api::Utils::ApiBase
31
31
  include Yext::Api::Concerns::AccountRelations
32
32
 
33
- after_save :save_account_id
34
-
35
33
  # The save action only allows the saving of the account_id and the accountName
36
34
  #
37
35
  # Furthermore, the account_id cannot be changed by the partner, but only by the customer
@@ -48,24 +46,6 @@ module Yext
48
46
 
49
47
  save_account_id
50
48
  end
51
-
52
- # rubocop:disable Naming/MethodName
53
-
54
- # Yext field names don't match the Ruby naming standard, this is the field name they use.
55
- # Because I use `account_id` in the route, I need that attribute defined. Because
56
- # Yext uses accountId, when it is set, I need to set `account_id` so they will match.
57
- def accountId=(value)
58
- super
59
- attributes[:account_id] ||= value
60
- end
61
-
62
- # rubocop:enable Naming/MethodName
63
-
64
- private
65
-
66
- def save_account_id
67
- attributes[:account_id] = accountId
68
- end
69
49
  end
70
50
  end
71
51
  end
@@ -47,6 +47,19 @@ module Yext
47
47
 
48
48
  include Yext::Api::Concerns::AccountChild
49
49
 
50
+ # rubocop:disable Naming/MethodName
51
+
52
+ # helper function to extract the affected location ID based on the locationMode
53
+ def locationId
54
+ if locationMode == Yext::Api::Enumerations::AddRequestLocationMode::NEW
55
+ newLocationId
56
+ else
57
+ existingLocationId
58
+ end
59
+ end
60
+
61
+ # rubocop:enable Naming/MethodName
62
+
50
63
  # This is a helper method to try to simplify changing the status of an AddRequest if you
51
64
  # don't have an AddRequest object.
52
65
  #
@@ -89,6 +102,8 @@ module Yext
89
102
  post
90
103
  end)
91
104
 
105
+ # After successfully creating a new add request, the object attributes will be updated/
106
+ # changed to the values of the created add request.
92
107
  def save
93
108
  if persisted?
94
109
  change_status
@@ -104,6 +119,12 @@ module Yext
104
119
  with(Yext::Api::Concerns::AccountChild.with_account_path("newlocationaddrequests")).
105
120
  where(attributes.reverse_merge(account_id: Yext::Api.configuration.param_account_id)).
106
121
  post
122
+
123
+ if Yext::Api::AdministrativeApi.last_status.between?(200, 299)
124
+ self.attributes = Yext::Api::AdministrativeApi.last_data.dup
125
+ else
126
+ self
127
+ end
107
128
  end
108
129
 
109
130
  def change_status
@@ -29,6 +29,7 @@ module Yext
29
29
  next if account_class.association?(klass)
30
30
 
31
31
  klass_uri = klass.instance_variable_get(:@uri)
32
+
32
33
  klass_uri ||= klass.send(:default_uri)
33
34
  helper_warnings(account_class, klass, klass_uri)
34
35
 
@@ -79,6 +80,8 @@ module Yext
79
80
  end)
80
81
 
81
82
  Yext::Api::Concerns::AccountChild.ensure_relation(self)
83
+
84
+ after_save :save_account_id
82
85
  end
83
86
 
84
87
  class_methods do
@@ -110,11 +113,31 @@ module Yext
110
113
 
111
114
  args[:account_id] ||= Yext::Api.configuration.param_account_id
112
115
 
116
+ # account_scope means that the scope will be applied to an Account rather than a
117
+ # relation off of an Account.
113
118
  args[:id] = args.delete(:account_id) if account_scope
114
119
 
115
120
  args
116
121
  end
117
122
  end
123
+
124
+ # rubocop:disable Naming/MethodName
125
+
126
+ # Yext field names don't match the Ruby naming standard, this is the field name they use.
127
+ # Because I use `account_id` in the route, I need that attribute defined. Because
128
+ # Yext uses accountId, when it is set, I need to set `account_id` so they will match.
129
+ def accountId=(value)
130
+ super
131
+ attributes[:account_id] = value
132
+ end
133
+
134
+ # rubocop:enable Naming/MethodName
135
+
136
+ private
137
+
138
+ def save_account_id
139
+ attributes[:account_id] = attributes[:accountId] if attributes.key?(:accountId)
140
+ end
118
141
  end
119
142
  end
120
143
  end
@@ -36,6 +36,26 @@ module Yext
36
36
 
37
37
  # LiveApi
38
38
  has_many :live_locations, class_name: "Yext::Api::LiveApi::Location"
39
+
40
+ after_save :save_account_id
41
+ end
42
+
43
+ # rubocop:disable Naming/MethodName
44
+
45
+ # Yext field names don't match the Ruby naming standard, this is the field name they use.
46
+ # Because I use `account_id` in the route, I need that attribute defined. Because
47
+ # Yext uses accountId, when it is set, I need to set `account_id` so they will match.
48
+ def accountId=(value)
49
+ super
50
+ attributes[:account_id] ||= value
51
+ end
52
+
53
+ # rubocop:enable Naming/MethodName
54
+
55
+ private
56
+
57
+ def save_account_id
58
+ attributes[:account_id] = accountId
39
59
  end
40
60
 
41
61
  class_methods do
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Enumerations
6
+ # The type of the location in an AddRequest
7
+ class AddRequestLocationMode
8
+ include Yext::Api::Concerns::EnumAll
9
+
10
+ EXISTING = "EXISTING"
11
+ NEW = "NEW"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -3,6 +3,7 @@
3
3
  module Yext
4
4
  module Api
5
5
  module Enumerations
6
+ # The possible modes to search for when looking up Optimization Links
6
7
  class OptimizationLinkMode
7
8
  include Yext::Api::Concerns::EnumAll
8
9
 
@@ -46,6 +46,30 @@ module Yext
46
46
  class Location < Yext::Api::Utils::ApiBase
47
47
  include Yext::Api::Concerns::AccountChild
48
48
 
49
+ scope(:search, lambda do |*filters|
50
+ args = scope_args true
51
+ args[:filters] = Array.wrap(filters).to_json
52
+
53
+ Yext::Api::AdministrativeApi::Account.
54
+ where(args).
55
+ with(:locationsearch).
56
+ get
57
+ end)
58
+
59
+ def save(*fields_to_update)
60
+ return super if fields_to_update.blank?
61
+
62
+ # To save only certain fields, slice those fields into a new Location so that everything
63
+ # is sent (which is only the fields we want)
64
+ location = Yext::Api::KnowledgeApi::KnowledgeManager::Location.
65
+ new(attributes.with_indifferent_access.slice(*fields_to_update))
66
+
67
+ location.id = id
68
+ location.accountId = accountId
69
+
70
+ location.save
71
+ end
72
+
49
73
  # http://developer.yext.com/docs/administrative-api/#operation/createExistingLocationAddRequest
50
74
  def add_services!(skus:, agreement_id: nil, force_review: false)
51
75
  args = { existingAccountId: account_id, existingLocationId: id }
@@ -55,23 +55,6 @@ module Yext
55
55
  #
56
56
  # sandbox
57
57
  # Boolean that indicates if the gem should use the production or sandbox URL.
58
- #
59
- # default_callback_processor
60
- # The default class to be used to process webhook messages that are called.
61
- # The code will warn about any missing webhook messages in a default processor.
62
- # set_callback_processor(callback_function_name, processor)
63
- # The class to be used to process webhook messages for a specific callback.
64
- # If the method callback_function_name is not a public instance method for processor, an error
65
- # will be raised.
66
- #
67
- # The processor class must be able to be instanciated with the following arguments:
68
- # * meta - a hash of metadata for the webhook
69
- # * object - a Spyke::Base object that represents the object that ws updated or changed
70
- # to cause the hook event.
71
- # * language_profiles - (optional) An array of objects.
72
- #
73
- # The functions that can be called for the webhooks are:
74
- # * add_request_changed
75
58
  class Configuration
76
59
  include Singleton
77
60
 
@@ -100,80 +83,8 @@ module Yext
100
83
  account_id || "me"
101
84
  end
102
85
 
103
- def default_callback_processor=(value)
104
- callback_names.each do |callback_name|
105
- verify_method(value, callback_name)
106
- end
107
-
108
- callback_processors[:default] = value
109
- end
110
-
111
- def default_callback_processor
112
- callback_processors[:default]
113
- end
114
-
115
- def set_callback_processor(callback_function_name, processor)
116
- callback_function_name = callback_function_name.downcase.to_sym
117
-
118
- validate_arguments(callback_function_name, processor)
119
-
120
- if processor.present?
121
- callback_processors[callback_function_name.downcase.to_sym] = processor
122
- else
123
- callback_processors.delete(callback_function_name.downcase.to_sym)
124
- end
125
- end
126
-
127
- def get_callback_processor(callback_function_name)
128
- callback_function_name = callback_function_name.downcase.to_sym
129
-
130
- callback_processors.fetch(callback_function_name, callback_processors[:default])
131
- end
132
-
133
86
  private
134
87
 
135
- def validate_arguments(callback_function_name, processor)
136
- raise ArgumentError, "invalid callback function #{callback_function_name}" unless callback_names.include?(callback_function_name)
137
-
138
- return if verify_method(processor, callback_function_name)
139
-
140
- raise ArgumentError, "#{processor.name} does not have a valid #{callback_function_name} function"
141
- end
142
-
143
- def callback_processors
144
- @callback_processors ||= {}
145
- end
146
-
147
- def callback_names
148
- %i[add_request_changed].dup
149
- end
150
-
151
- def verify_method(callback_class, method_name)
152
- return true if callback_class.blank?
153
- return true if valid_method_definition?(callback_class, method_name)
154
-
155
- warning_messsage = "The callback_processor does not include a valid #{method_name} method."
156
- if Object.const_defined?("Rails")
157
- Rails.logger.warn warning_messsage
158
- else
159
- # :nocov:
160
- puts warning_messsage
161
- # :nocov:
162
- end
163
-
164
- false
165
- end
166
-
167
- def valid_method_definition?(callback_class, method_name)
168
- return false if callback_class.public_instance_methods.grep(method_name).blank?
169
-
170
- method = callback_class.instance_method(method_name)
171
-
172
- return true if method.parameters.length.zero?
173
-
174
- method.parameters.count { |param_details| %i[keyreq req].include?(param_details.first) }.zero?
175
- end
176
-
177
88
  def read_from_environment_variables
178
89
  @sandbox = !Rails.env.production?
179
90
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yext
4
4
  module Api
5
- VERSION = "0.1.5"
5
+ VERSION = "0.1.7"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yext-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - CardTapp
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-20 00:00:00.000000000 Z
11
+ date: 2018-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: memoist
@@ -260,6 +260,7 @@ files:
260
260
  - lib/yext/api/concerns/faraday_connection.rb
261
261
  - lib/yext/api/concerns/rate_limits.rb
262
262
  - lib/yext/api/engine.rb
263
+ - lib/yext/api/enumerations/add_request_location_mode.rb
263
264
  - lib/yext/api/enumerations/add_request_status.rb
264
265
  - lib/yext/api/enumerations/error_codes.rb
265
266
  - lib/yext/api/enumerations/error_codes/agreements_errors.rb
@@ -298,7 +299,6 @@ files:
298
299
  - lib/yext/api/utils/middleware/default_parameters.rb
299
300
  - lib/yext/api/utils/middleware/response_parser.rb
300
301
  - lib/yext/api/utils/middleware/uri_cleanup.rb
301
- - lib/yext/api/utils/params.rb
302
302
  - lib/yext/api/validators/account_validator.rb
303
303
  - lib/yext/api/version.rb
304
304
  - lib/yext/include_rails.rb
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Yext
4
- module Api
5
- module Utils
6
- # A utility class for performing normal modifications to webhooks to convert/normalize data
7
- # before passing it along so that the receiver doesn't have to worry/thnk about it.
8
- class Params
9
- attr_reader :params
10
-
11
- def initialize(params)
12
- @params = params
13
- end
14
-
15
- # Converts an integer epoch date value into a Time.
16
- #
17
- # The param_names is a list of nodes which ends with a leaf node that is the epoch value
18
- # to be converted to a Time.
19
- #
20
- # If any node along the way cannot be found, the function exits without errors or changing any values.
21
- def convert_epoch(*param_names)
22
- return unless param_names.present?
23
-
24
- param_name = param_names[-1]
25
- param_level = find_value(*param_names)
26
-
27
- return unless param_level.present?
28
-
29
- param_level[param_name] = Time.at(param_level[param_name].to_i / 1_000.0)
30
- end
31
-
32
- # Converts time string into a Time.
33
- #
34
- # The param_names is a list of nodes which ends with a leaf node that is the time string
35
- # to be converted to a Time.
36
- #
37
- # If any node along the way cannot be found, the function exits without errors or changing any values.
38
- def convert_time(*param_names)
39
- return unless param_names.present?
40
-
41
- param_name = param_names[-1]
42
- param_level = find_value(*param_names)
43
-
44
- return unless param_level.present?
45
-
46
- param_level[param_name] = param_level[param_name].to_time(:utc)
47
- end
48
-
49
- private
50
-
51
- def find_value(*param_names)
52
- param_level = params
53
- found_param = param_names[0..-2].each do |param_name|
54
- break unless param_level.key?(param_name)
55
-
56
- param_level = param_level[param_name]
57
- end
58
-
59
- return if found_param.nil?
60
-
61
- param_name = param_names[-1]
62
- return unless param_level.key?(param_name) && param_level[param_name].present?
63
-
64
- param_level
65
- end
66
- end
67
- end
68
- end
69
- end