web-connect 0.1.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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -0
  3. data/Rakefile +3 -0
  4. data/lib/netfira/web_connect/components/checksum.rb +19 -0
  5. data/lib/netfira/web_connect/components/guid.rb +11 -0
  6. data/lib/netfira/web_connect/components/octa_word.rb +73 -0
  7. data/lib/netfira/web_connect/components.rb +1 -0
  8. data/lib/netfira/web_connect/configuration.rb +33 -0
  9. data/lib/netfira/web_connect/db_schema/20140514_support.rb +38 -0
  10. data/lib/netfira/web_connect/db_schema/20140515_alpha.rb +106 -0
  11. data/lib/netfira/web_connect/events.rb +14 -0
  12. data/lib/netfira/web_connect/migration/base_methods.rb +59 -0
  13. data/lib/netfira/web_connect/migration/refinements.rb +16 -0
  14. data/lib/netfira/web_connect/migration.rb +101 -0
  15. data/lib/netfira/web_connect/model/record/digests.rb +24 -0
  16. data/lib/netfira/web_connect/model/record/events.rb +35 -0
  17. data/lib/netfira/web_connect/model/record/file_record.rb +79 -0
  18. data/lib/netfira/web_connect/model/record/materialization.rb +59 -0
  19. data/lib/netfira/web_connect/model/record/relations.rb +51 -0
  20. data/lib/netfira/web_connect/model/record/sendable.rb +29 -0
  21. data/lib/netfira/web_connect/model/record/serializer.rb +56 -0
  22. data/lib/netfira/web_connect/model/record/translated_string.rb +42 -0
  23. data/lib/netfira/web_connect/model/record/translation.rb +58 -0
  24. data/lib/netfira/web_connect/model/record/translations.rb +63 -0
  25. data/lib/netfira/web_connect/model/record/tree.rb +13 -0
  26. data/lib/netfira/web_connect/model/record.rb +132 -0
  27. data/lib/netfira/web_connect/model/relation/events.rb +34 -0
  28. data/lib/netfira/web_connect/model/relation.rb +67 -0
  29. data/lib/netfira/web_connect/model/support.rb +13 -0
  30. data/lib/netfira/web_connect/model.rb +33 -0
  31. data/lib/netfira/web_connect/models/image.rb +48 -0
  32. data/lib/netfira/web_connect/models/order.rb +5 -0
  33. data/lib/netfira/web_connect/models/order_line.rb +13 -0
  34. data/lib/netfira/web_connect/models/support/setting.rb +31 -0
  35. data/lib/netfira/web_connect/models/support/shop/settings.rb +42 -0
  36. data/lib/netfira/web_connect/models/support/shop.rb +22 -0
  37. data/lib/netfira/web_connect/models/support/table.rb +5 -0
  38. data/lib/netfira/web_connect/models.rb +73 -0
  39. data/lib/netfira/web_connect/rack_app/action.rb +66 -0
  40. data/lib/netfira/web_connect/rack_app/action_helpers/data_types.rb +22 -0
  41. data/lib/netfira/web_connect/rack_app/action_helpers/env_importer.rb +59 -0
  42. data/lib/netfira/web_connect/rack_app/action_helpers/env_methods.rb +23 -0
  43. data/lib/netfira/web_connect/rack_app/actions/version_1/not_supported.rb +11 -0
  44. data/lib/netfira/web_connect/rack_app/actions/version_8/checksums.rb +14 -0
  45. data/lib/netfira/web_connect/rack_app/actions/version_8/commit/records.rb +45 -0
  46. data/lib/netfira/web_connect/rack_app/actions/version_8/commit/relations.rb +48 -0
  47. data/lib/netfira/web_connect/rack_app/actions/version_8/commit.rb +33 -0
  48. data/lib/netfira/web_connect/rack_app/actions/version_8/files.rb +21 -0
  49. data/lib/netfira/web_connect/rack_app/actions/version_8/info.rb +18 -0
  50. data/lib/netfira/web_connect/rack_app/actions/version_8/settings.rb +79 -0
  51. data/lib/netfira/web_connect/rack_app/exceptions/http_exception.rb +44 -0
  52. data/lib/netfira/web_connect/rack_app/exceptions.rb +6 -0
  53. data/lib/netfira/web_connect/rack_app.rb +56 -0
  54. data/lib/netfira/web_connect/request_filter.rb +66 -0
  55. data/lib/netfira/web_connect/schema/table.rb +58 -0
  56. data/lib/netfira/web_connect/schema.rb +22 -0
  57. data/lib/netfira/web_connect/version.rb +5 -0
  58. data/lib/netfira/web_connect.rb +82 -0
  59. data/lib/netfira.rb +10 -0
  60. data/lib/web_connect.rb +1 -0
  61. metadata +246 -0
@@ -0,0 +1,51 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+
4
+ # These methods help relate and unrelate records
5
+ module Relations
6
+
7
+ def relate(record)
8
+ error_messages = {
9
+ no_relation: 'You cannot add a %s to a %s',
10
+ wrong_shop: 'Tried to add a record from shop %s to shop %s'
11
+ }
12
+ prepare_relation(record, error_messages) do |relation_class, attrs|
13
+ relation_class.find_or_create_by attrs
14
+ end
15
+ end
16
+
17
+ alias_method :<<, :relate
18
+
19
+ def unrelate(record)
20
+ error_messages = {
21
+ no_relation: 'You cannot remove a %s from a %s',
22
+ wrong_shop: 'Tried to remove a record of shop %s from shop %s'
23
+ }
24
+ prepare_relation(record, error_messages) do |relation_class, attrs|
25
+ relation_class.where(attrs).destroy_all
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ # This method assists #relate and #unrelate
32
+ def prepare_relation(record, error_messages)
33
+
34
+ # The class of the relation between self and record
35
+ relation_class = Model::Record::Relation.for(self, record)
36
+
37
+ # Error for unrelatable classes
38
+ raise error_messages[:no_relation] % [record.class.name.demodulize, self.class.name.demodulize] unless relation_class
39
+
40
+ # Error for shop mismatches
41
+ raise error_messages[:wrong_shop] % [record.shop_id, shop_id] unless shop_id == record.shop_id
42
+
43
+ # The attributes to use for create or delete, e.g. {product_id: 1, category_id: 2}
44
+ attrs = [self, record].map{ |r| ["#{r.class.name.demodulize.underscore}_id", r.id]}.to_h
45
+
46
+ yield relation_class, attrs
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+
4
+ module Sendable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ after_initialize :create_guid
9
+ enum delivery_status: [:unsent, :sent, :delivered]
10
+ end
11
+
12
+ def guid
13
+ @guid ||= Guid.from(self[:guid])
14
+ end
15
+
16
+ def guid=(value)
17
+ raise 'GUIDs are read-only'
18
+ end
19
+
20
+ private
21
+
22
+ def create_guid
23
+ self[:guid] ||= (@guid = Guid.create).b
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,56 @@
1
+ require 'bigdecimal'
2
+
3
+ module Netfira::WebConnect
4
+ class Model::Record
5
+
6
+ module Serializer
7
+ extend ActiveSupport::Concern
8
+
9
+ EXCLUDE_FROM_SERIALIZE = %w[id shop_id digest delivery_status created_at updated_at]
10
+
11
+ included do
12
+
13
+ private
14
+
15
+ # Returns an array of three arrays of keys, e.g.
16
+ # [ ['product_id', 'unit_price'], ['description'], [] ]
17
+ def self.attributes_to_serialize
18
+ @attributes_to_serialize ||= [
19
+ attribute_names - EXCLUDE_FROM_SERIALIZE,
20
+ has_languages? ? self::Translation.translated_attribute_names : [],
21
+ [] # Custom attributes (not implemented)
22
+ ]
23
+ end
24
+ end
25
+
26
+ def to_s
27
+
28
+ # Map each array of keys from the above method into a sorted hash of key/value pairs
29
+ data = self.class.attributes_to_serialize.map do |keys|
30
+ pairs = keys.sort.map do |key|
31
+ [key.camelize(:lower), cast_for_serialization(__send__ key)]
32
+ end
33
+ pairs.reject!{ |v| v[1].nil? }.to_h
34
+ end
35
+
36
+ # Return the class name and the sets above, e.g. Product{...},{...},{...}
37
+ self.class.name.demodulize << JSON.generate(data)[1..-2]
38
+ end
39
+
40
+ private
41
+
42
+ def cast_for_serialization(value)
43
+ if TranslatedString === value
44
+ value = value.sort
45
+ value = value.empty? ? nil : value.to_h
46
+ elsif Numeric === value
47
+ value = (value == value.floor) ? value.to_i : value.to_f
48
+ elsif OctaWord === value
49
+ value = value.to_s
50
+ end
51
+ value
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,42 @@
1
+ require 'forwardable'
2
+
3
+ module Netfira::WebConnect
4
+
5
+ # This class represents a translated string on a model, e.g. product.description.
6
+ # Callbacks are supplied by the Model::Record::Translations mixin
7
+ class Model::Record::TranslatedString
8
+ extend Forwardable
9
+
10
+ def initialize
11
+ @callbacks = {}
12
+ end
13
+
14
+ def [](lang)
15
+ @callbacks[:get].call lang
16
+ end
17
+
18
+ def []=(lang, value)
19
+ @callbacks[:set].call lang, value
20
+ end
21
+
22
+ def on(action, &block)
23
+ @callbacks[action] = block
24
+ end
25
+
26
+ def to_s
27
+ self[nil]
28
+ end
29
+
30
+ def to_h
31
+ @callbacks[:all].call
32
+ end
33
+
34
+ def merge!(values)
35
+ values.each{ |key, value| self[key] = value }
36
+ self
37
+ end
38
+
39
+ delegate %i[count length size each map sort select reject] => :to_h
40
+
41
+ end
42
+ end
@@ -0,0 +1,58 @@
1
+ module Netfira::WebConnect
2
+
3
+ # Subclasses of this model represents rows from translation tables, e.g. nf_products_l10n.
4
+ # Subclasses are materialized when their parent record models are materialized.
5
+ class Model::Record::Translation
6
+
7
+ class << self
8
+
9
+ def materialize(owner_class)
10
+
11
+ # Make a translation model, e.g. Product::Translation
12
+ klass = Class.new(self)
13
+ owner_class.const_set :Translation, klass
14
+
15
+ # Keep a reference to the owner class
16
+ klass.instance_variable_set :@owner_class, owner_class
17
+
18
+ # Give translations references back to their parent records
19
+ klass.belongs_to :owner,
20
+ class_name: owner_class.name,
21
+ foreign_key: "#{owner_class.name.demodulize.underscore}_id",
22
+ inverse_of: :translation_models
23
+
24
+ # Add a translations relation, e.g. product.translations
25
+ owner_class.has_many :translation_models,
26
+ class_name: klass.name,
27
+ inverse_of: :owner,
28
+ autosave: true
29
+
30
+ # Add translations to the default scope, as they will almost
31
+ # always be needed for lookups
32
+ owner_class.default_scope { includes :translation_models }
33
+
34
+ end
35
+
36
+ def translated_attribute_names
37
+ @translated_attribute_names ||= attribute_names - ['id', 'language', "#{@owner_class.single_name}_id"]
38
+ end
39
+
40
+ def table_name
41
+ @table_name ||= if self == Model::Record::Translation
42
+ Models::Table.table_name
43
+ else
44
+ Netfira::WebConnect.db_table_prefix(plural_name).to_s
45
+ end
46
+ end
47
+
48
+ def single_name
49
+ @single_name ||= Netfira::WebConnect.db_table_l10n_suffix @owner_class.single_name
50
+ end
51
+
52
+ def plural_name
53
+ @plural_name ||= Netfira::WebConnect.db_table_l10n_suffix @owner_class.plural_name
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,63 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+
4
+ # This module is mixed into records that have translations.
5
+ module Translations
6
+
7
+ # Called when getting a translated string, e.g. product.description
8
+ def get_translated_string(key)
9
+ translated_string_for key
10
+ end
11
+
12
+ # Called when assigning a translated string, e.g. product.description = 'Stuff'
13
+ def set_translated_string(key, value)
14
+ if Hash === value
15
+ replace_translations_for key, value
16
+ else
17
+ translated_string_for(key)[nil] = value
18
+ end
19
+ end
20
+
21
+ def locale
22
+ shop.locale
23
+ end
24
+
25
+ private
26
+
27
+ def translations
28
+ @translations ||= translation_models.map{ |model| [model.language, model]}.to_h
29
+ end
30
+
31
+ def translated_strings
32
+ @translated_strings ||= {}
33
+ end
34
+
35
+ def translation_for_language(lang)
36
+ lang = lang.to_s
37
+ translations[lang] ||= translation_models.build(language: lang)
38
+ end
39
+
40
+ def replace_translations_for(key, value)
41
+ translations.each { |lang, model| model[key] = value[lang] }
42
+ translated_string_for(key).merge! value
43
+ end
44
+
45
+ def translated_string_for(key)
46
+ translated_strings[key] ||= begin
47
+ t = Model::Record::TranslatedString.new
48
+ t.on(:get) { |lang| translation_for_language(lang || locale).__send__ key }
49
+ t.on(:set) { |lang, value| translation_for_language(lang || locale).__send__ :"#{key}=", value }
50
+ t.on(:all) { translations.map{ |lang, model| [lang, model[key]] }.reject{ |x| x[1].nil? }.to_h }
51
+ t
52
+ end
53
+ end
54
+
55
+ def clear_translations
56
+ @translations = nil
57
+ @translated_strings = nil
58
+ self
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,13 @@
1
+ module Netfira::WebConnect
2
+ module Model::Record::Tree
3
+
4
+ def children
5
+ self.class.where(parent_id: id)
6
+ end
7
+
8
+ def parent
9
+ @parent ||= parent_id && self.class.find_by(id: parent_id)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,132 @@
1
+ require_relative 'record/relations'
2
+ require_relative 'record/materialization'
3
+ require_relative 'record/serializer'
4
+ require_relative 'record/digests'
5
+ require_relative 'record/sendable'
6
+ require_relative 'record/events'
7
+
8
+ module Netfira::WebConnect
9
+ class Model::Record
10
+ extend Materialization
11
+ include Relations
12
+ include Serializer
13
+ include Digests
14
+ include Events
15
+
16
+ class << self
17
+
18
+ def table_name
19
+ @table_name ||= if self == Model::Record
20
+ Models::Table.table_name
21
+ else
22
+ Netfira::WebConnect.db_table_prefix(plural_name).to_s
23
+ end
24
+ end
25
+
26
+ def has_languages?
27
+ const_defined? :Translation, false
28
+ end
29
+
30
+ def tree?
31
+ @is_tree ||= attribute_names.include? 'parent_id'
32
+ end
33
+
34
+ def origin_key
35
+ @origin_key ||= if sendable?
36
+ :guid
37
+ elsif writable?
38
+ nil
39
+ else
40
+ (table_props.origin_key || "#{single_name}_id").to_sym
41
+ end
42
+ end
43
+
44
+ def writable?
45
+ @writable ||= table_props.writable
46
+ end
47
+
48
+ def sendable?
49
+ @sendable ||= table_props.sendable
50
+ end
51
+
52
+ def find_by_origin_id(shop, id)
53
+ id = id.b if OctaWord === id
54
+ find_by origin_key => id, shop_id: shop.id
55
+ end
56
+
57
+ def find_or_initialize_by_origin_id(shop, id)
58
+ find_by_origin_id(shop, id) || new(origin_key => id, shop_id: shop.id)
59
+ end
60
+
61
+ def find_or_create_by_origin_id(shop, id)
62
+ record = find_or_initialize_by_origin_id(shop, id)
63
+ record.save unless record.persisted?
64
+ record
65
+ end
66
+
67
+ def has_file?
68
+ @has_file ||= self < FileRecord
69
+ end
70
+
71
+ def schema
72
+ @schema ||= Netfira::WebConnect.schema[self]
73
+ end
74
+
75
+ end
76
+
77
+ after_initialize :init
78
+
79
+ %i[has_languages? tree? origin_key writable? sendable? has_file?].each do |method|
80
+ define_method(method) { self.class.__send__ method }
81
+ end
82
+
83
+ def origin_id
84
+ __send__ origin_key
85
+ end
86
+
87
+ def as_readonly
88
+ readonly!
89
+ yield
90
+ instance_variable_set :@readonly, false
91
+ end
92
+
93
+ def reload
94
+ clear_translations if has_languages?
95
+ super
96
+ end
97
+
98
+ def write_with_type_casting(key, value)
99
+ schema = self.class.schema
100
+ if schema.localize.include? key
101
+ set_translated_string key, value
102
+ else
103
+ type = schema.columns[key]
104
+ return false unless type
105
+ value = value.to_s if type == 'string'
106
+ write_attribute key, value
107
+ end
108
+ true
109
+ end
110
+
111
+ private
112
+
113
+ def self.table_props
114
+ @table_props
115
+ end
116
+
117
+ def init
118
+ self.shop_id ||= 0
119
+ end
120
+
121
+ def after_add_relation(model)
122
+ model.shop_id = shop_id
123
+ end
124
+
125
+ end
126
+ end
127
+
128
+ require_relative 'record/file_record'
129
+ require_relative 'record/translated_string'
130
+ require_relative 'record/translation'
131
+ require_relative 'record/translations'
132
+ require_relative 'record/tree'
@@ -0,0 +1,34 @@
1
+ module Netfira::WebConnect
2
+ class Model::Relation
3
+ module Events
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ after_save :dispatch_create
8
+ after_destroy :dispatch_destroy
9
+ end
10
+
11
+ private
12
+
13
+ def dispatch_create
14
+ dispatch_relation_event 'add_%s_to_%s'
15
+ end
16
+
17
+ def dispatch_destroy
18
+ dispatch_relation_event 'remove_%s_from_%s'
19
+ end
20
+
21
+ def dispatch_relation_event(event_name_template)
22
+ [records, records.reverse].each do |records|
23
+ event_name = (event_name_template % records.map{ |record| record.class.single_name }).to_sym
24
+ records[0].as_readonly do
25
+ records[1].as_readonly do
26
+ Netfira::WebConnect.dispatch_event event_name, *records
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,67 @@
1
+ require_relative 'relation/events'
2
+
3
+ module Netfira::WebConnect
4
+ class Model::Relation
5
+ include Events
6
+
7
+ class << self
8
+
9
+ attr_reader :related_classes
10
+
11
+ def materialize(name_a, name_b)
12
+ klass = Class.new(self)
13
+ Models.const_set "#{name_a}To#{name_b}", klass
14
+ klass.related_classes = [name_a, name_b].map{ |n| Models.const_get n.camelize.singularize }
15
+ end
16
+
17
+ def related_classes=(classes)
18
+ raise 'Related classes have already been set' if related_classes
19
+ @related_classes = classes
20
+ classes.each_with_index do |related_class, index|
21
+
22
+ # The class on the opposite side of the relation. For example:
23
+ # related_class => Product
24
+ # opposite_class => Category
25
+ opposite_class = related_classes[1 - index]
26
+
27
+ # Name of the reference to add to the related class, e.g. Product#category_relations
28
+ relation_name = :"#{opposite_class.single_name}_relations"
29
+
30
+ # The relation class's reference, e.g. CategoryToProduct#product
31
+ belongs_to related_class.single_name.to_sym
32
+
33
+ # The related class's reference to the relation, e.g. Product#category_relations
34
+ related_class.has_many relation_name,
35
+ class_name: name,
36
+ inverse_of: related_class.single_name.to_sym
37
+
38
+ # The related class's reference to the other related class,
39
+ # e.g. Product#categories (at last!)
40
+ related_class.has_many opposite_class.plural_name.to_sym,
41
+ through: relation_name,
42
+ after_add: :after_add_relation
43
+
44
+ end
45
+ end
46
+
47
+ def table_name
48
+ @table_name ||= if self == Model::Relation
49
+ Models::Table.table_name
50
+ else
51
+ Netfira::WebConnect.db_table_prefix(related_classes.map(&:plural_name).join '_to_').to_s
52
+ end
53
+ end
54
+
55
+ def for(class_a, class_b)
56
+ name = [class_a, class_b].map{ |c| (c.is_a?(Class) ? c : c.class).name.demodulize }.sort.join 'To'
57
+ Models.const_get name if Models.const_defined? name
58
+ end
59
+
60
+ end
61
+
62
+ def records
63
+ self.class.related_classes.map{ |klass| __send__ klass.single_name.to_sym }
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ module Netfira::WebConnect
2
+ class Model::Support
3
+
4
+ def self.table_name
5
+ @table_name ||= if self == Model::Support
6
+ Models::Table.table_name
7
+ else
8
+ Netfira::WebConnect.db_table_prefix('_' << name.demodulize.underscore.pluralize).to_s
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ module Netfira::WebConnect
2
+ class Model < ActiveRecord::Base
3
+ class Record < self
4
+ class FileRecord < self
5
+ end
6
+ class Translation < Model
7
+ end
8
+ end
9
+ class Relation < self
10
+ end
11
+ class Support < self
12
+ end
13
+
14
+ class << self
15
+ def table_name
16
+ Models::Table.table_name
17
+ end
18
+
19
+ def single_name
20
+ @single_name ||= name.demodulize.underscore
21
+ end
22
+
23
+ def plural_name
24
+ @plural_name ||= single_name.pluralize
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+ require_relative 'model/record'
32
+ require_relative 'model/relation'
33
+ require_relative 'model/support'
@@ -0,0 +1,48 @@
1
+ require 'ostruct'
2
+ require 'fastimage'
3
+
4
+ module Netfira::WebConnect
5
+ class Models::Image < Model::Record::FileRecord
6
+
7
+ def focus_point=(point)
8
+ self.focus_point_top = point[:top]
9
+ self.focus_point_left = point[:left]
10
+ self.focus_point
11
+ end
12
+
13
+ def focus_point
14
+ @focus_point ||= FocusPoint.new(self)
15
+ end
16
+
17
+ def data=(value)
18
+ super value
19
+ self.width, self.height = FastImage.size(attachment.staged_path)
20
+ end
21
+
22
+ def dimensions
23
+ [width, height]
24
+ end
25
+
26
+ def dimensions=(value)
27
+ self.width, self.height = value
28
+ end
29
+
30
+ class FocusPoint
31
+
32
+ def initialize(image)
33
+ @image = image
34
+ end
35
+
36
+ %w[top left].each do |attr|
37
+ define_method :"#{attr}" do
38
+ @image[:"focus_point_#{attr}"]
39
+ end
40
+ define_method :"#{attr}=" do |value|
41
+ @image[:"focus_point_#{attr}"] = value
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ module Netfira::WebConnect
2
+ class Models::Order < Model::Record
3
+ has_many :lines, class_name: "#{name}Line"
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module Netfira::WebConnect
2
+ class Models::OrderLine < Model::Record
3
+ belongs_to :order
4
+
5
+ after_initialize :set_defaults
6
+
7
+ private
8
+
9
+ def set_defaults
10
+ self.quantity ||= 1
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ module Netfira::WebConnect
2
+ class Models::Setting < Model::Support
3
+
4
+ belongs_to :shop, inverse_of: :setting_models
5
+
6
+ def typed_value
7
+ case content_type
8
+ when 'application/json' then JSON.parse(value, quirks_mode: true)
9
+ when 'application/octet-stream' then value.b
10
+ when /^text\/plain;charset=(.+)$/ then value.force_encoding($1)
11
+ else value
12
+ end
13
+ end
14
+
15
+ def typed_value=(value)
16
+ if String === value
17
+ if value.encoding.name == 'ASCII-8BIT'
18
+ self.value = value.b
19
+ self.content_type = 'application/octet-stream'
20
+ else
21
+ self.value = value.force_encoding('UTF-8')
22
+ self.content_type = 'text/plain;charset=UTF-8'
23
+ end
24
+ else
25
+ self.value = JSON.generate(value, quirks_mode: true)
26
+ self.content_type = 'application/json'
27
+ end
28
+ end
29
+
30
+ end
31
+ end