web-connect 0.4.11 → 0.4.12

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