web-connect 0.4.11 → 0.4.12

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57e9bb59d41e8a0c01c87c705f8025d1d232f4ac
4
- data.tar.gz: 519a6611cddde1f5c82be9e983d4236eaaa028a3
3
+ metadata.gz: 273dc9f8b0c167f981f7dc726a5a2c90b4b3cca9
4
+ data.tar.gz: cf3251442213fa65617e0b69591345596efbf294
5
5
  SHA512:
6
- metadata.gz: 44e149eb63bb57f314fdd9b5a530aa969d2910aa506c6f719aef1c6f3e40d8c95214127a0d3f795a60025cdb5c41f3a3f2dcfa62bb914f86a4fa37993bf7ffe5
7
- data.tar.gz: 62ec603899fc3a43d0c83424c0ff94b7b0c5c3420c92ac18fc2f681ccb63a6facd4230cf9a665cdd3e13b017f771f2e6b50f61b1154b336a04be0f614ddaae56
6
+ metadata.gz: b7c425a18993a3ef9138327ced689d54f82ca5acb214e119b24c9bf41ca7ef7682070bbf2a70c4f43627b3c77978d28d56b430995c9aa8cbcc845ff7fc4352a1
7
+ data.tar.gz: a94076bac46ff5f1a6ef825a47d3895b7b54910155284b120556a50c6dbddd0b6ee54ec4b3fb0c2ddb3638dcc05d39682b0efa5c644f2d5e291060c18e96a158
@@ -5,7 +5,7 @@ class Netfira::WebConnect::OctaWord
5
5
  class << self
6
6
 
7
7
  def from_binary(digest)
8
- new digest
8
+ new digest if digest
9
9
  end
10
10
 
11
11
  alias_method :from, :from_binary
@@ -23,14 +23,9 @@ module Netfira::WebConnect
23
23
  t.string options[:origin_key] || :"#{table_name.to_s.singularize}_id", index: true unless options[:writable]
24
24
  yield t
25
25
  t.references :shop, index: true
26
- if options[:tree]
27
- t.string :parent_id
28
- t.index [:shop_id, :parent_id]
29
- end
30
- if options[:sendable]
31
- t.binary :guid, index: true
32
- t.integer :delivery_status, default: 0, limit: 3, index: true
33
- end
26
+ create_tree_table t if options[:tree]
27
+ create_writable_table t if options[:writable]
28
+ create_sendable_table t if options[:sendable]
34
29
  t.binary :digest, limit: 16
35
30
  t.timestamps
36
31
  t.datetime :deleted_at
@@ -55,20 +50,13 @@ module Netfira::WebConnect
55
50
  end
56
51
 
57
52
  def create_file_table(table_name)
58
- create_table table_name do |t|
59
- t.references :shop, index: true
60
- t.string :file_name, index: true
53
+ create_record_table table_name, origin_key: :file_name, file: true do |t|
61
54
  t.string :remote_location
62
55
  t.string :locale
63
56
  yield t if block_given?
64
57
  t.integer :size
65
58
  t.binary :checksum, limit: 16
66
- t.binary :digest, limit: 16
67
- t.timestamps
68
- t.datetime :deleted_at
69
- t.index :deleted_at
70
59
  end
71
- add_table_def table_name, {}, true
72
60
  end
73
61
 
74
62
  def create_relation_table(first, second)
@@ -81,9 +69,8 @@ module Netfira::WebConnect
81
69
  end
82
70
  end
83
71
 
84
- def add_table_def(table_name, options, is_file = false)
85
- Models::Table.create options.select{|k| %i[origin_key writable sendable].include? k}.merge name: table_name,
86
- file: is_file
72
+ def add_table_def(table_name, options)
73
+ Models::Table.create options.select{|k| %i[origin_key writable sendable file].include? k}.merge name: table_name
87
74
  end
88
75
 
89
76
  def write(text = '')
@@ -107,6 +94,20 @@ module Netfira::WebConnect
107
94
  Netfira::WebConnect.db_table_prefix name
108
95
  end
109
96
 
97
+ def create_tree_table(t)
98
+ t.string :parent_id
99
+ t.index [:shop_id, :parent_id]
100
+ end
101
+
102
+ def create_writable_table(t)
103
+ t.binary :guid, limit: 16
104
+ t.index :guid, unique: true
105
+ end
106
+
107
+ def create_sendable_table(t)
108
+ t.integer :delivery_status, default: 0, limit: 3, index: true
109
+ end
110
+
110
111
  end
111
112
  end
112
113
 
@@ -45,6 +45,9 @@ module Netfira::WebConnect
45
45
  # Set up tree behaviour (parent/child relations)
46
46
  klass.include Model::Record::Tree if klass.tree?
47
47
 
48
+ # Set up writable behaviour
49
+ klass.include Model::Record::Writable if klass.writable?
50
+
48
51
  # Set up sendable behaviour
49
52
  klass.include Model::Record::Sendable if klass.sendable?
50
53
 
@@ -4,25 +4,28 @@ module Netfira::WebConnect
4
4
  module Sendable
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ DELIVERY_STATUSES = %i(unsent sent delivered)
8
+
7
9
  included do
8
- after_initialize :create_guid
9
- enum delivery_status: [:unsent, :sent, :delivered]
10
- end
11
10
 
12
- def guid
13
- @guid ||= Guid.from(self[:guid])
11
+ # Make #delivery_status an enumeration, generating methods like #sent?, #sent!, etc.
12
+ enum delivery_status: DELIVERY_STATUSES
13
+
14
+ # Scopes
15
+ sent_and_undelivered_index = DELIVERY_STATUSES.index(:sent)
16
+ scope :sent_and_undelivered, -> { where delivery_status: sent_and_undelivered_index }
17
+
14
18
  end
15
19
 
16
- def guid=(value)
17
- raise 'GUIDs are read-only'
20
+ def send!
21
+ sent!
22
+ save!
23
+ #TODO: send notification to client(s)
24
+ self
18
25
  end
19
26
 
20
27
  private
21
28
 
22
- def create_guid
23
- self[:guid] ||= (@guid = Guid.create).b
24
- end
25
-
26
29
  end
27
30
 
28
31
  end
@@ -48,11 +48,11 @@ module Netfira::WebConnect
48
48
  end
49
49
 
50
50
  def single_name
51
- @single_name ||= Netfira::WebConnect.db_table_l10n_suffix @owner_class.single_name
51
+ @single_name ||= Netfira::WebConnect.db_table_l10n_suffix(@owner_class.single_name).freeze
52
52
  end
53
53
 
54
54
  def plural_name
55
- @plural_name ||= Netfira::WebConnect.db_table_l10n_suffix @owner_class.plural_name
55
+ @plural_name ||= Netfira::WebConnect.db_table_l10n_suffix(@owner_class.plural_name).freeze
56
56
  end
57
57
 
58
58
  end
@@ -0,0 +1,85 @@
1
+ module Netfira::WebConnect
2
+ # noinspection RubyStringKeysInHashInspection
3
+ class Model::Record
4
+
5
+ module Writable
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+
10
+ # Add a model initializer that generates a random GUID
11
+ after_initialize :create_guid
12
+
13
+ # Attributes that can be sent
14
+ def self.attributes_to_send
15
+ @attributes_to_send ||= attribute_names +
16
+ (has_languages? ? self::Translation.translated_attribute_names : []) -
17
+ Serializer::EXCLUDE_FROM_SERIALIZE
18
+ end
19
+
20
+ end
21
+
22
+ def to_deliverable
23
+ attributes_as_camel_cased_hash.tap do |result|
24
+
25
+ # Include GUIDs for sendables, e.g. "orderId" => "hd8jdi38jds02893hdo8wq3"
26
+ result["#{self.class.single_name_camel}Id"] = guid.to_s if sendable?
27
+
28
+ # Included timestamps, e.g. "createdAt" => "2014-09-27T11:10:00+10:00"
29
+ %w(created_at updated_at).each do |field|
30
+ result[field.camelize :lower] = __send__(field).strftime '%FT%T%:z'
31
+ end
32
+
33
+ # Include collections, e.g. "lines" => [{...}, ...]
34
+ result.merge! self.class.schema.has_many.keys.map { |k| [k, __send__(k).map(&:to_deliverable)] }.to_h
35
+ end
36
+ end
37
+
38
+ # Used by older downstream methods, e.g. newOrders, newInboundDocuments etc
39
+ def to_deprecated_downstream
40
+ fields = attributes_as_camel_cased_hash
41
+ if sendable?
42
+ sendable_fields = {
43
+ "#{self.class.single_name_camel}GUID" => guid.to_s,
44
+ "#{self.class.single_name_camel}Id" => id.to_s,
45
+ finalised: '1'
46
+ }
47
+ fields.merge! sendable_fields
48
+ end
49
+ {created: created_at.to_i, fields: fields}.merge deprecated_downstream_children
50
+ end
51
+
52
+ def guid
53
+ @guid ||= Guid.from(self[:guid])
54
+ end
55
+
56
+ def guid=(value)
57
+ raise 'GUIDs are read-only'
58
+ end
59
+
60
+ private
61
+
62
+ def attributes_as_camel_cased_hash
63
+ self.class.attributes_to_send.map { |key| [key.camelize(:lower), __send__(key).to_s] }.to_h
64
+ end
65
+
66
+ def deprecated_downstream_children
67
+ self.class.schema.has_many.keys.map do |key|
68
+ [key, __send__(key).map(&:to_deprecated_downstream)]
69
+ end.to_h
70
+ end
71
+
72
+ def create_guid
73
+ self[:guid] ||= (@guid = Guid.create).b
74
+ end
75
+
76
+ module ClassMethods
77
+ def single_name_camel
78
+ @single_name_camel ||= single_name.camelize :lower
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
@@ -3,6 +3,7 @@ require_relative 'record/materialization'
3
3
  require_relative 'record/serializer'
4
4
  require_relative 'record/digests'
5
5
  require_relative 'record/sendable'
6
+ require_relative 'record/writable'
6
7
  require_relative 'record/events'
7
8
 
8
9
  module Netfira::WebConnect
@@ -15,6 +16,15 @@ module Netfira::WebConnect
15
16
 
16
17
  class << self
17
18
 
19
+ def sendable
20
+ return super unless self == Model::Record # This should raise an error!
21
+ @sendable_classes ||= Models.constants.map do |name|
22
+ Models.const_get name
23
+ end.select do |klass|
24
+ Class === klass && klass < Model::Record && klass.sendable?
25
+ end
26
+ end
27
+
18
28
  def table_name
19
29
  @table_name ||= if self == Model::Record
20
30
  Models::Table.table_name
@@ -32,13 +42,7 @@ module Netfira::WebConnect
32
42
  end
33
43
 
34
44
  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
45
+ @origin_key ||= writable? ? :guid : (table_props.origin_key || "#{single_name}_id").to_sym
42
46
  end
43
47
 
44
48
  def writable?
@@ -55,6 +59,7 @@ module Netfira::WebConnect
55
59
  end
56
60
 
57
61
  def find_or_initialize_by_origin_id(shop, id)
62
+ id = Guid.from_base64(id).b if origin_key == :guid
58
63
  find_by_origin_id(shop, id).tap { |record| record.restore! if record && record.destroyed? } or
59
64
  new(origin_key => id, shop_id: shop.id)
60
65
  end
@@ -17,11 +17,11 @@ module Netfira::WebConnect
17
17
  end
18
18
 
19
19
  def single_name
20
- @single_name ||= name.demodulize.underscore
20
+ @single_name ||= name.demodulize.underscore.freeze
21
21
  end
22
22
 
23
23
  def plural_name
24
- @plural_name ||= single_name.pluralize
24
+ @plural_name ||= single_name.pluralize.freeze
25
25
  end
26
26
  end
27
27
 
@@ -91,7 +91,7 @@ module Netfira::WebConnect
91
91
 
92
92
  # Unserialize JSON
93
93
  begin
94
- @input = JSON.parse @input.read, quirks_mode: true if request.media_type == 'application/json'
94
+ @input = JSON.parse @input.read.sub(/\A\z/, 'null'), quirks_mode: true if request.media_type == 'application/json'
95
95
  rescue JSON::ParserError => error
96
96
  raise BadRequest.new('Invalid JSON in request body', details: error.message.sub(/^\d+:\s*/, ''))
97
97
  end
@@ -0,0 +1,32 @@
1
+ module Netfira::WebConnect
2
+ class RackApp
3
+ module Action::Version8
4
+ class Confirm < Action
5
+
6
+ def call
7
+ allow :put, Hash
8
+ self.class.types.each do |type, klass|
9
+ ids = input[type]
10
+ ids.each { |guid| confirm_delivery klass, guid if %r`^[\w+/]{22}$` === guid } if Array === ids
11
+ end
12
+ {}
13
+ end
14
+
15
+ private
16
+
17
+ def confirm_delivery(klass, guid)
18
+ record = klass.find_by(shop_id: shop.id, guid: Guid.from_base64(guid).b)
19
+ if record
20
+ record.delivered!
21
+ record.save!
22
+ end
23
+ end
24
+
25
+ def self.types
26
+ @types ||= Model::Record.sendable.map { |k| [k.plural_name.camelize(:lower), k] }.to_h
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,55 @@
1
+ class Netfira::WebConnect::RackApp
2
+ module Action::Version8
3
+
4
+ class_methods = Module.new do
5
+
6
+ def record_class
7
+ @record_class ||= Netfira::WebConnect::Models.const_get self::MODEL_NAME
8
+ end
9
+
10
+ def collection_name
11
+ @collection_name ||= self::MODEL_NAME.pluralize.downcase.freeze
12
+ end
13
+
14
+ end
15
+
16
+ fetch_class = Class.new Action do
17
+ extend class_methods
18
+
19
+ def call
20
+ allow :get
21
+ {self.class.collection_name => undelivered.map(&:to_deprecated_downstream)}
22
+ end
23
+
24
+ private
25
+
26
+ def undelivered
27
+ self.class.record_class.sent_and_undelivered.where(shop_id: shop.id)
28
+ end
29
+
30
+ end
31
+
32
+ confirm_class = Class.new Action do
33
+ extend class_methods
34
+
35
+ def call
36
+ allow :put
37
+ record = self.class.record_class.sent_and_undelivered.find_by(shop_id: shop.id, id: query_string['id'])
38
+ if record
39
+ record.delivered!
40
+ record.save
41
+ end
42
+ {}
43
+ end
44
+
45
+ end
46
+
47
+ # There will be more classes later, e.g. Documents. When they are needed, they can
48
+ # be added to the array below.
49
+ %w(Order).each do |name|
50
+ const_set :"New#{name.pluralize}", Class.new(fetch_class ).tap { |c| c::MODEL_NAME = name.freeze }
51
+ const_set :"Confirm#{name}", Class.new(confirm_class).tap { |c| c::MODEL_NAME = name.freeze }
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ module Netfira::WebConnect
2
+ class RackApp
3
+ module Action::Version8
4
+ class Fetch < Action
5
+
6
+ def call
7
+ allow :get
8
+ self.class.types.map { |type, klass| [type, records_for_class(klass)] }.select { |(_, x)| x && x.first }.to_h
9
+ end
10
+
11
+ private
12
+
13
+ def records_for_class(klass)
14
+ klass.sent_and_undelivered.where(shop_id: shop.id).map &:to_deliverable
15
+ end
16
+
17
+ def self.types
18
+ @types ||= Model::Record.sendable.map { |k| [k.plural_name.camelize(:lower), k] }.to_h
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module Netfira::WebConnect::RackApp::Exceptions
2
+ class UserException < Base
3
+
4
+ attr_reader :original_exception
5
+
6
+ def initialize(original_exception)
7
+ @original_exception = original_exception
8
+ end
9
+
10
+ end
11
+ end
@@ -1,7 +1,8 @@
1
1
  module Netfira::WebConnect::RackApp::Exceptions
2
- class Base < Exception
2
+ class Base < RuntimeError
3
3
  end
4
4
  end
5
5
 
6
6
  require_relative 'exceptions/http_exception'
7
7
  require_relative 'exceptions/send_file'
8
+ require_relative 'exceptions/user_exception'
@@ -26,7 +26,11 @@ module Netfira::WebConnect
26
26
  rescue => e
27
27
  # TODO: provide a way to silence these (i.e. for prod environments)
28
28
  # TODO: log errors
29
- raise e if defined? DONT_CATCH_ALL_EXCEPTIONS
29
+ if Exceptions::UserException === e
30
+ e = e.original_exception
31
+ else
32
+ raise e if defined? DONT_CATCH_ALL_EXCEPTIONS
33
+ end
30
34
  body = {
31
35
  errorCode: 1,
32
36
  errorMessage: 'Uncaught Exception',
@@ -28,7 +28,15 @@ module Netfira::WebConnect
28
28
  @relations = klass.related_classes
29
29
  end
30
30
 
31
- IGNORE_COLUMNS = %w[id shop_id created_at updated_at digest]
31
+ def has_many
32
+ @has_many ||= klass.reflect_on_all_associations(:has_many).select do |a|
33
+ a.klass < Model::Record && !a.options[:through]
34
+ end.map do |association|
35
+ [association.name, association.klass]
36
+ end.to_h
37
+ end
38
+
39
+ IGNORE_COLUMNS = %w[id shop_id created_at updated_at deleted_at digest]
32
40
 
33
41
  def columns
34
42
  @columns ||= klass.columns_hash.reject{ |k| IGNORE_COLUMNS.include? k }.merge(l10n_columns).map{ |k, v| [k.to_sym, v.type.to_s] }.to_h
@@ -40,7 +48,8 @@ module Netfira::WebConnect
40
48
  relations: relations.map{ |klass| klass.name.demodulize.pluralize },
41
49
  singular: singular,
42
50
  primaryKey: [primary_key.to_s.camelize(:lower)],
43
- localize: l10n_columns.keys.map{ |k| k.camelize :lower }
51
+ localize: l10n_columns.keys.map{ |k| k.camelize :lower },
52
+ hasMany: has_many.map{ |type, klass| [type, klass.plural_name.camelize] }.to_h
44
53
  }
45
54
  end
46
55
 
@@ -1,6 +1,6 @@
1
1
  module Netfira
2
2
  module WebConnect
3
- VERSION = '0.4.11'
3
+ VERSION = '0.4.12'
4
4
  PLATFORM_AND_VERSION = 'Rack/' << VERSION
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web-connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 0.4.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil E. Pearson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-21 00:00:00.000000000 Z
12
+ date: 2014-09-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -146,6 +146,7 @@ files:
146
146
  - lib/netfira/web_connect/model/record/translation.rb
147
147
  - lib/netfira/web_connect/model/record/translations.rb
148
148
  - lib/netfira/web_connect/model/record/tree.rb
149
+ - lib/netfira/web_connect/model/record/writable.rb
149
150
  - lib/netfira/web_connect/model/relation.rb
150
151
  - lib/netfira/web_connect/model/relation/events.rb
151
152
  - lib/netfira/web_connect/model/support.rb
@@ -172,6 +173,9 @@ files:
172
173
  - lib/netfira/web_connect/rack_app/actions/version_8/commit.rb
173
174
  - lib/netfira/web_connect/rack_app/actions/version_8/commit/records.rb
174
175
  - lib/netfira/web_connect/rack_app/actions/version_8/commit/relations.rb
176
+ - lib/netfira/web_connect/rack_app/actions/version_8/confirm.rb
177
+ - lib/netfira/web_connect/rack_app/actions/version_8/deprecated_downstream.rb
178
+ - lib/netfira/web_connect/rack_app/actions/version_8/fetch.rb
175
179
  - lib/netfira/web_connect/rack_app/actions/version_8/files.rb
176
180
  - lib/netfira/web_connect/rack_app/actions/version_8/records.rb
177
181
  - lib/netfira/web_connect/rack_app/actions/version_8/settings.rb
@@ -179,6 +183,7 @@ files:
179
183
  - lib/netfira/web_connect/rack_app/exceptions.rb
180
184
  - lib/netfira/web_connect/rack_app/exceptions/http_exception.rb
181
185
  - lib/netfira/web_connect/rack_app/exceptions/send_file.rb
186
+ - lib/netfira/web_connect/rack_app/exceptions/user_exception.rb
182
187
  - lib/netfira/web_connect/request_filter.rb
183
188
  - lib/netfira/web_connect/schema.rb
184
189
  - lib/netfira/web_connect/schema/table.rb