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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d2700cd5cc5eadda85a187ac4d92b4b8eb1901d1
4
+ data.tar.gz: 8be1511337716328f72746dd70235f058c767d24
5
+ SHA512:
6
+ metadata.gz: 08968c7e607aa00cd578d97df1e2aecf320a3f1dfc6be796d3846166b04d1e5824921a0f22249115f0d739bc43398918a5311e5b7a5ab38394696fedba100b54
7
+ data.tar.gz: 3d621b56728b17482bc46ce4802bd045712541baa0ea37a0dda47d2076ec05a9c8d20297c0a1f80af4d7455109b2527f37efac37ed4763b99bdb81bbe87dc1c4
data/README.md ADDED
@@ -0,0 +1 @@
1
+ This gem provides connectivity between your app and Netfira products.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ task :console do
2
+ require_relative 'spec/console'
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'securerandom'
2
+
3
+ module Netfira::WebConnect
4
+ class Checksum < OctaWord
5
+
6
+ def self.of(data)
7
+ new Digest::MD5.digest(data)
8
+ end
9
+
10
+ def =~(what)
11
+ if what.is_a?(self.class)
12
+ b == what.b
13
+ else
14
+ b == self.class.of(what).b
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'securerandom'
2
+
3
+ module Netfira::WebConnect
4
+ class Guid < OctaWord
5
+
6
+ def self.create
7
+ new SecureRandom.random_bytes(16)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,73 @@
1
+ require 'active_support/inflector'
2
+
3
+ class Netfira::WebConnect::OctaWord
4
+
5
+ class << self
6
+
7
+ def from_binary(digest)
8
+ new digest
9
+ end
10
+
11
+ alias_method :from, :from_binary
12
+
13
+ def from_base64(digest)
14
+ new (digest[0..21] << '==').unpack('m').first
15
+ end
16
+
17
+ def from_hex(digest)
18
+ new [digest].pack('H*')
19
+ end
20
+
21
+ end
22
+
23
+ def initialize(binary_digest)
24
+ @binary = binary_digest.b
25
+ end
26
+
27
+ def binary
28
+ @binary
29
+ end
30
+
31
+ alias_method :b, :binary
32
+
33
+ def hex
34
+ @binary.unpack('H*')[0]
35
+ end
36
+
37
+ def base64
38
+ [@binary].pack('m0')[0..21]
39
+ end
40
+
41
+ def to_s
42
+ base64
43
+ end
44
+
45
+ def inspect
46
+ "#{self.class.name.demodulize}: #{base64}"
47
+ end
48
+
49
+ def eql?(other)
50
+ case other
51
+ when Netfira::WebConnect::OctaWord then b == other.b
52
+ when String
53
+ case other.length
54
+ when 16 then other == b
55
+ when 22 then other == base64
56
+ when 32 then other == hex
57
+ else false
58
+ end
59
+ else false
60
+ end
61
+ end
62
+
63
+ alias_method :==, :eql?
64
+
65
+ def as_json(options = nil)
66
+ base64
67
+ end
68
+
69
+ end
70
+
71
+ # Subclasses:
72
+ require_relative 'guid'
73
+ require_relative 'checksum'
@@ -0,0 +1 @@
1
+ require_relative 'components/octa_word'
@@ -0,0 +1,33 @@
1
+ module Netfira::WebConnect
2
+ class Configuration
3
+
4
+ attr_accessor :db_table_prefix, :file_store, :authenticator, :custom_fields,
5
+ :time_zone, :materialize_when_db_changed
6
+
7
+ attr_reader :logger, :db
8
+
9
+ def initialize(defaults = nil)
10
+ defaults.each{ |k, v| __send__ :"#{k}=", v } if defaults
11
+ end
12
+
13
+ def on_authenticate(proc = nil, &block)
14
+ authenticator = proc || block
15
+ raise 'Authenticator must take exactly two arguments (shop ID and password)' unless authenticator.arity == 2
16
+ self.authenticator = authenticator
17
+ end
18
+
19
+ def db=(details)
20
+ @db = details
21
+ if details
22
+ Model.establish_connection details
23
+ Models.materialize if materialize_when_db_changed && !Netfira::WebConnect.needs_migration?
24
+ end
25
+ end
26
+
27
+ def logger=(logger)
28
+ @logger = logger
29
+ Model.logger = logger if logger
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ class Support < Netfira::WebConnect::Migration
2
+ using Refinements
3
+
4
+ def change
5
+
6
+ create_table :_tables do |t|
7
+ t.string :name, limit: 50, indexed: true
8
+ t.string :origin_key, limit: 20
9
+ t.boolean :file
10
+ t.boolean :writable
11
+ t.boolean :sendable
12
+ end
13
+
14
+ create_table :_shops do |t|
15
+ t.string :name
16
+ t.index :name, unique: true
17
+ end
18
+
19
+ Netfira::WebConnect::Models::Shop.create id: 0
20
+
21
+ create_table :_settings do |t|
22
+ t.references :shop
23
+ t.string :key
24
+ t.binary :value, limit: 0x10000
25
+ t.string :content_type
26
+ end
27
+
28
+ create_table :_custom_fields do |t|
29
+ t.references :shop
30
+ t.references :table
31
+ t.references :record
32
+ t.string :key
33
+ t.binary :value, limit: 0x10000
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,106 @@
1
+ class Alpha < Netfira::WebConnect::Migration
2
+ using Refinements
3
+
4
+ def change
5
+
6
+ def product(t)
7
+ t.decimal :unit_price, precision: 12, scale: 4
8
+ t.decimal :unit_tax, precision: 12, scale: 4
9
+ t.localized_string :part
10
+ t.localized_string :description
11
+ end
12
+
13
+ def buyer(t)
14
+ t.string :name
15
+ t.string :contact
16
+ t.string :email, limit: 100
17
+ t.string :phone, limit: 30
18
+ t.string :fax, limit: 30
19
+ %w[billing_ shipping_].each do |type|
20
+ t.string :"#{type}address_1", limit: 150
21
+ t.string :"#{type}address_2", limit: 150
22
+ t.string :"#{type}city", limit: 150
23
+ t.string :"#{type}state", limit: 150
24
+ t.string :"#{type}country", limit: 2
25
+ t.string :"#{type}post_code", limit: 20
26
+ end
27
+
28
+ end
29
+
30
+ create_record_table :products, with_l10n: true do |t|
31
+ product t
32
+
33
+ t.localized_string :category
34
+ t.localized_string :long_description, limit: 0x10000
35
+
36
+ t.decimal :stock, precision: 12, scale: 4
37
+ t.string :stock_text
38
+
39
+ t.integer :length
40
+ t.integer :height
41
+ t.integer :width
42
+ t.decimal :weight, precision: 14, scale: 3
43
+
44
+ t.boolean :show_on_website
45
+ end
46
+
47
+ create_record_table :categories, with_l10n: true do |t|
48
+ t.integer :parent_id
49
+ t.localized_string :name
50
+ end
51
+
52
+ create_record_table :buyers, origin_key: :nf_code do |t|
53
+ buyer t
54
+
55
+ t.binary :pin, limit: 255
56
+ t.boolean :website_access
57
+ t.boolean :allow_products
58
+ t.boolean :restrict_products
59
+ end
60
+
61
+ create_record_table :orders, sendable: true do |t|
62
+ t.string :nf_code
63
+ buyer t
64
+
65
+ t.string :buyer_reference
66
+ t.string :currency_code, limit: 3
67
+
68
+ t.string :shipping_method
69
+ t.decimal :shipping_price, precision: 12, scale: 4
70
+ t.decimal :shipping_tax, precision: 12, scale: 4
71
+ t.string :shipping_account
72
+ t.string :shipping_password
73
+
74
+ t.string :payment_method
75
+ t.boolean :payment_received
76
+ t.string :payment_reference
77
+ t.string :payment_error_code, limit: 16
78
+
79
+ t.string :comment, limit: 0x10000
80
+ end
81
+
82
+ create_record_table :order_lines, writable: true do |t|
83
+ t.string :product_id
84
+ product t
85
+
86
+ t.references :order
87
+ t.decimal :quantity, precision: 12, scale: 4
88
+ t.string :comment, limit: 0x10000
89
+ end
90
+
91
+ create_file_table :images do |t|
92
+ t.float :focus_point_top
93
+ t.float :focus_point_left
94
+ t.integer :size
95
+ t.integer :width
96
+ t.integer :height
97
+ end
98
+ create_file_table :attachments
99
+
100
+ create_relation_table :products, :images
101
+ create_relation_table :products, :categories
102
+ create_relation_table :products, :attachments
103
+ create_relation_table :products, :buyers
104
+
105
+ end
106
+ end
@@ -0,0 +1,14 @@
1
+ module Netfira::WebConnect
2
+
3
+ def self.event_delegates
4
+ @event_delegates ||= []
5
+ end
6
+
7
+ def self.dispatch_event(event, *args)
8
+ target = :"on_#{event}"
9
+ event_delegates.map do |delegate|
10
+ delegate.__send__(target, *args) if delegate.respond_to? target
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,59 @@
1
+ module Netfira::WebConnect
2
+
3
+ def self.migrate
4
+ force_db_connection { ActiveRecord::Migrator.migrate migrations_dir }
5
+ end
6
+
7
+ def self.rollback
8
+ force_db_connection { ActiveRecord::Migrator.rollback migrations_dir }
9
+ end
10
+
11
+ def self.needs_migration?
12
+ original = ActiveRecord::Migrator.migrations_paths
13
+ ActiveRecord::Migrator.migrations_paths = [migrations_dir]
14
+ result = force_db_connection { ActiveRecord::Migrator.needs_migration? }
15
+ ActiveRecord::Migrator.migrations_paths = original
16
+ result
17
+ end
18
+
19
+ private
20
+
21
+ def self.migrations_dir
22
+ @migrations_dir ||= ROOT.join('web_connect/db_schema').to_s
23
+ end
24
+
25
+ # This method tricks ActiveRecord into using the connection for Netfira::WebConnect::Model
26
+ # instead of the ActiveRecord::Base connection, which it's hard-wired to do for migrations
27
+ # and other tasks. Two methods are backed up and replaced, then restored after yield. Those
28
+ # methods are identical to the originals, except they specify `Model` in place of `self`.
29
+ def self.force_db_connection
30
+
31
+ # Save the original methods
32
+ originals = [:connection_pool, :retrieve_connection, :schema_migrations_table_name].map do |name|
33
+ [name, ActiveRecord::Base.method(name)]
34
+ end.to_h
35
+
36
+ # Add some new methods
37
+ class << ActiveRecord::Base
38
+ def connection_pool
39
+ connection_handler.retrieve_connection_pool(Model) or raise ActiveRecord::ConnectionNotEstablished
40
+ end
41
+ def retrieve_connection
42
+ connection_handler.retrieve_connection(Model)
43
+ end
44
+ def schema_migrations_table_name
45
+ Netfira::WebConnect.schema_migrations_table_name
46
+ end
47
+ end
48
+
49
+ # Run the given block
50
+ result = yield
51
+
52
+ # Restore the original methods
53
+ originals.each { |name, method| ActiveRecord::Base.define_singleton_method name, method }
54
+
55
+ # Return the result of the given block
56
+ result
57
+ end
58
+
59
+ end
@@ -0,0 +1,16 @@
1
+ class Netfira::WebConnect::Migration
2
+ module Refinements
3
+
4
+ class << self
5
+ attr_accessor :running_migration
6
+ end
7
+
8
+ refine ActiveRecord::ConnectionAdapters::TableDefinition do
9
+
10
+ def localized_string(*args)
11
+ Refinements.running_migration.add_localized_string(args) or string *args
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,101 @@
1
+ require 'active_record'
2
+
3
+ module Netfira::WebConnect
4
+ class Migration < ActiveRecord::Migration
5
+
6
+ class << self
7
+ attr_accessor :log_to_stdout
8
+ end
9
+
10
+ def add_localized_string(args)
11
+ @l10n_buffer << args if @l10n_buffer
12
+ end
13
+
14
+ def create_table(table_name, options = {}, &block)
15
+ super table_prefix(table_name), options, &block
16
+ end
17
+
18
+ def create_record_table(table_name, options = {})
19
+ Refinements.running_migration = self
20
+ @l10n_buffer = options[:with_l10n] && []
21
+ options[:writable] ||= options[:sendable]
22
+ create_table table_name, options do |t|
23
+ t.string options[:origin_key] || :"#{table_name.to_s.singularize}_id", index: true unless options[:writable]
24
+ yield t
25
+ t.references :shop
26
+ if options[:sendable]
27
+ t.binary :guid, index: true
28
+ t.integer :delivery_status, default: 0, limit: 3, index: true
29
+ end
30
+ t.binary :digest, limit: 16
31
+ t.timestamps
32
+ end
33
+ if @l10n_buffer
34
+ create_l10n_table table_name do |t|
35
+ @l10n_buffer.each do |args|
36
+ t.string *args
37
+ end
38
+ end
39
+ end
40
+ add_table_def table_name, options
41
+ end
42
+
43
+ def create_l10n_table(table_name)
44
+ create_table l10n_suffix(table_name) do |t|
45
+ t.references table_name.to_s.singularize.to_sym, index: true
46
+ t.string :language, limit: 20, index: true
47
+ yield t
48
+ end
49
+ end
50
+
51
+ def create_file_table(table_name)
52
+ create_table table_name do |t|
53
+ t.references :shop
54
+ t.string :file_name, index: true
55
+ t.string :locale
56
+ yield t if block_given?
57
+ t.binary :checksum, limit: 16
58
+ t.binary :digest, limit: 16
59
+ t.timestamps
60
+ end
61
+ add_table_def table_name, {}, true
62
+ end
63
+
64
+ def create_relation_table(first, second)
65
+ first, second = [first, second].sort
66
+ create_table :"#{first}_to_#{second}" do |t|
67
+ t.references first.to_s.singularize, second.to_s.singularize, index: true
68
+ end
69
+ end
70
+
71
+ def add_table_def(table_name, options, is_file = false)
72
+ Models::Table.create options.select{|k| %i[origin_key writable sendable].include? k}.merge name: table_name,
73
+ file: is_file
74
+ end
75
+
76
+ def write(text = '')
77
+ if verbose
78
+ puts text if Migration.log_to_stdout
79
+ Netfira::WebConnect.logger.info text
80
+ end
81
+ end
82
+
83
+ def schema_migrations_table_name
84
+ Netfira::WebConnect.schema_migrations_table_name
85
+ end
86
+
87
+ private
88
+
89
+ def l10n_suffix(name = '')
90
+ Netfira::WebConnect.db_table_l10n_suffix name
91
+ end
92
+
93
+ def table_prefix(name = '')
94
+ Netfira::WebConnect.db_table_prefix name
95
+ end
96
+
97
+ end
98
+ end
99
+
100
+ require_relative 'migration/refinements'
101
+ require_relative 'migration/base_methods'
@@ -0,0 +1,24 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+
4
+ module Digests
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ before_save :write_digest
9
+ end
10
+
11
+ def digest
12
+ changed? ? Checksum.of(to_s) : Checksum.new(self[:digest])
13
+ end
14
+
15
+ private
16
+
17
+ def write_digest
18
+ self.digest = digest.b
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+ module Events
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ around_save :dispatch_create_or_update
8
+ before_destroy :dispatch_destroy
9
+ end
10
+
11
+ private
12
+
13
+ def dispatch_create_or_update
14
+ previous = persisted? && changed_attributes.map do |key, value|
15
+ # TODO: solve this type casting issue without guessing by attribute names!
16
+ value = Checksum.new(value) if value and (key == 'checksum' or key == 'digest')
17
+ [key, value]
18
+ end.to_h
19
+ yield
20
+ as_readonly do
21
+ if previous
22
+ Netfira::WebConnect.dispatch_event "update_#{self.class.single_name}", self, previous
23
+ else
24
+ Netfira::WebConnect.dispatch_event "create_#{self.class.single_name}", self
25
+ end
26
+ end
27
+ end
28
+
29
+ def dispatch_destroy
30
+ as_readonly { Netfira::WebConnect.dispatch_event "delete_#{self.class.single_name}", self }
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,79 @@
1
+ require 'paperclip'
2
+
3
+ Paperclip.interpolates :shop_id do |record, x|
4
+ record.instance.shop_id
5
+ end
6
+
7
+ Paperclip.interpolates :model_type do |record, x|
8
+ record.instance.class.name.demodulize.underscore.pluralize
9
+ end
10
+
11
+ module Netfira::WebConnect
12
+ class Model::Record::FileRecord
13
+ include Paperclip::Glue
14
+
15
+ class << self
16
+
17
+ def table_name
18
+ self == Model::Record::FileRecord ? Models::Table.table_name : super
19
+ end
20
+
21
+ def origin_key
22
+ :file_name
23
+ end
24
+
25
+ end
26
+
27
+ after_initialize :set_file_defaults
28
+
29
+ def <<(input)
30
+ if input.is_a? Model::Record
31
+ super input
32
+ else
33
+ self.data = input
34
+ end
35
+ end
36
+
37
+ def checksum
38
+ bin = self[:checksum]
39
+ @checksum ||= bin && Checksum.new(bin)
40
+ end
41
+
42
+ def checksum=(value)
43
+ @checksum = nil
44
+ self[:checksum] = Checksum === value ? value.b : value
45
+ end
46
+
47
+ def data
48
+ attachment.present? ? Paperclip.io_adapters.for(attachment) : nil
49
+ end
50
+
51
+ def data=(value)
52
+ self.attachment = value
53
+ value.rewind
54
+ self.checksum = Checksum.of(value.read)
55
+ end
56
+
57
+ def attachment_file_name
58
+ file_name
59
+ end
60
+
61
+ def attachment_file_name=(value)
62
+ self.file_name = value
63
+ end
64
+
65
+ def attachment_file_size
66
+ size
67
+ end
68
+
69
+ def attachment_file_size=(value)
70
+ self.size = value
71
+ end
72
+
73
+ private
74
+
75
+ def set_file_defaults
76
+ self.locale ||= shop.locale
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,59 @@
1
+ module Netfira::WebConnect
2
+ class Model::Record
3
+ module Materialization
4
+
5
+ def materialize(name, has_languages, props)
6
+
7
+ # Get a reference to the record class, creating it if it doesn't exist
8
+ klass = begin
9
+ Models.const_get name
10
+ rescue NameError
11
+ Models.const_set name, Class.new(props.file ? FileRecord : self)
12
+ end
13
+
14
+ # Give the model access to properties from the `tables` table
15
+ klass.instance_variable_set :@table_props, props
16
+
17
+ # Add a reference to the record's shop
18
+ shop_relation = name.underscore.pluralize.to_sym
19
+ klass.belongs_to :shop,
20
+ class_name: 'Netfira::WebConnect::Models::Shop',
21
+ inverse_of: shop_relation
22
+
23
+ # Add a has-many to Shop so we can do Shop.first.products etc
24
+ Models::Shop.has_many shop_relation, inverse_of: :shop
25
+
26
+ # Set up access to localised fields
27
+ if has_languages
28
+ Model::Record::Translation.materialize klass
29
+ klass.include Model::Record::Translations
30
+ translated_attributes = klass::Translation.attribute_names.reject do |attribute|
31
+ (%w[id language] << "#{klass.single_name}_id").include? attribute
32
+ end
33
+ translated_attributes.each do |attribute|
34
+ klass.__send__ :define_method, :"#{attribute}" do
35
+ self.get_translated_string attribute.to_sym
36
+ end
37
+ klass.__send__ :define_method, :"#{attribute}=" do |value|
38
+ self.set_translated_string attribute.to_sym, value
39
+ end
40
+ end
41
+ end
42
+
43
+ # Set up tree behaviour (parent/child relations)
44
+ klass.include Model::Record::Tree if klass.tree?
45
+
46
+ # Set up sendable behaviour
47
+ klass.include Model::Record::Sendable if klass.sendable?
48
+
49
+ # Set up file record behaviour
50
+ if klass.has_file?
51
+ klass.has_attached_file :attachment, Netfira::WebConnect.file_store
52
+ klass.do_not_validate_attachment_file_type :attachment
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
59
+ end