Class: EPlat::Base

Inherits:
ActiveResource::Base
  • Object
show all
Extended by:
Countable
Includes:
Concerns::Aliases, Concerns::Dirty, Concerns::FullJson, Concerns::GraphQLable, Concerns::OverwriteInstanceMethods, Concerns::OverwriteRequestMethods
Defined in:
lib/e_plat/resource/base.rb

Constant Summary collapse

PROTECTED_ATTRIBUTES =
[
	"self", "collection", "password", "api_key", "attributes",
	"eval", "send", "public_send",
	"class", "send", "destroy", "delete_all", "__send__", "__id__", "initialize", "method",
	"delete", "delete_all", "destroy", "destroy_all", "update", "update_all", "save", "save_all",
	"delete!", "delete_all!", "destroy!", "destroy_all!", "update!", "update_all!", "save!", "save_all!",
].freeze

Constants included from Concerns::GraphQLable

Concerns::GraphQLable::FILTER_ARGS, Concerns::GraphQLable::QUERY_ARG_ARGS

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from Concerns::Aliases

#type_coercer

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Countable

count

Methods included from Concerns::GraphQLable

#graphql_mutation_string, #mutate_graphql, #remove_mutation_root_from

Methods included from Concerns::Aliases

#add_aliases!

Methods included from Concerns::FullJson

#as_full_json, #to_full_json

Methods included from Concerns::OverwriteRequestMethods

#collection_path, #element_path, included

Methods included from Concerns::OverwriteInstanceMethods

#as_eplat_json, #as_json, #create, #create_resource_for, #to_eplat_json, #to_json, #update

Constructor Details

#initialize(attributes = {}, persisted = false) ⇒ Base

Returns a new instance of Base.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/e_plat/resource/base.rb', line 102

def initialize(attributes = {}, persisted = false)
	site = client.base_url
	ActiveResource::Base.include_root_in_json = client.shopify? && top_level_resource?
	# attributes.reject!{ _1.starts_with? "_"} # remove private attributes, e.g. WooCommerce's '_links'

	super
	
	self.mapping = mapping_instance

	@mapped_attributes = ensure_e_plat_attributes!
	ensure_native_attributes!
	
	add_aliases!(mapping.native_attribute_aliases, type_schema || {})
end

Class Attribute Details

.read_onlyObject

Returns the value of attribute read_only.



24
25
26
# File 'lib/e_plat/resource/base.rb', line 24

def read_only
  @read_only
end

Instance Attribute Details

#mapped_attributesObject

Returns the value of attribute mapped_attributes.



100
101
102
# File 'lib/e_plat/resource/base.rb', line 100

def mapped_attributes
  @mapped_attributes
end

#mappingObject

Returns the value of attribute mapping.



100
101
102
# File 'lib/e_plat/resource/base.rb', line 100

def mapping
  @mapping
end

Class Method Details

.cached_shopify_webhook?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/e_plat/resource/base.rb', line 81

def cached_shopify_webhook?
	self.to_s.include?("EPlat::ShopifyWebhook")
end

.clientObject



46
47
48
# File 'lib/e_plat/resource/base.rb', line 46

def client
	EPlat::Current.e_plat_session
end

.element_name_plural?(word) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/e_plat/resource/base.rb', line 85

def element_name_plural?(word)
	word&.downcase&.include? element_name.pluralize 
end

.exclude_from_json(read_only) ⇒ Object



73
74
75
# File 'lib/e_plat/resource/base.rb', line 73

def exclude_from_json(read_only)
	self.read_only = read_only
end

.inherited(subclass) ⇒ Object



29
30
31
32
33
# File 'lib/e_plat/resource/base.rb', line 29

def inherited(subclass)
	super
	subclass.exclude_from_json(read_only) if read_only
	subclass.schema ||= schema.dup
end

.initialize_singleton!Object



35
36
37
38
39
40
41
42
43
44
# File 'lib/e_plat/resource/base.rb', line 35

def initialize_singleton!
	self.site  = client.base_url # .site is an ActiveResource method that uses the threadsafe _site attribute underneath
	self.prefix  = client.url_prefix(klass: self) # this is overwritten below in prefix= for threadsafety
	
	self.timeout = 20
	self.include_format_in_path = client.include_format_in_path?
	self.mapping = mapping_instance

	client.platform_headers.each {|name, value| self.headers[name] = value}
end

.platform_specific_class?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/e_plat/resource/base.rb', line 77

def platform_specific_class?
	self.class.to_s.include? client.platform.to_s.capitalize
end

.prefix=(value = "/") ⇒ Object

monkey patch prefix= so we can add thread-local value to the generated prefix_source() method



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/e_plat/resource/base.rb', line 52

def prefix=(value = "/")
	# Replace :placeholders with '#{embedded options[:lookups]}'
	prefix_call = value.gsub(/:\w+/) { |key| "\#{URI::DEFAULT_PARSER.escape options[#{key}].to_s}" }
		
	# Clear prefix parameters in case they have been cached
	@prefix_parameters = nil
		
	silence_warnings do
	  # Redefine the new methods.
	  instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
		def prefix_source() 
			client.url_prefix(klass: self) || "#{value}" 
		end
		def prefix(options={}) "#{prefix_call}" end
	  RUBY_EVAL
	end
rescue Exception => e
	logger.error "Couldn't set prefix: #{e}\n  #{code}" if logger
	raise
end

Instance Method Details

#clientObject



117
118
119
# File 'lib/e_plat/resource/base.rb', line 117

def client
	EPlat::Current.e_plat_session
end

#formatted_idObject



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/e_plat/resource/base.rb', line 149

def formatted_id
	return id unless client.shopify? && client.api_version != "2024_01"
	return if id.to_s.include?("gid://")

	case element_name
	when "product"
		"gid://shopify/Product/#{id}"
	when "variant"
		"gid://shopify/ProductVariant/#{id}"
	when "image"
		"gid://shopify/ProductImage/#{id}"
	else
		id
	end
end

#graphql_inputObject

Raises:



165
166
167
# File 'lib/e_plat/resource/base.rb', line 165

def graphql_input
	raise EPlat::Error.new("GraphQL input not supported for this resource and platform")
end

#headersObject



139
140
141
# File 'lib/e_plat/resource/base.rb', line 139

def headers
	full_response&.each_header&.to_h || {}
end

#include_root_in_jsonObject



143
144
145
146
147
# File 'lib/e_plat/resource/base.rb', line 143

def include_root_in_json
	return false unless client.shopify?
	
	top_level_resource?
end

#mapped?(attribute) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/e_plat/resource/base.rb', line 121

def mapped?(attribute)
	mapped_attributes.include? attribute.to_s
end

#native_keysObject



125
126
127
128
129
130
131
132
133
# File 'lib/e_plat/resource/base.rb', line 125

def native_keys
	if client.shopify? 
		@mapping.native_attributes.presence || schema.keys # EPlat uses Shopify's schema, apar from a couple of Graphql only fields
	elsif mapping.class.to_s != EPlat::Mapping::Base && @mapping.native_attributes.present?
		@mapping.native_attributes.presence - EPlat::Base::PROTECTED_ATTRIBUTES
	else
		attributes.keys - EPlat::Base::PROTECTED_ATTRIBUTES
	end
end

#read_only?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/e_plat/resource/base.rb', line 135

def read_only?
	!!self.class.read_only
end

#string_to_consistent_id(str) ⇒ Object

Generate a consistent integer ID from a string This method will always return the same ID for the same string



171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/e_plat/resource/base.rb', line 171

def string_to_consistent_id(str)
	# Normalize the string (lowercase, remove spaces)
	normalized = str.to_s.downcase.gsub(/\s+/, '')
	
	# Use a consistent algorithm to convert string to integer
	# Simple sum of ASCII values multiplied by position
	id = 0
	normalized.each_char.with_index do |char, index|
		id += (char.ord * (index + 1))
	end
	
	# Keep it within a reasonable range (1-1,000,000)
	(id % 1_000_000) + 1
end