e_plat 0.2.4 → 0.4.0

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +633 -135
  3. data/lib/active_resource/connection_error.rb +29 -0
  4. data/lib/active_resource/formats.rb +27 -0
  5. data/lib/current.rb +7 -0
  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/errors/missing_session_error.rb +1 -1
  10. data/lib/e_plat/mapping/base.rb +119 -12
  11. data/lib/e_plat/mapping/bigcommerce/v_3/metafield.rb +62 -0
  12. data/lib/e_plat/mapping/bigcommerce/v_3/order/billing_address.rb +14 -0
  13. data/lib/e_plat/mapping/bigcommerce/v_3/order/line_item.rb +85 -0
  14. data/lib/e_plat/mapping/bigcommerce/v_3/order/shipping_address.rb +73 -0
  15. data/lib/e_plat/mapping/bigcommerce/v_3/order.rb +160 -0
  16. data/lib/e_plat/mapping/bigcommerce/v_3/product/image.rb +12 -12
  17. data/lib/e_plat/mapping/bigcommerce/v_3/product/variant.rb +1 -1
  18. data/lib/e_plat/mapping/bigcommerce/v_3/script_tag.rb +78 -0
  19. data/lib/e_plat/mapping/bigcommerce/v_3/shop.rb +11 -6
  20. data/lib/e_plat/mapping/bigcommerce/v_3/webhook.rb +54 -0
  21. data/lib/e_plat/mapping/request_body_root.rb +38 -0
  22. data/lib/e_plat/mapping/shopify/v_2024_01/metafield.rb +26 -0
  23. data/lib/e_plat/mapping/shopify/v_2024_01/order/billing_address.rb +14 -0
  24. data/lib/e_plat/mapping/shopify/v_2024_01/order/shipping_address.rb +30 -0
  25. data/lib/e_plat/mapping/shopify/{v_2022_07/product.rb → v_2024_01/order.rb} +3 -3
  26. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/product/image.rb +1 -1
  27. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/product/variant.rb +2 -1
  28. data/lib/e_plat/mapping/shopify/v_2024_01/product.rb +26 -0
  29. data/lib/e_plat/mapping/shopify/v_2024_01/script_tag.rb +26 -0
  30. data/lib/e_plat/mapping/shopify/{v_2022_07 → v_2024_01}/shop.rb +1 -1
  31. data/lib/e_plat/mapping/shopify/v_2024_01/webhook.rb +29 -0
  32. data/lib/e_plat/mapping/virtual_collection/base.rb +14 -0
  33. data/lib/e_plat/mapping/virtual_collection/bigcommerce/order_line_items.rb +297 -0
  34. data/lib/e_plat/mapping.rb +3 -3
  35. data/lib/e_plat/resource/attribute_interface.rb +28 -28
  36. data/lib/e_plat/resource/base.rb +107 -68
  37. data/lib/e_plat/resource/collection.rb +92 -0
  38. data/lib/e_plat/resource/concerns/aliases.rb +102 -18
  39. data/lib/e_plat/resource/concerns/dirty.rb +54 -0
  40. data/lib/e_plat/resource/concerns/metafieldable.rb +43 -0
  41. data/lib/e_plat/resource/concerns/overwrite_instance_methods.rb +108 -6
  42. data/lib/e_plat/resource/concerns/overwrite_request_methods.rb +73 -37
  43. data/lib/e_plat/resource/countable.rb +43 -0
  44. data/lib/e_plat/resource/metafield.rb +70 -0
  45. data/lib/e_plat/resource/order/Consignment.rb +8 -0
  46. data/lib/e_plat/resource/order/billing_address.rb +6 -0
  47. data/lib/e_plat/resource/order/fulfillment.rb +1 -0
  48. data/lib/e_plat/resource/order/line_item.rb +1 -0
  49. data/lib/e_plat/resource/order/shipping_address.rb +44 -0
  50. data/lib/e_plat/resource/order/shipping_line.rb +15 -14
  51. data/lib/e_plat/resource/order.rb +32 -0
  52. data/lib/e_plat/resource/paginated/link_headers.rb +42 -0
  53. data/lib/e_plat/resource/paginated/link_params.rb +26 -0
  54. data/lib/e_plat/resource/product/image.rb +6 -0
  55. data/lib/e_plat/resource/product/option.rb +1 -0
  56. data/lib/e_plat/resource/product/variant.rb +8 -12
  57. data/lib/e_plat/resource/product.rb +8 -2
  58. data/lib/e_plat/resource/script_tag.rb +56 -0
  59. data/lib/e_plat/resource/shop.rb +17 -13
  60. data/lib/e_plat/resource/shopify_only/recurring_application_charge/usage_charge.rb +32 -0
  61. data/lib/e_plat/resource/shopify_only/recurring_application_charge.rb +47 -0
  62. data/lib/e_plat/resource/webhook.rb +50 -0
  63. data/lib/e_plat/session.rb +14 -14
  64. data/lib/e_plat/type_coercer.rb +15 -17
  65. data/lib/e_plat/types.rb +1 -1
  66. data/lib/e_plat/version.rb +1 -1
  67. data/lib/e_plat.rb +4 -4
  68. metadata +51 -19
  69. data/lib/e_plat/resource/order/customer.rb +0 -37
  70. data/lib/e_plat/session_state.rb +0 -25
@@ -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,79 +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 Dry::Effects.State(:e_plat_session)
8
- include Concerns::OverwriteRequestMethods
9
- 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
10
20
 
11
21
  def initialize_singleton!
12
- self.client = e_plat_session
13
-
14
- self.site = client.base_url
15
- 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
16
24
 
17
25
  self.timeout = 5
18
- self.include_format_in_path = !client.bigcommerce?
26
+ self.include_format_in_path = client.include_format_in_path?
19
27
  self.mapping = mapping_instance
20
28
 
21
29
  client.platform_headers.each {|name, value| self.headers[name] = value}
22
30
  end
23
-
24
- def find_by(title:)
25
- 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
26
61
  end
62
+
27
63
 
28
64
  private
29
65
 
30
- def mapping_instance
31
- class_constant_string = element_name.capitalize
32
- mapping_class_name = "EPlat::Mapping::#{ client.platform.capitalize }::V#{ client.api_version.camelize }::#{ class_constant_string }"
33
-
34
- EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name)
35
- 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
36
71
 
37
72
  end
38
73
 
39
-
40
- include Dry::Effects.State(:e_plat_session)
41
- include Concerns::Aliases, Concerns::OverwriteInstanceMethods
42
-
43
- attr_accessor :client, :mapping, :mapped_attributes
74
+ attr_accessor :mapping, :mapped_attributes
44
75
 
45
76
  def initialize(attributes = {}, persisted = false)
46
- self.client = e_plat_session
47
77
  site = client.base_url
48
- self.mapping = mapping_instance
49
78
  ActiveResource::Base.include_root_in_json = client.shopify? && top_level_resource?
50
79
 
51
80
  super
81
+
82
+ self.mapping = mapping_instance
52
83
 
53
- add_aliases!(mapping.native_attribute_aliases, schema)
54
- @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 || {})
55
87
  end
56
-
88
+
89
+ def client
90
+ Current.e_plat_session
91
+ end
92
+
57
93
  def mapped?(attribute)
58
94
  mapped_attributes.include? attribute.to_s
59
95
  end
60
96
 
61
97
  def native_keys
62
- (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?
63
119
  end
64
120
 
121
+
65
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
66
133
 
67
134
  def mapping_instance
68
135
  class_constant_string = self.class.to_s.gsub("EPlat::", "")
69
136
  mapping_class_name = "EPlat::Mapping::#{ client.platform.capitalize }::V#{ client.api_version.camelize }::#{ class_constant_string }"
70
-
71
- EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name)
137
+
138
+ EPlat::Mapping.new_instance(specifc_mapping: mapping_class_name, resource: self)
72
139
  end
73
140
 
74
141
  def mappable_keys
75
142
  mappable_keys = mapping.mappable_keys
76
143
  (mappable_keys == :all) ? schema.keys : mappable_keys
77
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
78
150
 
79
151
  def type_check!(schema)
80
152
  schema.each{|name, type| type_attr!(name, type) }
@@ -98,10 +170,11 @@ module EPlat
98
170
  end
99
171
 
100
172
  def top_level_resource?
101
- [
102
- "product",
103
- "order"
104
- ].include? self.class.element_name
173
+ self.class.name.split("::").count <= 2
174
+ end
175
+
176
+ def element_name
177
+ self.class.element_name
105
178
  end
106
179
 
107
180
  end
@@ -109,37 +182,3 @@ module EPlat
109
182
 
110
183
  end
111
184
 
112
-
113
-
114
-
115
-
116
-
117
-
118
- ###### api call methods
119
-
120
- ### create new entry
121
- # product = EPlat::Product.new(:title => 't-shirt')
122
- # t-shirt.save
123
- # or... EPlat::Product.create(:title => 't-shirt')
124
- # new_product = product.dup #duplicates entry without saving
125
-
126
- ### delete record
127
- # EPlat::Product.delete(params[:id])
128
- # EPlat::Product.find(my_id).destroy
129
-
130
- ### save record
131
- # product = EPlat::Product.new(:title => 't-shirt')
132
- # product.save
133
-
134
- ### get records
135
- # EPlat::Product.find(1) # => GET /people/1.json (or EPlat::Product.first(args)) (or EPlat::Product.last(args))
136
- # EPlat::Product.find(:all) # => GET /people.json
137
- # EPlat::Product.find(:all, :params => { :title => "tshirt" }) # => GET /product.json?title=tshirt
138
- # EPlat::Product.find(:one, :from => :leader) # => GET /product/leader.json
139
- # EPlat::Product.find(:one, :from => "/companies/1/manager.json") # => GET /companies/1/manager.json
140
-
141
-
142
- #### options
143
- # prefix_options #for nested URLs Comment.collection_path(:post_id => 5) # => /posts/5/comments.json
144
- # query_options #to add to params ?x=y
145
- # instance.known_attributes #to return mix of schema and native attributes