Class: ShopifyAPI::Rest::Base

Inherits:
Object
  • Object
show all
Extended by:
T::Helpers, T::Sig
Defined in:
lib/shopify_api/rest/base.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(session: nil, from_hash: nil) ⇒ Base

Returns a new instance of Base.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/shopify_api/rest/base.rb', line 31

def initialize(session: nil, from_hash: nil)
  @original_state = T.let({}, T::Hash[Symbol, T.untyped])
  @custom_prefix = T.let(nil, T.nilable(String))
  @forced_nils = T.let({}, T::Hash[String, T::Boolean])

  session ||= ShopifyAPI::Context.active_session

  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)

  @session = T.let(T.must(session), Auth::Session)
  @client = T.let(client, Clients::Rest::Admin)
  @errors = T.let(Rest::BaseErrors.new, Rest::BaseErrors)

  from_hash&.each do |key, value|
    instance_variable_set("@#{key}", value)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth_id, val = nil) ⇒ Object



238
239
240
241
242
243
244
245
246
247
# File 'lib/shopify_api/rest/base.rb', line 238

def method_missing(meth_id, val = nil)
  match = meth_id.id2name.match(/([^=]+)=/)

  return super unless match

  var = match[1]

  instance_variable_set("@#{var}", val)
  @forced_nils[T.must(var)] = val.nil?
end

Class Attribute Details

.custom_prefixObject (readonly)

Returns the value of attribute custom_prefix.



53
54
55
# File 'lib/shopify_api/rest/base.rb', line 53

def custom_prefix
  @custom_prefix
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



23
24
25
# File 'lib/shopify_api/rest/base.rb', line 23

def errors
  @errors
end

#original_stateObject

Returns the value of attribute original_state.



20
21
22
# File 'lib/shopify_api/rest/base.rb', line 20

def original_state
  @original_state
end

Class Method Details

.base_find(session: nil, ids: {}, params: {}) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/shopify_api/rest/base.rb', line 62

def base_find(session: nil, ids: {}, params: {})
  session ||= ShopifyAPI::Context.active_session

  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)

  path = T.must(get_path(http_method: :get, operation: :get, ids: ids))
  response = client.get(path: path, query: params.compact)

  instance_variable_get(:"@prev_page_info").value = response.prev_page_info
  instance_variable_get(:"@next_page_info").value = response.next_page_info

  create_instances_from_response(response: response, session: T.must(session))
end

.class_nameObject



77
78
79
# File 'lib/shopify_api/rest/base.rb', line 77

def class_name
  T.must(name).demodulize.underscore
end

.create_instance(data:, session:, instance: nil) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/shopify_api/rest/base.rb', line 208

def create_instance(data:, session:, instance: nil)
  instance ||= new(session: session)
  instance.original_state = {}

  unless data.empty?
    # This retrieves all the setters on the resource and calls them with the data
    instance_methods(false).select { |method| !method.to_s.include?("=") }.each do |attribute|
      next unless data.key?(attribute.to_s)

      if has_many?(attribute) && data[attribute.to_s]
        attr_list = []
        data[attribute.to_s].each do |element|
          attr_list << T.unsafe(@has_many[attribute]).create_instance(data: element, session: session)
        end
        instance.public_send("#{attribute}=", attr_list)
      elsif has_one?(attribute) && data[attribute.to_s]
        instance.public_send("#{attribute}=",
          T.unsafe(@has_one[attribute]).create_instance(data: data[attribute.to_s], session: session))
      else
        instance.public_send("#{attribute}=", data[attribute.to_s])
        instance.original_state[attribute] = data[attribute.to_s]
      end
    end
  end

  instance
end

.create_instances_from_response(response:, session:) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/shopify_api/rest/base.rb', line 189

def create_instances_from_response(response:, session:)
  objects = []

  body = T.cast(response.body, T::Hash[String, T.untyped])

  if body.key?(class_name.pluralize) || (body.key?(class_name) && body[class_name].is_a?(Array))
    (body[class_name.pluralize] || body[class_name]).each do |entry|
      objects << create_instance(data: entry, session: session)
    end
  elsif body.key?(class_name)
    objects << create_instance(data: body[class_name], session: session)
  end

  objects
end

.get_path(http_method:, operation:, entity: nil, ids: {}) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/shopify_api/rest/base.rb', line 129

def get_path(http_method:, operation:, entity: nil, ids: {})
  match = T.let(nil, T.nilable(String))
  max_ids = T.let(-1, Integer)
  @paths.each do |path|
    next if http_method != path[:http_method] || operation != path[:operation]

    path_ids = T.cast(path[:ids], T::Array[Symbol])

    url_ids = ids.transform_keys(&:to_sym)
    path_ids.each do |id|
      if url_ids[id].nil? && (entity_id = entity&.public_send(id))
        url_ids[id] = entity_id
      end
    end

    url_ids.compact!

    # We haven't found all the required ids or we have a more specific match
    next if !(path_ids - url_ids.keys).empty? || path_ids.length <= max_ids

    max_ids = path_ids.length
    match = T.cast(path[:path], String).gsub(/(<([^>]+)>)/) do
      url_ids[T.unsafe(Regexp.last_match)[2].to_sym]
    end
  end

  custom_prefix ? "#{T.must(custom_prefix).sub(%r{\A/}, "")}/#{match}" : match
end

.has_many?(attribute) ⇒ Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/shopify_api/rest/base.rb', line 112

def has_many?(attribute)
  @has_many.include?(attribute)
end

.has_one?(attribute) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/shopify_api/rest/base.rb', line 117

def has_one?(attribute)
  @has_one.include?(attribute)
end

.json_body_nameObject



87
88
89
# File 'lib/shopify_api/rest/base.rb', line 87

def json_body_name
  class_name.underscore
end

.next_page?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/shopify_api/rest/base.rb', line 107

def next_page?
  !instance_variable_get(:"@next_page_info").value.nil?
end

.next_page_infoObject



97
98
99
# File 'lib/shopify_api/rest/base.rb', line 97

def next_page_info
  instance_variable_get(:"@next_page_info").value
end

.prev_page?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/shopify_api/rest/base.rb', line 102

def prev_page?
  !instance_variable_get(:"@prev_page_info").value.nil?
end

.prev_page_infoObject



92
93
94
# File 'lib/shopify_api/rest/base.rb', line 92

def prev_page_info
  instance_variable_get(:"@prev_page_info").value
end

.primary_keyObject



82
83
84
# File 'lib/shopify_api/rest/base.rb', line 82

def primary_key
  "id"
end

.request(http_method:, operation:, session:, ids: {}, params: {}, body: nil, entity: nil) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/shopify_api/rest/base.rb', line 169

def request(http_method:, operation:, session:, ids: {}, params: {}, body: nil, entity: nil)
  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)

  path = get_path(http_method: http_method, operation: operation.to_sym, ids: ids)

  case http_method
  when :get
    client.get(path: T.must(path), query: params.compact)
  when :post
    client.post(path: T.must(path), query: params.compact, body: body || {})
  when :put
    client.put(path: T.must(path), query: params.compact, body: body || {})
  when :delete
    client.delete(path: T.must(path), query: params.compact)
  else
    raise Errors::InvalidHttpRequestError, "Invalid HTTP method: #{http_method}"
  end
end

Instance Method Details

#delete(params: {}) ⇒ Object



278
279
280
281
282
283
284
285
286
# File 'lib/shopify_api/rest/base.rb', line 278

def delete(params: {})
  @client.delete(
    path: T.must(self.class.get_path(http_method: :delete, operation: :delete, entity: self)),
    query: params.compact
  )
rescue ShopifyAPI::Errors::HttpResponseError => e
  @errors.errors << e
  raise
end

#respond_to_missing?(meth_id, *args) ⇒ Boolean

Returns:

  • (Boolean)


250
251
252
253
254
255
# File 'lib/shopify_api/rest/base.rb', line 250

def respond_to_missing?(meth_id, *args)
  str = meth_id.id2name
  match = str.match(/([^=]+)=/)

  match.nil? ? true : super
end

#save(update_object: false) ⇒ Object



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/shopify_api/rest/base.rb', line 294

def save(update_object: false)
  hash = HashDiff::Comparison.new(original_state, to_hash).left_diff
  method = hash[self.class.primary_key] ? :put : :post

  path = self.class.get_path(http_method: method, operation: method, entity: self)
  if path.nil?
    method = method == :post ? :put : :post
    path = self.class.get_path(http_method: method, operation: method, entity: self)
  end

  response = @client.public_send(method, body: { self.class.json_body_name => hash }, path: path)

  if update_object
    self.class.create_instance(
      data: response.body[self.class.class_name.downcase],
      session: @session, instance: self
    )
  end
rescue ShopifyAPI::Errors::HttpResponseError => e
  @errors.errors << e
  raise
end

#save!Object



289
290
291
# File 'lib/shopify_api/rest/base.rb', line 289

def save!
  save(update_object: true)
end

#to_hashObject



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/shopify_api/rest/base.rb', line 258

def to_hash
  hash = {}
  instance_variables.each do |var|
    next if [:"@original_state", :"@session", :"@client", :"@forced_nils", :"@errors"].include?(var)

    attribute = var.to_s.delete("@").to_sym
    if self.class.has_many?(attribute)
      hash[attribute.to_s] = instance_variable_get(var).map(&:to_hash).to_a if instance_variable_get(var)
    elsif self.class.has_one?(attribute)
      element_hash = instance_variable_get(var)&.to_hash
      hash[attribute.to_s] = element_hash if element_hash || @forced_nils[attribute.to_s]
    elsif !instance_variable_get(var).nil? || @forced_nils[attribute.to_s]
      hash[attribute.to_s] =
        instance_variable_get(var)
    end
  end
  hash
end