trax_model 0.0.91 → 0.0.92
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 +4 -4
- data/Gemfile +1 -1
- data/lib/trax/model.rb +71 -12
- data/lib/trax/model/attributes.rb +40 -0
- data/lib/trax/model/attributes/definitions.rb +19 -0
- data/lib/trax/model/attributes/errors.rb +15 -0
- data/lib/trax/model/attributes/mixin.rb +43 -0
- data/lib/trax/model/attributes/type.rb +11 -0
- data/lib/trax/model/attributes/types.rb +11 -0
- data/lib/trax/model/attributes/types/array.rb +92 -0
- data/lib/trax/model/attributes/types/enum.rb +32 -0
- data/lib/trax/model/attributes/types/json.rb +76 -0
- data/lib/trax/model/attributes/types/uuid_array.rb +83 -0
- data/lib/trax/model/attributes/value.rb +9 -0
- data/lib/trax/model/config.rb +1 -9
- data/lib/trax/model/enum.rb +3 -3
- data/lib/trax/model/errors.rb +30 -19
- data/lib/trax/model/freezable.rb +1 -1
- data/lib/trax/model/mixin.rb +16 -4
- data/lib/trax/model/railtie.rb +17 -0
- data/lib/trax/model/registry.rb +3 -3
- data/lib/trax/model/restorable.rb +26 -17
- data/lib/trax/model/struct.rb +31 -0
- data/lib/trax/model/unique_id.rb +56 -14
- data/lib/trax/model/uuid_array.rb +59 -0
- data/lib/trax/model/validators.rb +2 -0
- data/lib/trax/validators/boolean_validator.rb +14 -0
- data/lib/trax/validators/email_validator.rb +6 -2
- data/lib/trax/validators/enum_validator.rb +16 -0
- data/lib/trax/validators/json_attribute_validator.rb +19 -0
- data/lib/trax_model/version.rb +1 -1
- data/spec/support/schema.rb +26 -10
- data/spec/trax/model/struct_spec.rb +16 -0
- data/spec/trax/model_spec.rb +2 -4
- data/trax_model.gemspec +1 -0
- metadata +35 -2
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'hashie/extensions/ignore_undeclared'
|
2
|
+
|
3
|
+
module Trax
|
4
|
+
module Model
|
5
|
+
module Attributes
|
6
|
+
module Types
|
7
|
+
class UuidArray < ::Trax::Model::Attributes::Type
|
8
|
+
class Value < ::Trax::Model::Attributes::Value
|
9
|
+
def initialize(*args)
|
10
|
+
@array = ::Trax::Model::UUIDArray.new(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def __getobj__
|
14
|
+
@array
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
@array.to_a.flatten.inspect
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class TypeCaster < ActiveRecord::Type::Value
|
23
|
+
include ::ActiveRecord::Type::Mutable
|
24
|
+
|
25
|
+
def initialize(*args, target_klass:)
|
26
|
+
super(*args)
|
27
|
+
|
28
|
+
@target_klass = target_klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
:uuid_array
|
33
|
+
end
|
34
|
+
|
35
|
+
def type_cast_from_user(value)
|
36
|
+
value.is_a?(@target_klass) ? @target_klass : @target_klass.new(value) || @target_klass.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def type_cast_from_database(value)
|
40
|
+
value.present? ? @target_klass.new(*value) : @target_klass.new(nil)
|
41
|
+
end
|
42
|
+
|
43
|
+
def type_cast_for_database(value)
|
44
|
+
if value.present?
|
45
|
+
value.to_json
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module Mixin
|
53
|
+
def self.mixin_registry_key; :uuid_array_attributes end;
|
54
|
+
|
55
|
+
extend ::Trax::Model::Mixin
|
56
|
+
include ::Trax::Model::Attributes::Mixin
|
57
|
+
|
58
|
+
module ClassMethods
|
59
|
+
def uuid_array_attribute(attribute_name, **options, &block)
|
60
|
+
attributes_klass_name = "#{attribute_name}_attributes".classify
|
61
|
+
attributes_klass = const_set(attributes_klass_name, ::Class.new(::Trax::Model::Attributes[:uuid_array]::Value))
|
62
|
+
attributes_klass.instance_eval(&block) if block_given?
|
63
|
+
|
64
|
+
attributes_klass.element_class = options[:of] if options.has_key?(:of)
|
65
|
+
|
66
|
+
trax_attribute_fields[:uuid_array] ||= {}
|
67
|
+
trax_attribute_fields[:uuid_array][attribute_name] = attributes_klass
|
68
|
+
|
69
|
+
if options.has_key?(:default)
|
70
|
+
self.default_value_for(attribute_name, options[:default])
|
71
|
+
else
|
72
|
+
[]
|
73
|
+
end
|
74
|
+
|
75
|
+
attribute(attribute_name, ::Trax::Model::Attributes[:uuid_array]::TypeCaster.new(target_klass: attributes_klass))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/trax/model/config.rb
CHANGED
@@ -1,20 +1,12 @@
|
|
1
1
|
module Trax
|
2
2
|
module Model
|
3
3
|
class Config < ::Hashie::Dash
|
4
|
-
ERROR_MESSAGES = {
|
5
|
-
:invalid_uuid_prefix => [
|
6
|
-
"UUID prefix must be 2 characters long",
|
7
|
-
"and be 0-9 or a-f",
|
8
|
-
"for hexadecimal id compatibility"
|
9
|
-
].join("\n")
|
10
|
-
}.freeze
|
11
|
-
|
12
4
|
property :uuid_prefix, :default => nil
|
13
5
|
property :uuid_column, :default => :id
|
14
6
|
|
15
7
|
def uuid_prefix=(prefix)
|
16
8
|
if prefix.length != 2 || prefix.chars.any?{|char| char !~ /[0-9a-f]/ }
|
17
|
-
raise ::Trax::Model::Errors::InvalidPrefixForUUID.new(prefix)
|
9
|
+
raise ::Trax::Model::Errors::InvalidPrefixForUUID.new(:prefix => prefix)
|
18
10
|
end
|
19
11
|
|
20
12
|
self[:uuid_prefix] = ::Trax::Model::UUIDPrefix.new(prefix)
|
data/lib/trax/model/enum.rb
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
module Trax
|
21
21
|
module Model
|
22
22
|
module Enum
|
23
|
-
|
23
|
+
extend ::Trax::Model::Mixin
|
24
24
|
|
25
25
|
module ClassMethods
|
26
26
|
def define_scopes_for_trax_enum(enum_name)
|
@@ -50,13 +50,13 @@ module Trax
|
|
50
50
|
validation_options = { :in => enum_values, :message => options.extract!(:message)[:message] }
|
51
51
|
|
52
52
|
self.validates_inclusion_of(enum_name, validation_options) unless options.key?(:validate) && !options[:validate]
|
53
|
+
|
53
54
|
options.delete(:validate) if options.key?(:validate)
|
54
55
|
|
55
56
|
define_scopes_for_trax_enum(enum_name)
|
56
57
|
|
57
|
-
self.default_value_for(enum_name) { default_value } if default_value
|
58
|
-
|
59
58
|
super(enum_name, enum_mapping, options)
|
59
|
+
self.default_value_for(enum_name) { default_value } if default_value
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
data/lib/trax/model/errors.rb
CHANGED
@@ -1,32 +1,43 @@
|
|
1
|
+
require 'trax/core/errors'
|
2
|
+
|
1
3
|
module Trax
|
2
4
|
module Model
|
3
5
|
module Errors
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class MixinNotRegistered < ::Trax::Core::Errors::Base
|
7
|
+
argument :mixin
|
8
|
+
argument :model
|
9
|
+
|
10
|
+
message {
|
11
|
+
"#{model} tried to load mixin: #{mixin}, whichdoes not exist in " \
|
12
|
+
"registry. Registered mixins were #{::Trax::Model.mixin_registry.keys.join(', ')} \n"
|
13
|
+
}
|
9
14
|
end
|
10
15
|
|
11
|
-
class InvalidPrefix < Trax::
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
class InvalidPrefix < ::Trax::Core::Errors::Base
|
17
|
+
argument :prefix, :required => true
|
18
|
+
|
19
|
+
message {
|
20
|
+
"Prefix #{prefix}"
|
21
|
+
"UUID prefix must be 2 characters long" \
|
22
|
+
"and be 0-9 or a-f" \
|
15
23
|
"for hexadecimal id compatibility"
|
16
|
-
|
24
|
+
}
|
17
25
|
end
|
18
26
|
|
19
|
-
class DuplicatePrefixRegistered < Trax::
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
27
|
+
class DuplicatePrefixRegistered < Trax::Core::Errors::Base
|
28
|
+
argument :prefix, :required => true
|
29
|
+
argument :model, :required => true
|
30
|
+
|
31
|
+
message {
|
32
|
+
"UUID prefix must be unique,\n" \
|
33
|
+
"#{prefix} was already registered by #{model}!"
|
34
|
+
}
|
24
35
|
end
|
25
36
|
|
26
|
-
class STIAttributeNotFound < ::Trax::
|
27
|
-
|
28
|
-
|
29
|
-
|
37
|
+
class STIAttributeNotFound < ::Trax::Core::Errors::Base
|
38
|
+
argument :attribute_name
|
39
|
+
|
40
|
+
message { "STI Attribute was not found for #{attribute_name}" }
|
30
41
|
end
|
31
42
|
end
|
32
43
|
end
|
data/lib/trax/model/freezable.rb
CHANGED
data/lib/trax/model/mixin.rb
CHANGED
@@ -1,12 +1,24 @@
|
|
1
1
|
module Trax
|
2
2
|
module Model
|
3
3
|
module Mixin
|
4
|
-
|
4
|
+
def self.extended(base)
|
5
|
+
base.extend(::ActiveSupport::Concern)
|
5
6
|
|
6
|
-
|
7
|
-
self.extend(::ActiveSupport::Concern)
|
7
|
+
super(base)
|
8
8
|
|
9
|
-
::Trax::Model.register_mixin(
|
9
|
+
::Trax::Model.register_mixin(base)
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_included(&block)
|
13
|
+
self.instance_variable_set(:@_after_included_block, block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def mixed_in(&block)
|
17
|
+
after_included(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def mixed(&block)
|
21
|
+
after_included(&block)
|
10
22
|
end
|
11
23
|
end
|
12
24
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
class Railtie < ::Rails::Railtie
|
4
|
+
::ActiveSupport.on_load(:active_record) do
|
5
|
+
def self.inherited(subklass)
|
6
|
+
subklass.include(::Trax::Model) if ::Trax::Model.config.auto_include
|
7
|
+
|
8
|
+
super(subklass)
|
9
|
+
|
10
|
+
::Trax::Model.config.auto_include_mixins.each do |mixin|
|
11
|
+
subklass.mixin(mixin)
|
12
|
+
end if ::Trax::Model.config.auto_include_mixins.any?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/trax/model/registry.rb
CHANGED
@@ -3,7 +3,7 @@ module Trax
|
|
3
3
|
class Registry
|
4
4
|
class_attribute :models
|
5
5
|
|
6
|
-
self.models
|
6
|
+
self.models = ::Hashie::Mash.new
|
7
7
|
|
8
8
|
class << self
|
9
9
|
delegate :key?, :to => :models
|
@@ -52,8 +52,8 @@ module Trax
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def self.uuid_map
|
55
|
-
models.values.reject{|model| model.try(:uuid_prefix) == nil }.inject(::Hashie::Mash.new) do |result, model|
|
56
|
-
result[model.uuid_prefix] = model
|
55
|
+
models.values.reject{|model| model.try(:unique_id_config).try(:uuid_prefix) == nil }.inject(::Hashie::Mash.new) do |result, model|
|
56
|
+
result[model.unique_id_config.uuid_prefix] = model
|
57
57
|
result
|
58
58
|
end
|
59
59
|
end
|
@@ -1,50 +1,59 @@
|
|
1
1
|
module Trax
|
2
2
|
module Model
|
3
3
|
module Restorable
|
4
|
-
|
4
|
+
extend ::Trax::Model::Mixin
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
define_configuration_options! do
|
7
|
+
option :field, :default => :is_deleted
|
8
|
+
option :timestamp_field, :default => :deleted_at
|
9
|
+
option :hide_deleted, :default => true
|
10
|
+
option :alias_destroy, :default => true
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
:
|
14
|
-
:
|
15
|
-
|
13
|
+
included do
|
14
|
+
define_configuration_options!(:restorable) do
|
15
|
+
option :field, :default => ::Trax::Model::Restorable.config.field
|
16
|
+
option :timestamp_field, :default => ::Trax::Model::Restorable.config.timestamp_field
|
17
|
+
option :hide_deleted, :default => ::Trax::Model::Restorable.config.hide_deleted
|
18
|
+
option :alias_destroy, :default => ::Trax::Model::Restorable.config.alias_destroy
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
module ClassMethods
|
19
23
|
def setup_restorable!
|
20
24
|
self.class_eval do
|
21
|
-
if(self.
|
25
|
+
if(self.restorable_config.hide_deleted)
|
22
26
|
default_scope { by_not_deleted }
|
23
27
|
end
|
24
28
|
|
29
|
+
if(self.restorable_config.alias_destroy)
|
30
|
+
alias_method :destroy!, :destroy
|
31
|
+
end
|
32
|
+
|
25
33
|
### Clear default deleted scope ###
|
26
34
|
scope :by_is_deleted, lambda { |*|
|
27
|
-
unscope(:where => self.
|
35
|
+
unscope(:where => self.restorable_config.field).where(self.restorable_config.field => true)
|
28
36
|
}
|
29
37
|
scope :by_not_deleted, lambda { |*|
|
30
|
-
where(self.
|
38
|
+
where(self.restorable_config.field => false)
|
31
39
|
}
|
32
40
|
|
33
|
-
default_value_for(self.
|
41
|
+
default_value_for(self.restorable_config.field) { false }
|
34
42
|
end
|
35
43
|
end
|
36
44
|
end
|
37
45
|
|
38
46
|
def destroy
|
39
|
-
self.update_attributes(self.
|
47
|
+
self.update_attributes(self.class.restorable_config.field => true, self.class.restorable_config.timestamp_field => ::DateTime.now)
|
40
48
|
end
|
41
49
|
|
42
50
|
def restore
|
43
|
-
self.update_attributes(self.
|
51
|
+
self.update_attributes(self.class.restorable_config.field => false, self.class.restorable_config.timestamp_field => ::DateTime.now)
|
44
52
|
end
|
45
53
|
|
46
54
|
def self.apply_mixin(target, options)
|
47
|
-
target.
|
55
|
+
target.restorable_config.merge!(options)
|
56
|
+
|
48
57
|
target.setup_restorable!
|
49
58
|
end
|
50
59
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
class Struct < ::Hashie::Dash
|
4
|
+
include ::Hashie::Extensions::Dash::IndifferentAccess
|
5
|
+
include ::Hashie::Extensions::Coercion
|
6
|
+
include ::Hashie::Extensions::IgnoreUndeclared
|
7
|
+
include ::ActiveModel::Validations
|
8
|
+
|
9
|
+
class_attribute :property_types
|
10
|
+
|
11
|
+
def self.inherited(subklass)
|
12
|
+
super(subklass)
|
13
|
+
|
14
|
+
subklass.property_types = {}.dup.tap do |hash|
|
15
|
+
hash[:structs] = []
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.struct_property(name, *args, **options, &block)
|
21
|
+
struct_klass_name = "#{name}_structs".classify
|
22
|
+
struct_klass = const_set(struct_klass_name, ::Class.new(::Trax::Model::Struct))
|
23
|
+
struct_klass.instance_eval(&block)
|
24
|
+
options[:default] = {} unless options.key?(:default)
|
25
|
+
property(name, *args, **options)
|
26
|
+
coerce_key(name, struct_klass)
|
27
|
+
property_types[:structs].push(name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/trax/model/unique_id.rb
CHANGED
@@ -1,17 +1,56 @@
|
|
1
1
|
module Trax
|
2
2
|
module Model
|
3
3
|
module UniqueId
|
4
|
-
|
4
|
+
extend ::Trax::Model::Mixin
|
5
|
+
|
6
|
+
define_configuration_options! do
|
7
|
+
option :uuid_column, :default => :id
|
8
|
+
option :uuid_map, :default => {}
|
9
|
+
end
|
5
10
|
|
6
11
|
included do
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
define_configuration_options!(:unique_id) do
|
13
|
+
option :uuid_prefix,
|
14
|
+
:setter => lambda{ |prefix|
|
15
|
+
if(::Trax::Model::UniqueId.config.uuid_map.values.include?(prefix) && ::Trax::Model::UniqueId.config.uuid_map[self.source.name] != prefix)
|
16
|
+
raise ::Trax::Model::Errors::DuplicatePrefixRegistered.new(:prefix => prefix, :model => self.source.name)
|
17
|
+
end
|
18
|
+
|
19
|
+
::Trax::Model::UniqueId.config.uuid_map[self.source.name] = prefix
|
20
|
+
::Trax::Model::UUIDPrefix.new(prefix)
|
21
|
+
},
|
22
|
+
:validates => {
|
23
|
+
:exclusion => {
|
24
|
+
:in => ::Trax::Model::Registry.uuid_map.values
|
25
|
+
},
|
26
|
+
:inclusion => {
|
27
|
+
:in => ::Trax::Model::UUIDPrefix.all,
|
28
|
+
:message => "%{value} not a valid uuid prefix!\nRun Trax::Model::UUIDPrefix.all for valid prefix list"
|
29
|
+
},
|
30
|
+
:allow_nil => true
|
31
|
+
}
|
32
|
+
|
33
|
+
option :uuid_column, :default => ::Trax::Model::UniqueId.config.uuid_column
|
34
|
+
end
|
35
|
+
|
36
|
+
#grab prefix from uuid registry if uuids are defined in an initializer
|
37
|
+
if ::Trax::Model.mixin_registry.key?(:unique_id) && ::Trax::Model::UUID.klass_prefix_map.key?(self.name)
|
38
|
+
self.unique_id_config.uuid_prefix = ::Trax::Model::UUID.klass_prefix_map[self.name]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
after_included do |options|
|
43
|
+
self.unique_id_config.merge!(options)
|
44
|
+
|
45
|
+
if(self.unique_id_config.uuid_prefix)
|
46
|
+
default_value_for(:"#{self.unique_id_config.uuid_column}") {
|
47
|
+
::Trax::Model::UUID.generate(self.unique_id_config.uuid_prefix)
|
48
|
+
}
|
10
49
|
end
|
11
50
|
end
|
12
51
|
|
13
52
|
def uuid
|
14
|
-
uuid_column = self.class.
|
53
|
+
uuid_column = self.class.unique_id_config.uuid_column
|
15
54
|
uuid_value = (uuid_column == "uuid") ? super : __send__(uuid_column)
|
16
55
|
|
17
56
|
::Trax::Model::UUID.new(uuid_value)
|
@@ -33,17 +72,20 @@ module Trax
|
|
33
72
|
end
|
34
73
|
|
35
74
|
module ClassMethods
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def defaults(*args)
|
40
|
-
super(*args)
|
41
|
-
|
42
|
-
self.default_value_for(:"#{self.trax_defaults.uuid_column}") {
|
43
|
-
::Trax::Model::UUID.generate(self.trax_defaults.uuid_prefix)
|
44
|
-
}
|
75
|
+
def uuid_prefix
|
76
|
+
self.unique_id_config.uuid_prefix
|
45
77
|
end
|
46
78
|
end
|
79
|
+
|
80
|
+
# def self.apply_mixin(target, options)
|
81
|
+
# target.unique_id_config.merge!(options)
|
82
|
+
#
|
83
|
+
# if(target.unique_id_config.uuid_prefix)
|
84
|
+
# target.default_value_for(:"#{target.unique_id_config.uuid_column}") {
|
85
|
+
# ::Trax::Model::UUID.generate(target.unique_id_config.uuid_prefix)
|
86
|
+
# }
|
87
|
+
# end
|
88
|
+
# end
|
47
89
|
end
|
48
90
|
end
|
49
91
|
end
|