e_plat 0.3.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +631 -131
  3. data/lib/active_resource/connection_error.rb +29 -0
  4. data/lib/active_resource/formats.rb +27 -0
  5. data/lib/current.rb +1 -1
  6. data/lib/e_plat/client/default_request_args.rb +27 -3
  7. data/lib/e_plat/client.rb +114 -87
  8. data/lib/e_plat/connection.rb +4 -0
  9. data/lib/e_plat/mapping/base.rb +119 -12
  10. data/lib/e_plat/mapping/bigcommerce/v_3/metafield.rb +62 -0
  11. data/lib/e_plat/mapping/bigcommerce/v_3/order/billing_address.rb +14 -0
  12. data/lib/e_plat/mapping/bigcommerce/v_3/order/line_item.rb +85 -0
  13. data/lib/e_plat/mapping/bigcommerce/v_3/order/shipping_address.rb +73 -0
  14. data/lib/e_plat/mapping/bigcommerce/v_3/order.rb +160 -0
  15. data/lib/e_plat/mapping/bigcommerce/v_3/product/image.rb +12 -12
  16. data/lib/e_plat/mapping/bigcommerce/v_3/product/variant.rb +1 -1
  17. data/lib/e_plat/mapping/bigcommerce/v_3/script_tag.rb +78 -0
  18. data/lib/e_plat/mapping/bigcommerce/v_3/shop.rb +11 -6
  19. data/lib/e_plat/mapping/bigcommerce/v_3/webhook.rb +54 -0
  20. data/lib/e_plat/mapping/request_body_root.rb +38 -0
  21. data/lib/e_plat/mapping/shopify/v_2024_01/metafield.rb +26 -0
  22. data/lib/e_plat/mapping/shopify/v_2024_01/order/billing_address.rb +14 -0
  23. data/lib/e_plat/mapping/shopify/v_2024_01/order/shipping_address.rb +30 -0
  24. data/lib/e_plat/mapping/shopify/{v_2022_07/product.rb → v_2024_01/order.rb} +3 -3
  25. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/product/image.rb +1 -1
  26. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/product/variant.rb +2 -1
  27. data/lib/e_plat/mapping/shopify/v_2024_01/product.rb +26 -0
  28. data/lib/e_plat/mapping/shopify/v_2024_01/script_tag.rb +26 -0
  29. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/shop.rb +1 -1
  30. data/lib/e_plat/mapping/shopify/v_2024_01/webhook.rb +29 -0
  31. data/lib/e_plat/mapping/virtual_collection/base.rb +14 -0
  32. data/lib/e_plat/mapping/virtual_collection/bigcommerce/order_line_items.rb +297 -0
  33. data/lib/e_plat/mapping.rb +3 -3
  34. data/lib/e_plat/resource/attribute_interface.rb +28 -28
  35. data/lib/e_plat/resource/base.rb +107 -66
  36. data/lib/e_plat/resource/collection.rb +92 -0
  37. data/lib/e_plat/resource/concerns/aliases.rb +102 -18
  38. data/lib/e_plat/resource/concerns/dirty.rb +54 -0
  39. data/lib/e_plat/resource/concerns/metafieldable.rb +43 -0
  40. data/lib/e_plat/resource/concerns/overwrite_instance_methods.rb +108 -6
  41. data/lib/e_plat/resource/concerns/overwrite_request_methods.rb +73 -37
  42. data/lib/e_plat/resource/countable.rb +43 -0
  43. data/lib/e_plat/resource/metafield.rb +70 -0
  44. data/lib/e_plat/resource/order/Consignment.rb +8 -0
  45. data/lib/e_plat/resource/order/billing_address.rb +6 -0
  46. data/lib/e_plat/resource/order/fulfillment.rb +1 -0
  47. data/lib/e_plat/resource/order/line_item.rb +1 -0
  48. data/lib/e_plat/resource/order/shipping_address.rb +44 -0
  49. data/lib/e_plat/resource/order/shipping_line.rb +15 -14
  50. data/lib/e_plat/resource/order.rb +32 -0
  51. data/lib/e_plat/resource/paginated/link_headers.rb +42 -0
  52. data/lib/e_plat/resource/paginated/link_params.rb +26 -0
  53. data/lib/e_plat/resource/product/image.rb +6 -0
  54. data/lib/e_plat/resource/product/option.rb +1 -0
  55. data/lib/e_plat/resource/product/variant.rb +8 -12
  56. data/lib/e_plat/resource/product.rb +8 -2
  57. data/lib/e_plat/resource/script_tag.rb +56 -0
  58. data/lib/e_plat/resource/shop.rb +17 -13
  59. data/lib/e_plat/resource/shopify_only/recurring_application_charge/usage_charge.rb +32 -0
  60. data/lib/e_plat/resource/shopify_only/recurring_application_charge.rb +47 -0
  61. data/lib/e_plat/resource/webhook.rb +50 -0
  62. data/lib/e_plat/session.rb +10 -7
  63. data/lib/e_plat/type_coercer.rb +15 -17
  64. data/lib/e_plat/version.rb +1 -1
  65. data/lib/e_plat.rb +14 -4
  66. metadata +67 -7
  67. data/lib/e_plat/resource/order/customer.rb +0 -37
@@ -0,0 +1,29 @@
1
+ module EPlat
2
+ class Mapping
3
+ module Shopify
4
+ module V202401 #< :module
5
+ class Webhook < EPlat::Mapping::Base
6
+ DEFAULT_VALUES = {
7
+ format: "json"
8
+ }
9
+
10
+ def native_top_key
11
+ "webhook"
12
+ end
13
+
14
+ def native_attributes
15
+ super.concat([
16
+ ])
17
+ end
18
+
19
+ def native_attribute_aliases
20
+ super.concat([
21
+ ])
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,14 @@
1
+
2
+ module EPlat
3
+ class Mapping
4
+ class VirtualCollection::Base
5
+ attr_accessor :resource
6
+ # useful for adding an interface that gets and sets from nested attributes accross nested resources
7
+ # for example a order.line_items collection that is aliased to attributes in both order.consignments[0].shipping and order.consignments[0].shipping.line_items
8
+
9
+ def initialize(resource:, map_from:)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,297 @@
1
+
2
+ module EPlat
3
+ class Mapping
4
+ module VirtualCollection
5
+ module Bigcommerce
6
+ class OrderLineItems < VirtualCollection::Base
7
+ attr_accessor :resource
8
+ # will create an array of EPlat::Order::LineItem objects with no proper attributes, only aliases
9
+ # i.e. e_plat_key will always be virtual, whilst the native key will point to a proper attributes other resources
10
+ # Order line_items do actually exist in BigCommerce, but they're in a much deeper level of the JSON that order.line_items
11
+ # Using a virtual collection, allows us to treat the line_items as if they were in the proper position: order.line_items
12
+
13
+ def initialize(resource:, map_from:)
14
+ @resource = resource
15
+ super
16
+
17
+ return unless @resource.try :consignments #map_from
18
+
19
+ @resource.line_items =
20
+ (@resource.consignments[0].try(:shipping).presence || @resource.consignments[0].try(:pickups))&.first&.line_items.map.with_index do |data, i|
21
+ item = EPlat::Order::LineItem.new(order_id: @resource.id)
22
+ item.mapping.virtual_collection = self
23
+ item.add_aliases!(native_attribute_aliases(i), EPlat::Order::LineItem.schema)
24
+
25
+ item
26
+ end
27
+ end
28
+
29
+ def native_attribute_aliases(i)
30
+ [
31
+ {
32
+ alias_attribute: {
33
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][id]",
34
+ e_plat_key: "id",
35
+ virtual_collection: true
36
+ }
37
+ },
38
+ {
39
+ alias_attribute: {
40
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][variant_id]",
41
+ e_plat_key: "variant_id",
42
+ virtual_collection: true
43
+ }
44
+ },
45
+ {
46
+ alias_attribute: {
47
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][name]",
48
+ e_plat_key: "name",
49
+ virtual_collection: true
50
+ }
51
+ },
52
+ {
53
+ alias_attribute: {
54
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][price]",
55
+ e_plat_key: "price",
56
+ virtual_collection: true
57
+ }
58
+ },
59
+ {
60
+ alias_attribute: {
61
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][product_id]",
62
+ e_plat_key: "product_id",
63
+ virtual_collection: true
64
+ }
65
+ },
66
+ {
67
+ alias_attribute: {
68
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][quantity]",
69
+ e_plat_key: "quantity",
70
+ virtual_collection: true
71
+ }
72
+ },
73
+ {
74
+ alias_attribute: {
75
+ native_key: "[consignments][0][shipping][0][line_items][#{i}][sku]",
76
+ e_plat_key: "sku",
77
+ virtual_collection: true
78
+ }
79
+ },
80
+ ]
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+
90
+
91
+ # consignments are deliveries, we're just going to operate within the context on one delivery per order
92
+ # this should be reasonable to tie us over for now
93
+
94
+ # integer :id
95
+ # string :admin_graphql_api_id
96
+ # integer :fulfillable_quantity
97
+ # string :fulfillment_service
98
+ # string :fulfillment_status
99
+ # boolean :gift_card
100
+ # integer :grams
101
+ # string :name
102
+ # string :price
103
+ # hash :price_set
104
+ # boolean :product_exists
105
+ # integer :product_id
106
+ # array :properties
107
+ # integer :quantity
108
+ # boolean :requires_shipping
109
+ # string :sku
110
+ # boolean :taxable
111
+ # string :title
112
+ # string :total_discount
113
+ # hash :total_discount_set
114
+ # integer :variant_id
115
+ # string :variant_inventory_management
116
+ # string :variant_title
117
+ # string :vendor
118
+ # array :tax_lines
119
+ # array :duties
120
+ # array :discount_allocations
121
+
122
+
123
+ # BG = {
124
+ # "consignments": [
125
+ # {
126
+ # "pickups": [],
127
+ # "shipping": [
128
+ # {
129
+ # "id": 3,
130
+ # "first_name": "Jane",
131
+ # "last_name": "Doe",
132
+ # "company": "",
133
+ # "street_1": "123 Main Street",
134
+ # "street_2": "",
135
+ # "city": "Austin",
136
+ # "zip": "78751",
137
+ # "country": "United States",
138
+ # "country_iso2": "US",
139
+ # "state": "Texas",
140
+ # "email": "oli@example.com",
141
+ # "phone": "",
142
+ # "form_fields": [],
143
+ # "line_items": [
144
+ # {
145
+ # "id": 3,
146
+ # "order_id": 102,
147
+ # "product_id": 88,
148
+ # "variant_id": 81,
149
+ # "order_pickup_method_id": 0,
150
+ # "order_address_id": 3,
151
+ # "name": "Chemex Coffeemaker",
152
+ # "name_customer": "Chemex Coffeemaker",
153
+ # "name_merchant": "Chemex Coffeemaker",
154
+ # "sku": "CC3C-SM",
155
+ # "upc": "",
156
+ # "type": "physical",
157
+ # "base_price": "83.3300",
158
+ # "price_ex_tax": "83.3300",
159
+ # "price_inc_tax": "83.3300",
160
+ # "price_tax": "0.0000",
161
+ # "base_total": "83.3300",
162
+ # "total_ex_tax": "83.3300",
163
+ # "total_inc_tax": "83.3300",
164
+ # "total_tax": "0.0000",
165
+ # "weight": "1.0000",
166
+ # "width": "0.0000",
167
+ # "height": "0.0000",
168
+ # "depth": "0.0000",
169
+ # "quantity": 1,
170
+ # "base_cost_price": "0.0000",
171
+ # "cost_price_inc_tax": "0.0000",
172
+ # "cost_price_ex_tax": "0.0000",
173
+ # "cost_price_tax": "0.0000",
174
+ # "is_refunded": false,
175
+ # "quantity_refunded": 0,
176
+ # "refund_amount": "0.0000",
177
+ # "return_id": 0,
178
+ # "wrapping_id": 0,
179
+ # "wrapping_name": "",
180
+ # "base_wrapping_cost": "0.0000",
181
+ # "wrapping_cost_ex_tax": "0.0000",
182
+ # "wrapping_cost_inc_tax": "0.0000",
183
+ # "wrapping_cost_tax": "0.0000",
184
+ # "wrapping_message": "",
185
+ # "quantity_shipped": 0,
186
+ # "event_name": null,
187
+ # "event_date": null,
188
+ # "fixed_shipping_cost": "0.0000",
189
+ # "ebay_item_id": "",
190
+ # "ebay_transaction_id": "",
191
+ # "option_set_id": 18,
192
+ # "parent_order_product_id": null,
193
+ # "is_bundled_product": false,
194
+ # "bin_picking_number": "0",
195
+ # "external_id": "",
196
+ # "fulfillment_source": "",
197
+ # "brand": "",
198
+ # "gift_certificate_id": null,
199
+ # "applied_discounts": [],
200
+ # "product_options": [
201
+ # {
202
+ # "id": 2,
203
+ # "option_id": 34,
204
+ # "order_product_id": 3,
205
+ # "product_option_id": 114,
206
+ # "display_name": "Size",
207
+ # "display_name_customer": "Size",
208
+ # "display_name_merchant": "Size",
209
+ # "display_value": "Small",
210
+ # "display_value_customer": "Small",
211
+ # "display_value_merchant": "Small",
212
+ # "value": "101",
213
+ # "type": "Multiple choice",
214
+ # "name": "Size1699441692-88",
215
+ # "display_style": "Dropdown"
216
+ # }
217
+ # ],
218
+ # "configurable_fields": [],
219
+ # "discounted_total_inc_tax": "83.3300"
220
+ # }
221
+ # ]
222
+ # }
223
+ # ],
224
+ # "items_total": 1,
225
+ # "items_shipped": 0,
226
+ # "shipping_method": "None",
227
+ # "base_cost": 0,
228
+ # "cost_ex_tax": 0,
229
+ # "cost_inc_tax": 0,
230
+ # "cost_tax": 0,
231
+ # "cost_tax_class_id": 0,
232
+ # "base_handling_cost": 0,
233
+ # "handling_cost_ex_tax": 0,
234
+ # "handling_cost_inc_tax": 0,
235
+ # "handling_cost_tax": 0,
236
+ # "handling_cost_tax_class_id": 0,
237
+ # "shipping_zone_id": 0,
238
+ # "shipping_zone_name": "",
239
+ # "shipping_quotes": {
240
+ # "url": "https://api.bigcommerce.com/stores/d0kmq3bory/v2/orders/102/consignments/shipping/3/shipping_quotes",
241
+ # "resource": "/orders/102/consignments/shipping/3/shipping_quotes"
242
+ # }
243
+ # }
244
+ # ]
245
+ # }
246
+
247
+ # Shopify = {
248
+ # "line_items": [
249
+ # {
250
+ # "id": 13120677806211,
251
+ # "admin_graphql_api_id": "gid://shopify/LineItem/13120677806211",
252
+ # "fulfillable_quantity": 1,
253
+ # "fulfillment_service": "manual",
254
+ # "fulfillment_status": null,
255
+ # "gift_card": false,
256
+ # "grams": 0,
257
+ # "name": "Winter Luggage - Sienna the longest name variant in the world",
258
+ # "price": "150.00",
259
+ # "price_set": {
260
+ # "shop_money": {
261
+ # "amount": "150.00",
262
+ # "currency_code": "GBP"
263
+ # },
264
+ # "presentment_money": {
265
+ # "amount": "150.00",
266
+ # "currency_code": "GBP"
267
+ # }
268
+ # },
269
+ # "product_exists": true,
270
+ # "product_id": 6610509627523,
271
+ # "properties": [],
272
+ # "quantity": 1,
273
+ # "requires_shipping": true,
274
+ # "sku": "skusku123",
275
+ # "taxable": true,
276
+ # "title": "Winter Luggage",
277
+ # "total_discount": "0.00",
278
+ # "total_discount_set": {
279
+ # "shop_money": {
280
+ # "amount": "0.00",
281
+ # "currency_code": "GBP"
282
+ # },
283
+ # "presentment_money": {
284
+ # "amount": "0.00",
285
+ # "currency_code": "GBP"
286
+ # }
287
+ # },
288
+ # "variant_id": 39428269408387,
289
+ # "variant_inventory_management": "shopify",
290
+ # "variant_title": "Sienna the longest name variant in the world",
291
+ # "vendor": "PreProduct Test",
292
+ # "tax_lines": [],
293
+ # "duties": [],
294
+ # "discount_allocations": []
295
+ # }
296
+ # ]
297
+ # }
@@ -5,11 +5,11 @@ module EPlat
5
5
 
6
6
  class << self
7
7
 
8
- def new_instance(specifc_mapping:)
8
+ def new_instance(specifc_mapping:, resource: nil)
9
9
  if Object.const_defined?(specifc_mapping)
10
- mapping = specifc_mapping.constantize.new
10
+ mapping = specifc_mapping.constantize.new(resource)
11
11
  else
12
- mapping = EPlat::Mapping::Base.new
12
+ mapping = EPlat::Mapping::Base.new(resource)
13
13
  end
14
14
  end
15
15
 
@@ -1,10 +1,11 @@
1
1
  module EPlat
2
2
  class AttributeInterface
3
- attr_accessor :parent, :keys
3
+ attr_accessor :klass, :keys
4
4
 
5
- def initialize(parent, keys:)
6
- @parent, @keys = parent, keys
7
- add_convenience_methods
5
+ def initialize(klass, keys:)
6
+ @klass, @keys = klass, keys
7
+
8
+ add_to_instance! if keys.present?
8
9
  end
9
10
 
10
11
  def inspect
@@ -12,15 +13,15 @@ module EPlat
12
13
  end
13
14
 
14
15
  def entries
15
- keys.map{|k| {k => parent.send(k)} }.inject(&:merge)
16
+ keys.map{|k| {k => klass.send(k)} }.inject(&:merge)
16
17
  end
17
18
 
18
19
  define_method :[] do |key|
19
- parent.attributes[key]
20
+ klass.attributes[key]
20
21
  end
21
22
 
22
23
  define_method :[]= do |key, value|
23
- parent.attributes[key] = value
24
+ klass.attributes[key] = value
24
25
  end
25
26
 
26
27
  def include?(value)
@@ -34,27 +35,26 @@ module EPlat
34
35
 
35
36
  private
36
37
 
37
- def add_convenience_methods
38
- keys.each do |key|
39
- class_eval <<-STRING
40
- define_method "#{ key }" do
41
- parent.send("#{key}")
42
- end
43
- STRING
44
-
45
- class_eval <<-STRING
46
- define_method("#{key}=") do |val|
47
- parent.send("#{key}=", val)
48
- end
49
- STRING
50
-
51
- class_eval <<-STRING
52
- define_method "#{ key }?" do
53
- ActiveModel::Type::Boolean.new.cast parent.send("#{key}")
54
- end
55
- STRING
56
- end
57
- end
38
+ def add_to_instance!
39
+ meta_programming_string =
40
+ keys.map do |key|
41
+ <<-STRING
42
+ def #{ key }
43
+ self.attributes['#{key}']
44
+ end
45
+
46
+ def #{key}=(value)
47
+ self.attributes['#{key}'] = value
48
+ end
49
+
50
+ def #{ key }?
51
+ ActiveModel::Type::Boolean.new.cast send '#{key}'
52
+ end
53
+ STRING
54
+ end.join("\n")
55
+
56
+ klass.instance_eval { eval meta_programming_string }
57
+ end
58
58
 
59
59
  end
60
60
  end
@@ -2,77 +2,151 @@
2
2
 
3
3
  module EPlat
4
4
  class Base < ActiveResource::Base
5
+ include Concerns::OverwriteRequestMethods, Concerns::OverwriteInstanceMethods
6
+ include Concerns::Aliases, Concerns::Dirty
5
7
 
8
+ self.connection_class = EPlat::Connection
9
+ self.collection_parser = EPlat::Collection
10
+ self.site = "/" # this is overwritten below in initialize_singleton! when EPlat::Session is initialized
11
+ add_response_method :full_response
12
+
6
13
  class << self
7
- include Concerns::OverwriteRequestMethods
8
- threadsafe_attribute :client, :mapping, :include_root_in_json, :include_format_in_path
14
+ include Countable
15
+
16
+ attr_accessor :read_only
17
+
18
+ threadsafe_attribute :_headers, :_connection, :_user, :_password, :_bearer_token, :_site, :_proxy, # active resource
19
+ :mapping, :include_root_in_json, :include_format_in_path # e_plat specific
9
20
 
10
21
  def initialize_singleton!
11
- self.client = Current.e_plat_session
12
-
13
- self.site = client.base_url
14
- self.prefix = client.url_prefix
22
+ self.site = client.base_url # .site is an ActiveResource method that uses the threadsafe _site attribute underneath
23
+ self.prefix = client.url_prefix(klass: self) # this is overwritten below in prefix= for threadsafety
15
24
 
16
25
  self.timeout = 5
17
- self.include_format_in_path = !client.bigcommerce?
26
+ self.include_format_in_path = client.include_format_in_path?
18
27
  self.mapping = mapping_instance
19
28
 
20
29
  client.platform_headers.each {|name, value| self.headers[name] = value}
21
30
  end
22
-
23
- def find_by(title:)
24
- find(:all, params: { title: title })&.first
31
+
32
+ def client
33
+ Current.e_plat_session
34
+ end
35
+
36
+
37
+ # monkey patch prefix= so we can add thread-local value to the generated prefix_source() method
38
+ def prefix=(value = "/")
39
+ # Replace :placeholders with '#{embedded options[:lookups]}'
40
+ prefix_call = value.gsub(/:\w+/) { |key| "\#{URI::DEFAULT_PARSER.escape options[#{key}].to_s}" }
41
+
42
+ # Clear prefix parameters in case they have been cached
43
+ @prefix_parameters = nil
44
+
45
+ silence_warnings do
46
+ # Redefine the new methods.
47
+ instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
48
+ def prefix_source()
49
+ client.url_prefix(klass: self) || "#{value}"
50
+ end
51
+ def prefix(options={}) "#{prefix_call}" end
52
+ RUBY_EVAL
53
+ end
54
+ rescue Exception => e
55
+ logger.error "Couldn't set prefix: #{e}\n #{code}" if logger
56
+ raise
57
+ end
58
+
59
+ def exclude_from_json(read_only)
60
+ self.read_only = read_only
25
61
  end
62
+
26
63
 
27
64
  private
28
65
 
29
- def mapping_instance
30
- class_constant_string = element_name.capitalize
31
- mapping_class_name = "EPlat::Mapping::#{ client.platform.capitalize }::V#{ client.api_version.camelize }::#{ class_constant_string }"
32
-
33
- EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name)
34
- end
66
+ def mapping_instance
67
+ mapping_class_name = "EPlat::Mapping::#{ client.platform.capitalize }::V#{ client.api_version.camelize }::#{ element_name.classify }"
68
+
69
+ EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name, resource: nil)
70
+ end
35
71
 
36
72
  end
37
73
 
38
-
39
- include Concerns::Aliases, Concerns::OverwriteInstanceMethods
40
-
41
- attr_accessor :client, :mapping, :mapped_attributes
74
+ attr_accessor :mapping, :mapped_attributes
42
75
 
43
76
  def initialize(attributes = {}, persisted = false)
44
- self.client = Current.e_plat_session
45
77
  site = client.base_url
46
- self.mapping = mapping_instance
47
78
  ActiveResource::Base.include_root_in_json = client.shopify? && top_level_resource?
48
79
 
49
80
  super
81
+
82
+ self.mapping = mapping_instance
50
83
 
51
- add_aliases!(mapping.native_attribute_aliases, schema)
52
- @mapped_attributes = AttributeInterface.new(self, keys: mappable_keys)
84
+ @mapped_attributes = ensure_e_plat_attributes!
85
+ ensure_native_attributes!
86
+ add_aliases!(mapping.native_attribute_aliases, type_schema || {})
53
87
  end
54
-
88
+
89
+ def client
90
+ Current.e_plat_session
91
+ end
92
+
55
93
  def mapped?(attribute)
56
94
  mapped_attributes.include? attribute.to_s
57
95
  end
58
96
 
59
97
  def native_keys
60
- (client.shopify?) ? schema.keys : @mapping.native_attributes.presence
98
+ if client.shopify?
99
+ schema.keys # EPlat uses Shopify's schema, so keys are always native
100
+ elsif mapping.class.to_s != EPlat::Mapping::Base && @mapping.native_attributes.present?
101
+ @mapping.native_attributes.presence
102
+ else
103
+ attributes.keys
104
+ end
105
+ end
106
+
107
+ def read_only?
108
+ !!self.class.read_only
109
+ end
110
+
111
+ def headers
112
+ full_response&.each_header&.to_h || {}
113
+ end
114
+
115
+ def include_root_in_json
116
+ return false unless client.shopify?
117
+
118
+ top_level_resource?
61
119
  end
62
120
 
121
+
63
122
  private
123
+
124
+ def ensure_e_plat_attributes!
125
+ AttributeInterface.new(self, keys: mappable_keys)
126
+ end
127
+
128
+ def ensure_native_attributes!
129
+ return if client.shopify? # EPlat uses Shopify's schema
130
+
131
+ AttributeInterface.new(self, keys: native_keys)
132
+ end
64
133
 
65
134
  def mapping_instance
66
135
  class_constant_string = self.class.to_s.gsub("EPlat::", "")
67
136
  mapping_class_name = "EPlat::Mapping::#{ client.platform.capitalize }::V#{ client.api_version.camelize }::#{ class_constant_string }"
68
-
69
- EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name)
137
+
138
+ EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name, resource: self)
70
139
  end
71
140
 
72
141
  def mappable_keys
73
142
  mappable_keys = mapping.mappable_keys
74
143
  (mappable_keys == :all) ? schema.keys : mappable_keys
75
144
  end
145
+
146
+ def type_schema
147
+ return unless schema.present? && schema.values.any?{|value| value == "string" or value == "hash" }
148
+ schema
149
+ end
76
150
 
77
151
  def type_check!(schema)
78
152
  schema.each{|name, type| type_attr!(name, type) }
@@ -96,10 +170,11 @@ module EPlat
96
170
  end
97
171
 
98
172
  def top_level_resource?
99
- [
100
- "product",
101
- "order"
102
- ].include? self.class.element_name
173
+ self.class.name.split("::").count <= 2
174
+ end
175
+
176
+ def element_name
177
+ self.class.element_name
103
178
  end
104
179
 
105
180
  end
@@ -107,37 +182,3 @@ module EPlat
107
182
 
108
183
  end
109
184
 
110
-
111
-
112
-
113
-
114
-
115
-
116
- ###### api call methods
117
-
118
- ### create new entry
119
- # product = EPlat::Product.new(:title => 't-shirt')
120
- # t-shirt.save
121
- # or... EPlat::Product.create(:title => 't-shirt')
122
- # new_product = product.dup #duplicates entry without saving
123
-
124
- ### delete record
125
- # EPlat::Product.delete(params[:id])
126
- # EPlat::Product.find(my_id).destroy
127
-
128
- ### save record
129
- # product = EPlat::Product.new(:title => 't-shirt')
130
- # product.save
131
-
132
- ### get records
133
- # EPlat::Product.find(1) # => GET /people/1.json (or EPlat::Product.first(args)) (or EPlat::Product.last(args))
134
- # EPlat::Product.find(:all) # => GET /people.json
135
- # EPlat::Product.find(:all, :params => { :title => "tshirt" }) # => GET /product.json?title=tshirt
136
- # EPlat::Product.find(:one, :from => :leader) # => GET /product/leader.json
137
- # EPlat::Product.find(:one, :from => "/companies/1/manager.json") # => GET /companies/1/manager.json
138
-
139
-
140
- #### options
141
- # prefix_options #for nested URLs Comment.collection_path(:post_id => 5) # => /posts/5/comments.json
142
- # query_options #to add to params ?x=y
143
- # instance.known_attributes #to return mix of schema and native attributes