yext-api 0.1.1 → 0.1.3

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