yext-api 0.1.1 → 0.1.3

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +16 -8
  4. data/PULL_REQUEST_TEMPLATE.md +11 -0
  5. data/README.md +25 -7
  6. data/app/controllers/yext/api/agreements/add_request_controller.rb +78 -0
  7. data/app/controllers/yext/api/application_controller.rb +1 -3
  8. data/config/initializers/memoist.rb +3 -0
  9. data/config/routes.rb +3 -0
  10. data/lib/config/api.yml +95 -230
  11. data/lib/yext/api/administrative_api/account.rb +37 -27
  12. data/lib/yext/api/administrative_api/add_request.rb +87 -3
  13. data/lib/yext/api/administrative_api/service.rb +26 -4
  14. data/lib/yext/api/concerns/account_child.rb +37 -8
  15. data/lib/yext/api/concerns/account_relations.rb +16 -1
  16. data/lib/yext/api/concerns/default_scopes.rb +8 -2
  17. data/lib/yext/api/concerns/faraday_connection.rb +21 -7
  18. data/lib/yext/api/concerns/rate_limits.rb +8 -1
  19. data/lib/yext/api/enumerations/add_request_status.rb +19 -0
  20. data/lib/yext/api/enumerations/location_type.rb +18 -0
  21. data/lib/yext/api/knowledge_api/account_settings/account.rb +0 -2
  22. data/lib/yext/api/knowledge_api/account_settings/role.rb +24 -0
  23. data/lib/yext/api/knowledge_api/account_settings/user.rb +81 -0
  24. data/lib/yext/api/knowledge_api/health_check/health.rb +0 -1
  25. data/lib/yext/api/knowledge_api/knowledge_manager/category.rb +0 -1
  26. data/lib/yext/api/knowledge_api/knowledge_manager/location.rb +18 -6
  27. data/lib/yext/api/live_api/location.rb +0 -4
  28. data/lib/yext/api/utils/api_base.rb +8 -0
  29. data/lib/yext/api/utils/api_finder.rb +100 -0
  30. data/lib/yext/api/utils/configuration.rb +93 -0
  31. data/lib/yext/api/utils/middleware/api_rate_limits.rb +35 -0
  32. data/lib/yext/api/utils/middleware/default_parameters.rb +138 -0
  33. data/lib/yext/api/utils/middleware/response_parser.rb +111 -0
  34. data/lib/yext/api/utils/middleware/uri_cleanup.rb +48 -0
  35. data/lib/yext/api/utils/params.rb +69 -0
  36. data/lib/yext/api/version.rb +1 -1
  37. data/yext-api.gemspec +6 -7
  38. metadata +56 -31
  39. data/.travis.yml +0 -5
  40. data/app/assets/config/yext_api_manifest.js +0 -2
  41. data/app/assets/images/yext/api/.keep +0 -0
  42. data/app/assets/javascripts/yext/api/application.js +0 -13
  43. data/app/assets/stylesheets/yext/api/application.css +0 -15
  44. data/app/docs/notes.txt +0 -45
  45. data/app/helpers/yext/api/application_helper.rb +0 -11
  46. data/app/jobs/yext/api/application_job.rb +0 -8
  47. data/app/mailers/yext/api/application_mailer.rb +0 -11
  48. data/app/models/yext/api/application_record.rb +0 -10
  49. data/app/views/layouts/yext/api/application.html.erb +0 -14
  50. data/lib/tasks/yext/api_tasks.rake +0 -6
  51. data/lib/yext/api/concerns/api_finder.rb +0 -61
  52. data/lib/yext/api/utils/api_rate_limits.rb +0 -36
  53. data/lib/yext/api/utils/default_parameters.rb +0 -57
  54. data/lib/yext/api/utils/response_parser.rb +0 -84
@@ -6,37 +6,12 @@ module Yext
6
6
  # :administrative_api:
7
7
  # :account:
8
8
  # :actions:
9
- # - :action: :create
10
- # :method: :post
11
- # :endpoint: https://api.yext.com/v2/accounts/{accountId}/newlocationaddrequests
12
- # :path_regex: v2/accounts/\w+/newlocationaddrequests
13
- # :default_version: 20161012
14
- # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createNewLocationAddRequest
15
- # :comment: Request that a new location be added and services added to it. The location is created only if the request succeeds.
16
- # :sandbox_only: false
17
- # - :action: :add_services
18
- # :method: :post
19
- # :endpoint: https://api.yext.com/v2/accounts/{accountId}/existinglocationaddrequests
20
- # :path_regex: v2/accounts/\w+/existinglocationaddrequests
21
- # :default_version: 20161012
22
- # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createExistingLocationAddRequest
23
- # :comment: Request that one or more available services be added to an existing location.
24
- # :sandbox_only: false
25
- # - :action: :change_status
26
- # :method: :post
27
- # :endpoint: https://api.yext.com/v2/accounts/{accountId}/processaddrequest
28
- # :path_regex: v2/accounts/\w+/processaddrequest
29
- # :default_version: 20161012
30
- # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createProcessReviewAddRequest
31
- # :comment: Request that an add request in REVIEW be processed to COMPLETE, CANCELED, or FAILED.
32
- # :sandbox_only: true
33
9
  # - :action: :index
34
10
  # :method: :get
35
11
  # :endpoint: https://api.yext.com/v2/accounts
36
12
  # :path_regex: v2/accounts
37
13
  # :default_version: 20161012
38
14
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAccounts
39
- # :comment: List all accounts that you have access to. Unless you are in Partner Portal mode, this will only be your own account.
40
15
  # :sandbox_only: false
41
16
  # - :action: :show
42
17
  # :method: :get
@@ -44,7 +19,6 @@ module Yext
44
19
  # :path_regex: v2/accounts/\w+
45
20
  # :default_version: 20161012
46
21
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/getAccount
47
- # :comment: Get details for an account.
48
22
  # :sandbox_only: false
49
23
  # - :action: :update
50
24
  # :method: :put
@@ -52,10 +26,46 @@ module Yext
52
26
  # :path_regex: v2/accounts/\w+
53
27
  # :default_version: 20161012
54
28
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/updateAccount
55
- # :comment: Update an account's name or ID.
56
29
  # :sandbox_only: false
57
30
  class Account < Yext::Api::Utils::ApiBase
58
31
  include Yext::Api::Concerns::AccountRelations
32
+
33
+ after_save :save_account_id
34
+
35
+ # The save action only allows the saving of the account_id and the accountName
36
+ #
37
+ # Furthermore, the account_id cannot be changed by the partner, but only by the customer
38
+ # themselves.
39
+ def save
40
+ return unless accountId?
41
+
42
+ updates = { account_id: account_id, accountName: accountName }
43
+ updates[:accountId] = accountId if accountId != account_id
44
+
45
+ scope.with(Yext::Api::Concerns::AccountChild.with_account_path("")).
46
+ where(updates).
47
+ put
48
+
49
+ save_account_id
50
+ 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
59
69
  end
60
70
  end
61
71
  end
@@ -13,8 +13,6 @@ module Yext
13
13
  # :path_regex: v2/accounts/[^/]+?/addrequests
14
14
  # :default_version: 20161012
15
15
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAddRequests
16
- # :comment: Get all of the add requests in the account. The response includes both New Location
17
- # Add Requests and Existing Location Add Requests.
18
16
  # :sandbox_only: false
19
17
  # - :action: :show
20
18
  # :method: :get
@@ -22,12 +20,98 @@ module Yext
22
20
  # :path_regex: v2/accounts/[^/]+?/addrequests/[^/]+??
23
21
  # :default_version: 20161012
24
22
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/getAddRequest
25
- # :comment: Get status information about an add request previously created.
23
+ # :sandbox_only: false
24
+ # - :action: :create
25
+ # :method: :post
26
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/newlocationaddrequests
27
+ # :path_regex: v2/accounts/\w+/newlocationaddrequests
28
+ # :default_version: 20161012
29
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createNewLocationAddRequest
30
+ # :sandbox_only: false
31
+ # - :action: :update
32
+ # :method: :post
33
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/processaddrequest
34
+ # :path_regex: v2/accounts/\w+/processaddrequest
35
+ # :default_version: 20161012
36
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createProcessReviewAddRequest
37
+ # :sandbox_only: true
38
+ # - :action: :add_services
39
+ # :method: :post
40
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/existinglocationaddrequests
41
+ # :path_regex: v2/accounts/\w+/existinglocationaddrequests
42
+ # :default_version: 20161012
43
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createExistingLocationAddRequest
26
44
  # :sandbox_only: false
27
45
  class AddRequest < Yext::Api::Utils::ApiBase
28
46
  uri("addrequests/(:id)")
29
47
 
30
48
  include Yext::Api::Concerns::AccountChild
49
+
50
+ # This is a helper method to try to simplify changing the status of an AddRequest if you
51
+ # don't have an AddRequest object.
52
+ #
53
+ # Some examples of ways to change a status:
54
+ # Yext::Api::AdministrativeApi::AddRequest.change_status!(request_id, Yext::Api::Enumerations::AddRequestStatus::COMPLETE)
55
+ # Yext::Api::AdministrativeApi::AddRequest.new(id: request_id, status: Yext::Api::Enumerations::AddRequestStatus::COMPLETE).save
56
+ # add_request = Yext::Api::AdministrativeApi::AddRequest.find(request_id)
57
+ # add_request.status = Yext::Api::Enumerations::AddRequestStatus::COMPLETE)
58
+ # add_request.save
59
+ def self.change_status!(request_id, new_status)
60
+ raise InvalidArgument "invalid status" unless Yext::Api::Enumerations::AddRequestStatus.all.include?(new_status)
61
+
62
+ new(id: request_id, status: new_status).save
63
+ end
64
+
65
+ # A method as scope to add services to an AddRequest. This feature is here because it is documented
66
+ # in the AdministrativeApi as basically a method on the AddRequest concept.
67
+ #
68
+ # The Location contains an instance method to do this without having to pass in the
69
+ # arguments hash:
70
+ #
71
+ # Some examples of ways to add services:
72
+ # Yext::Api::AdministrativeApi::AddRequest.add_services! existingLocationId: location_id
73
+ # existingLocationAccountId: child_account_id,
74
+ # skus: [sku]
75
+ #
76
+ # location = Yext::KnowledgeApi::KnowledgeManager::Location.account(child_account_id).find(location_id)
77
+ # location.add_services! skus: [sku]
78
+ #
79
+ # location = Yext::KnowledgeApi::KnowledgeManager::Location.new(account_id: child_account_id, id: location_id)
80
+ # location.add_services! skus: [sku]
81
+ scope(:add_services!, lambda do |location_update_hash = {}|
82
+ args = scope_args(true)
83
+
84
+ args.merge!(location_update_hash)
85
+
86
+ Yext::Api::AdministrativeApi::Account.
87
+ where(args).
88
+ with(:existinglocationaddrequests).
89
+ post
90
+ end)
91
+
92
+ def save
93
+ if persisted?
94
+ change_status
95
+ else
96
+ create_new_location
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def create_new_location
103
+ scope.
104
+ with(Yext::Api::Concerns::AccountChild.with_account_path("newlocationaddrequests")).
105
+ where(attributes.reverse_merge(account_id: Yext::Api.configuration.param_account_id)).
106
+ post
107
+ end
108
+
109
+ def change_status
110
+ scope.
111
+ with(Yext::Api::Concerns::AccountChild.with_account_path("processaddrequest")).
112
+ where(addRequestId: id, status: status).
113
+ post
114
+ end
31
115
  end
32
116
  end
33
117
  end
@@ -11,27 +11,49 @@ module Yext
11
11
  # :endpoint: https://api.yext.com/v2/accounts/{accountId}/availableservices
12
12
  # :default_version: 20161012
13
13
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAvailableServices
14
- # :comment: Return list of services available to you under your agreements.
15
14
  # :sandbox_only: false
16
15
  # - :action: :index
17
16
  # :method: :get
18
17
  # :endpoint: https://api.yext.com/v2/accounts/{accountId}/services
19
18
  # :default_version: 20161012
20
19
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listServices
21
- # :comment: Retrieve a list of all services provisioned through this account.
22
20
  # :sandbox_only: false
23
21
  # - :action: :destroy
24
22
  # :method: :post
25
23
  # :endpoint: https://api.yext.com/v2/accounts/{accountId}/cancelservices
26
24
  # :default_version: 20161012
27
25
  # :documentation: http://developer.yext.com/docs/administrative-api/#operation/cancelServices
28
- # :comment: Cancel one or more active services.
29
26
  # :sandbox_only: false
30
27
  class Service < Yext::Api::Utils::ApiBase
31
28
  include Yext::Api::Concerns::AccountChild
32
29
 
33
30
  scope :available, -> { with(Yext::Api::Concerns::AccountChild.with_account_path("availableservices")) }
34
- scope :cancel_services, -> { with(Yext::Api::Concerns::AccountChild.with_account_path("cancelservices")) }
31
+
32
+ # A method as scope to cancel services for a location. This feature is here because it is documented
33
+ # in the AdministrativeApi as basically a method on the Service concept.
34
+ #
35
+ # The Location contains an instance method to do this without having to pass in the
36
+ # arguments hash:
37
+ #
38
+ # Some examples of ways to add services:
39
+ # Yext::Api::AdministrativeApi::Service.cancel_services! locationId: location_id
40
+ # skus: [sku]
41
+ #
42
+ # location = Yext::KnowledgeApi::KnowledgeManager::Location.account(child_account_id).find(location_id)
43
+ # location.cancel_services! skus: [sku]
44
+ #
45
+ # location = Yext::KnowledgeApi::KnowledgeManager::Location.new(id: location_id)
46
+ # location.cancel_services! skus: [sku]
47
+ scope(:cancel_services!, lambda do |cancel_hash|
48
+ args = scope_args(true)
49
+
50
+ args.merge!(cancel_hash)
51
+
52
+ Yext::Api::AdministrativeApi::Account.
53
+ where(args).
54
+ with(:cancelservices).
55
+ post
56
+ end)
35
57
  end
36
58
  end
37
59
  end
@@ -9,7 +9,7 @@ module Yext
9
9
  # * Global configuration:
10
10
  # * Yext::Api.configuration.account_id = new_account_id
11
11
  # * For an individual call:
12
- # * SpykeClass.with_account(new_account_id)
12
+ # * SpykeClass.account(new_account_id)
13
13
  # * SpykeClass.where(account_id: new_account_id)
14
14
  #
15
15
  # NOTE: This will not work if the DefaultParameters middleware is not being used.
@@ -26,7 +26,7 @@ module Yext
26
26
 
27
27
  def ensure_relation(klass)
28
28
  [Yext::Api::KnowledgeApi::AccountSettings::Account, Yext::Api::AdministrativeApi::Account].each do |account_class|
29
- next if account_class.instance_methods.include?("#{klass.model_name.element}_ids".to_sym)
29
+ next if account_class.association?(klass)
30
30
 
31
31
  klass_uri = klass.instance_variable_get(:@uri)
32
32
  helper_warnings(account_class, klass, klass_uri)
@@ -36,11 +36,17 @@ module Yext
36
36
  end
37
37
  end
38
38
 
39
+ def association_name(klass)
40
+ association_name = klass.parents.include?(Yext::Api::LiveApi) ? "live_" : ""
41
+
42
+ association_name + klass.model_name.element.pluralize
43
+ end
44
+
39
45
  private
40
46
 
41
47
  def add_has_many_relation(account_class, klass, klass_uri)
42
48
  account_class.class_eval do
43
- has_many klass.model_name.element.pluralize.to_sym,
49
+ has_many Yext::Api::Concerns::AccountChild.association_name(klass).to_sym,
44
50
  class_name: klass.name,
45
51
  uri: Yext::Api::Concerns::AccountChild.with_account_path(klass_uri)
46
52
  end
@@ -48,7 +54,7 @@ module Yext
48
54
 
49
55
  def helper_warnings(account_class, klass, klass_uri)
50
56
  klass_name = klass.name
51
- relation_name = klass.model_name.element.pluralize
57
+ relation_name = Yext::Api::Concerns::AccountChild.association_name(klass)
52
58
 
53
59
  puts "WARNING! #{account_class.name} does not include the relationship for #{klass_name}"
54
60
  puts " Add the following line to Yext::Api::Concerns::AccountRelations:"
@@ -63,13 +69,13 @@ module Yext
63
69
  end
64
70
 
65
71
  included do
66
- scope(:with_account, lambda do |account_or_id|
72
+ scope(:account, lambda do |account_or_id|
67
73
  if account_or_id.is_a?(Yext::Api::KnowledgeApi::AccountSettings::Account) ||
68
74
  account_or_id.is_a?(Yext::Api::AdministrativeApi::Account)
69
75
  account_or_id
70
76
  else
71
77
  Yext::Api::KnowledgeApi::AccountSettings::Account.new(id: account_or_id)
72
- end.public_send(model_name.element.pluralize)
78
+ end.public_send(Yext::Api::Concerns::AccountChild.association_name(self))
73
79
  end)
74
80
 
75
81
  Yext::Api::Concerns::AccountChild.ensure_relation(self)
@@ -79,12 +85,35 @@ module Yext
79
85
  def all
80
86
  if current_scope.nil?
81
87
  Yext::Api::KnowledgeApi::AccountSettings::Account.
82
- new(id: Yext::Api.configuration.account_id || "me").
83
- public_send(model_name.element.pluralize)
88
+ new(id: Yext::Api.configuration.param_account_id).
89
+ public_send(Yext::Api::Concerns::AccountChild.association_name(self))
84
90
  else
85
91
  current_scope
86
92
  end
87
93
  end
94
+
95
+ def reset_uri
96
+ [Yext::Api::KnowledgeApi::AccountSettings::Account, Yext::Api::AdministrativeApi::Account].each do |account_class|
97
+ next unless account_class.association?(self)
98
+
99
+ klass_uri = instance_variable_get(:@uri) || default_uri
100
+
101
+ account_class.
102
+ new.
103
+ send(Yext::Api::Concerns::AccountChild.association_name(self)).
104
+ with(Yext::Api::Concerns::AccountChild.with_account_path(klass_uri))
105
+ end
106
+ end
107
+
108
+ def scope_args(account_scope = false)
109
+ args = current_scope&.params&.dup || {}
110
+
111
+ args[:account_id] ||= Yext::Api.configuration.param_account_id
112
+
113
+ args[:id] = args.delete(:account_id) if account_scope
114
+
115
+ args
116
+ end
88
117
  end
89
118
  end
90
119
  end
@@ -13,11 +13,26 @@ module Yext
13
13
  # The module AccountChild will add these relations if they are missing, but if they are
14
14
  # listed explicitly it is more efficient.
15
15
  included do
16
+ # AdministrativeApi
16
17
  has_many :add_requests,
17
18
  class_name: "Yext::Api::AdministrativeApi::AddRequest",
18
19
  uri: Yext::Api::Concerns::AccountChild.with_account_path("addrequests/(:id)")
19
- has_many :locations, class_name: "Yext::Api::KnowledgeApi::KnowledgeManager::Location"
20
20
  has_many :services, class_name: "Yext::Api::AdministrativeApi::Service"
21
+
22
+ # KnowledgeApi::KnowledgeManager
23
+ has_many :locations, class_name: "Yext::Api::KnowledgeApi::KnowledgeManager::Location"
24
+
25
+ # KnowledgeApi::AccountSettings
26
+ has_many :users, class_name: "Yext::Api::KnowledgeApi::AccountSettings::User"
27
+
28
+ # LiveApi
29
+ has_many :live_locations, class_name: "Yext::Api::LiveApi::Location"
30
+ end
31
+
32
+ class_methods do
33
+ def association?(klass)
34
+ associations.key?(Yext::Api::Concerns::AccountChild.association_name(klass).to_sym)
35
+ end
21
36
  end
22
37
  end
23
38
  end
@@ -12,8 +12,8 @@ module Yext
12
12
  extend ActiveSupport::Concern
13
13
 
14
14
  included do
15
- scope(:with_version, ->(version) { where(v: version) })
16
- scope(:with_application, ->(app_id) { where(api_key: app_id) })
15
+ scope(:version, ->(version) { where(v: version) })
16
+ scope(:application, ->(app_id) { where(api_key: app_id) })
17
17
  scope(:yext_username, ->(username) { where(yext_username: username) })
18
18
  scope(:yext_user_id, ->(user_id) { where(yext_user_id: user_id) })
19
19
 
@@ -31,6 +31,12 @@ module Yext
31
31
  where(validation: validation)
32
32
  end)
33
33
  end
34
+
35
+ class_methods do
36
+ def reset_uri
37
+ # do nothing.
38
+ end
39
+ end
34
40
  end
35
41
  end
36
42
  end
@@ -28,15 +28,29 @@ module Yext
28
28
  end
29
29
  end
30
30
 
31
- def self.faraday_connection(url)
32
- Faraday.new(url: url) do |c|
33
- c.request :json
31
+ class << self
32
+ def faraday_connection(url)
33
+ Faraday.new(url: url) do |c|
34
+ c.request :json
35
+ c.request :retry,
36
+ max: 2,
37
+ interval: 0.05,
38
+ interval_randomness: 0.5,
39
+ backoff_factor: 2
34
40
 
35
- c.use Yext::Api::Utils::ResponseParser
36
- c.use Yext::Api::Utils::DefaultParameters
37
- c.use Yext::Api::Utils::ApiRateLimits
41
+ add_middleware(c)
38
42
 
39
- c.adapter Faraday.default_adapter
43
+ c.adapter Faraday.default_adapter
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def add_middleware(c)
50
+ c.use Yext::Api::Utils::Middleware::ResponseParser
51
+ c.use Yext::Api::Utils::Middleware::DefaultParameters
52
+ c.use Yext::Api::Utils::Middleware::ApiRateLimits
53
+ c.use Yext::Api::Utils::Middleware::UriCleanup
40
54
  end
41
55
  end
42
56
  end
@@ -10,7 +10,14 @@ module Yext
10
10
  :rate_limit_limit,
11
11
  :rate_limit_reset_at,
12
12
  :last_status,
13
- :last_meta
13
+ :last_meta,
14
+ :last_data
15
+
16
+ private
17
+
18
+ def last_data=(last_data)
19
+ @last_data = last_data
20
+ end
14
21
 
15
22
  def last_status=(last_status)
16
23
  @last_status = last_status