Class: Api::ReviewsIo::Client

Inherits:
Object
  • Object
show all
Defined in:
app/services/api/reviews_io/client.rb

Overview

Thin HTTP client for interacting with the Reviews.io API.

Defined Under Namespace

Classes: Error, MissingCredentialsError

Constant Summary collapse

INVITATION_PATH =

Filesystem/URL path for invitation.

'/invitation'
PRODUCT_RATING_BATCH_PATH =

Filesystem/URL path for product rating batch.

'/product/rating-batch'
REVIEWS_PATH =

Filesystem/URL path for reviews.

'/reviews'
MERCHANT_REVIEWS_PATH =

Filesystem/URL path for merchant reviews.

'/merchant/reviews'
DEFAULT_TIMEOUT =

seconds

15

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(store_id: nil, api_key: nil, base_url: nil, http: nil, logger: Rails.logger) ⇒ Client

Returns a new instance of Client.



25
26
27
28
29
30
31
32
33
# File 'app/services/api/reviews_io/client.rb', line 25

def initialize(store_id: nil, api_key: nil, base_url: nil, http: nil, logger: Rails.logger)
  @logger = logger
  @store_id = store_id || env_or_config(:store_id)
  @api_key = api_key || env_or_config(:api_key)
  @base_url = base_url || env_or_config(:api_url)
  @http = http || default_http_client

  validate_credentials!
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



23
24
25
# File 'app/services/api/reviews_io/client.rb', line 23

def api_key
  @api_key
end

#base_urlObject (readonly)

Returns the value of attribute base_url.



23
24
25
# File 'app/services/api/reviews_io/client.rb', line 23

def base_url
  @base_url
end

#httpObject (readonly)

Returns the value of attribute http.



23
24
25
# File 'app/services/api/reviews_io/client.rb', line 23

def http
  @http
end

#loggerObject (readonly)

Returns the value of attribute logger.



23
24
25
# File 'app/services/api/reviews_io/client.rb', line 23

def logger
  @logger
end

#store_idObject (readonly)

Returns the value of attribute store_id.



23
24
25
# File 'app/services/api/reviews_io/client.rb', line 23

def store_id
  @store_id
end

Instance Method Details

#fetch_product_ratings(skus) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'app/services/api/reviews_io/client.rb', line 44

def fetch_product_ratings(skus)
  normalized_skus = normalize_skus(skus)
  return {} if normalized_skus.empty?

  response = perform_rating_request(normalized_skus)
  log_debug("Reviews.io rating response: status=#{response.status}, body=#{safe_body(response)}")
  ensure_success!(response)
  parse_response(response)
rescue HTTP::Error => e
  raise Error, "Reviews.io request failed: #{e.message}"
rescue JSON::ParserError => e
  raise Error, "Reviews.io response parse failed: #{e.message}"
end

#fetch_reviews_by_email(email, options = {}) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/services/api/reviews_io/client.rb', line 68

def fetch_reviews_by_email(email, options = {})
  raise ArgumentError, 'Email is required' if email.blank?
  raise MissingCredentialsError, 'API key is required for email filtering' if api_key.blank?

  query = reviews_query_params(options).merge(
    store: store_id,
    email: email.strip,
    apikey: api_key
  )

  response = http.headers(rating_headers).get(reviews_url, params: query)
  log_debug("Reviews.io reviews by email response: status=#{response.status}, body=#{safe_body(response)}")
  ensure_success!(response)

  parsed = parse_response(response)
  parsed.is_a?(Hash) ? parsed : { 'data' => parsed }
rescue HTTP::Error => e
  raise Error, "Reviews.io request failed: #{e.message}"
rescue JSON::ParserError => e
  raise Error, "Reviews.io response parse failed: #{e.message}"
end

#fetch_reviews_by_tag(tag, options = {}) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/services/api/reviews_io/client.rb', line 90

def fetch_reviews_by_tag(tag, options = {})
  raise ArgumentError, 'Tag is required' if tag.blank?

  query = reviews_query_params(options).merge(
    store: store_id,
    tag: tag.strip,
    apikey: api_key
  )

  response = http.headers(rating_headers).get(reviews_url, params: query)
  log_debug("Reviews.io reviews by tag response: status=#{response.status}, body=#{safe_body(response)}")
  ensure_success!(response)

  parsed = parse_response(response)
  parsed.is_a?(Hash) ? parsed : { 'data' => parsed }
rescue HTTP::Error => e
  raise Error, "Reviews.io request failed: #{e.message}"
rescue JSON::ParserError => e
  raise Error, "Reviews.io response parse failed: #{e.message}"
end

#fetch_reviews_for_sku(sku, options = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'app/services/api/reviews_io/client.rb', line 58

def fetch_reviews_for_sku(sku, options = {})
  normalized_sku = normalize_review_sku(sku)
  response = perform_reviews_request(normalized_sku, options)
  build_reviews_payload(response, normalized_sku)
rescue HTTP::Error => e
  raise Error, "Reviews.io request failed: #{e.message}"
rescue JSON::ParserError => e
  raise Error, "Reviews.io response parse failed: #{e.message}"
end

#queue_invitation(payload) ⇒ Object



35
36
37
38
39
40
41
42
# File 'app/services/api/reviews_io/client.rb', line 35

def queue_invitation(payload)
  response = http.headers(default_headers)
                 .post(invitation_url, json: payload)
  log_debug("Reviews.io invitation response: status=#{response.status}, body=#{safe_body(response)}")
  response
rescue HTTP::Error => e
  raise Error, "Reviews.io request failed: #{e.message}"
end