web-connect 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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