trax_model 0.0.98 → 0.0.99
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 +4 -0
- data/lib/trax/model.rb +6 -16
- data/lib/trax/model/attributes.rb +1 -1
- data/lib/trax/model/attributes/definitions.rb +4 -0
- data/lib/trax/model/attributes/{mixin.rb → dsl.rb} +2 -12
- data/lib/trax/model/attributes/types/boolean.rb +1 -2
- data/lib/trax/model/attributes/types/enum.rb +0 -2
- data/lib/trax/model/attributes/types/integer.rb +2 -2
- data/lib/trax/model/attributes/types/set.rb +67 -0
- data/lib/trax/model/attributes/types/string.rb +3 -3
- data/lib/trax/model/attributes/types/struct.rb +5 -3
- data/lib/trax/model/attributes/types/uuid_array.rb +0 -2
- data/lib/trax/model/{sti.rb → core_extensions.rb} +2 -2
- data/lib/trax/model/core_extensions/string.rb +17 -0
- data/lib/trax/model/extensions_for.rb +18 -0
- data/lib/trax/model/extensions_for/base.rb +31 -0
- data/lib/trax/model/extensions_for/boolean.rb +29 -0
- data/lib/trax/model/extensions_for/enumerable.rb +18 -0
- data/lib/trax/model/extensions_for/integer.rb +10 -0
- data/lib/trax/model/extensions_for/numeric.rb +46 -0
- data/lib/trax/model/extensions_for/set.rb +10 -0
- data/lib/trax/model/extensions_for/string.rb +30 -0
- data/lib/trax/model/extensions_for/struct.rb +191 -0
- data/lib/trax/model/extensions_for/struct_fields.rb +21 -0
- data/lib/trax/model/extensions_for/struct_fields/boolean.rb +32 -0
- data/lib/trax/model/extensions_for/struct_fields/enum.rb +20 -0
- data/lib/trax/model/extensions_for/struct_fields/float.rb +12 -0
- data/lib/trax/model/extensions_for/struct_fields/integer.rb +12 -0
- data/lib/trax/model/extensions_for/struct_fields/numeric.rb +52 -0
- data/lib/trax/model/extensions_for/struct_fields/string.rb +29 -0
- data/lib/trax/model/extensions_for/struct_fields/time.rb +54 -0
- data/lib/trax/model/matchable.rb +3 -10
- data/lib/trax/model/mixins.rb +3 -0
- data/lib/trax/model/mixins/freezable.rb +31 -0
- data/lib/trax/model/mixins/restorable.rb +63 -0
- data/lib/trax/model/mixins/sti_enum.rb +4 -5
- data/lib/trax/model/mixins/unique_id.rb +85 -0
- data/lib/trax/model/railtie.rb +4 -2
- data/lib/trax/validators/json_attribute_validator.rb +1 -0
- data/lib/trax_model/version.rb +1 -1
- data/spec/db/schema/default_tables.rb +1 -17
- data/spec/db/schema/pg_tables.rb +15 -0
- data/spec/support/models.rb +11 -16
- data/spec/support/pg/models.rb +31 -6
- data/spec/trax/model/attributes/types/set_spec.rb +68 -0
- data/spec/trax/model/attributes/types/struct_spec.rb +6 -0
- data/spec/trax/model/extensions_for/boolean_spec.rb +26 -0
- data/spec/trax/model/extensions_for/numeric_spec.rb +53 -0
- data/spec/trax/model/extensions_for/string_spec.rb +25 -0
- data/spec/trax/model/extensions_for/struct_spec.rb +223 -0
- data/spec/trax/model/extensions_for_spec.rb +0 -0
- data/spec/trax/model/{freezable_spec.rb → mixins/freezable_spec.rb} +1 -1
- data/spec/trax/model/{restorable_spec.rb → mixins/restorable_spec.rb} +1 -1
- data/spec/trax/model/{unique_id_spec.rb → mixins/unique_id_spec.rb} +1 -1
- data/trax_model.gemspec +4 -5
- metadata +49 -59
- data/lib/trax/model/enum.rb +0 -64
- data/lib/trax/model/freezable.rb +0 -29
- data/lib/trax/model/mti.rb +0 -11
- data/lib/trax/model/mti/abstract.rb +0 -65
- data/lib/trax/model/mti/entity.rb +0 -62
- data/lib/trax/model/mti/namespace.rb +0 -21
- data/lib/trax/model/restorable.rb +0 -61
- data/lib/trax/model/scopes.rb +0 -16
- data/lib/trax/model/sti/attributes.rb +0 -94
- data/lib/trax/model/string_extensions.rb +0 -11
- data/lib/trax/model/struct_extensions.rb +0 -185
- data/lib/trax/model/unique_id.rb +0 -83
- data/spec/trax/model/sti/attributes_spec.rb +0 -15
- data/spec/trax/model/struct_extensions_spec.rb +0 -16
@@ -0,0 +1,54 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
module ExtensionsFor
|
4
|
+
module StructFields
|
5
|
+
module Time
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
include ::Trax::Model::ExtensionsFor::Base
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def after(value)
|
11
|
+
cast_type = 'timestamp'
|
12
|
+
operator = '>'
|
13
|
+
model_class.where("(#{parent_definition.field_name} ->> '#{field_name}')::#{cast_type} #{operator} ?", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def before(value)
|
17
|
+
cast_type = 'timestamp'
|
18
|
+
operator = '<'
|
19
|
+
model_class.where("(#{parent_definition.field_name} ->> '#{field_name}')::#{cast_type} #{operator} ?", value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def between(first_time, second_time)
|
23
|
+
after(first_time).merge(before(second_time))
|
24
|
+
end
|
25
|
+
|
26
|
+
def gt(value)
|
27
|
+
after(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def gte(value)
|
31
|
+
cast_type = 'timestamp'
|
32
|
+
operator = '>='
|
33
|
+
model_class.where("(#{parent_definition.field_name} ->> '#{field_name}')::#{cast_type} #{operator} ?", value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def in_range(first_time, second_time)
|
37
|
+
gte(first_time).merge(lte(second_time))
|
38
|
+
end
|
39
|
+
|
40
|
+
def lt(value)
|
41
|
+
before(value)
|
42
|
+
end
|
43
|
+
|
44
|
+
def lte(value)
|
45
|
+
cast_type = 'timestamp'
|
46
|
+
operator = '<='
|
47
|
+
model_class.where("(#{parent_definition.field_name} ->> '#{field_name}')::#{cast_type} #{operator} ?", value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/trax/model/matchable.rb
CHANGED
@@ -3,23 +3,16 @@ module Trax
|
|
3
3
|
module Matchable
|
4
4
|
extend ::ActiveSupport::Concern
|
5
5
|
|
6
|
-
included do
|
7
|
-
::String.class_eval do
|
8
|
-
def to_matchable
|
9
|
-
"%#{self.strip}%"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
module ClassMethods
|
15
7
|
def matching(args = {})
|
16
8
|
matches = args.inject(self.all) do |scope, (key, value)|
|
17
9
|
node = key.is_a?(Symbol) ? self.arel_table[key] : key
|
18
10
|
|
19
11
|
values = [value]
|
12
|
+
values.flat_compact_uniq!
|
13
|
+
values.map!(&:to_matchable)
|
20
14
|
|
21
|
-
|
22
|
-
scope = scope.where(node.matches_any(match_values))
|
15
|
+
scope = scope.where(node.matches_any(values))
|
23
16
|
scope
|
24
17
|
end
|
25
18
|
|
data/lib/trax/model/mixins.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
module Mixins
|
4
|
+
module Freezable
|
5
|
+
extend ::Trax::Model::Mixin
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :freezable_fields
|
9
|
+
self.freezable_fields = ::ActiveSupport::OrderedOptions.new
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def freezable_by_enum(options = {})
|
14
|
+
freezable_fields.merge!(options)
|
15
|
+
define_frozen_validators_for_enum(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_frozen_validators_for_enum(options)
|
19
|
+
self.class_eval do
|
20
|
+
options.each_pair do |enum_method, frozen_states|
|
21
|
+
validates_with ::FrozenValidator, :if => lambda { |record|
|
22
|
+
frozen_states.any?{ |state| state == :"#{record.send(enum_method)}" } && !record.changed.include?("#{enum_method}")
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
module Mixins
|
4
|
+
module Restorable
|
5
|
+
extend ::Trax::Model::Mixin
|
6
|
+
|
7
|
+
define_configuration_options! do
|
8
|
+
option :field, :default => :is_deleted
|
9
|
+
option :timestamp_field, :default => :deleted_at
|
10
|
+
option :hide_deleted, :default => true
|
11
|
+
option :alias_destroy, :default => true
|
12
|
+
end
|
13
|
+
|
14
|
+
included do
|
15
|
+
define_configuration_options!(:restorable) do
|
16
|
+
option :field, :default => ::Trax::Model::Mixins::Restorable.config.field
|
17
|
+
option :timestamp_field, :default => ::Trax::Model::Mixins::Restorable.config.timestamp_field
|
18
|
+
option :hide_deleted, :default => ::Trax::Model::Mixins::Restorable.config.hide_deleted
|
19
|
+
option :alias_destroy, :default => ::Trax::Model::Mixins::Restorable.config.alias_destroy
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def setup_restorable!
|
25
|
+
self.class_eval do
|
26
|
+
if(self.restorable_config.hide_deleted)
|
27
|
+
default_scope { by_not_deleted }
|
28
|
+
end
|
29
|
+
|
30
|
+
if(self.restorable_config.alias_destroy)
|
31
|
+
alias_method :destroy!, :destroy
|
32
|
+
end
|
33
|
+
|
34
|
+
### Clear default deleted scope ###
|
35
|
+
scope :by_is_deleted, lambda { |*|
|
36
|
+
unscope(:where => self.restorable_config.field).where(self.restorable_config.field => true)
|
37
|
+
}
|
38
|
+
scope :by_not_deleted, lambda { |*|
|
39
|
+
where(self.restorable_config.field => false)
|
40
|
+
}
|
41
|
+
|
42
|
+
default_value_for(self.restorable_config.field) { false }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroy
|
48
|
+
self.update_attributes(self.class.restorable_config.field => true, self.class.restorable_config.timestamp_field => ::DateTime.now)
|
49
|
+
end
|
50
|
+
|
51
|
+
def restore
|
52
|
+
self.update_attributes(self.class.restorable_config.field => false, self.class.restorable_config.timestamp_field => ::DateTime.now)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.apply_mixin(target, options)
|
56
|
+
target.restorable_config.merge!(options)
|
57
|
+
|
58
|
+
target.setup_restorable!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module Trax
|
3
2
|
module Model
|
4
3
|
module Mixins
|
@@ -12,16 +11,16 @@ module Trax
|
|
12
11
|
end
|
13
12
|
|
14
13
|
included do
|
15
|
-
after_initialize :
|
16
|
-
after_initialize :
|
14
|
+
after_initialize :set_kind_from_type
|
15
|
+
after_initialize :set_type_from_kind
|
17
16
|
end
|
18
17
|
|
19
18
|
def set_type_from_kind
|
20
|
-
self[:type] = self.class.kind_to_type_mapping[self[:kind]] if !self[:type]
|
19
|
+
self[:type] = self.class.kind_to_type_mapping[self[:kind]] if self.has_attribute?(:kind) && self.has_attribute?(:type) && !self[:type]
|
21
20
|
end
|
22
21
|
|
23
22
|
def set_kind_from_type
|
24
|
-
self[:kind] = self.class.type_to_kind_mapping[self[:type]] if !self[:kind]
|
23
|
+
self[:kind] = self.class.type_to_kind_mapping[self[:type]] if self.has_attribute?(:kind) && self.has_attribute?(:type) && self.has_attribute?(:type) && !self[:kind]
|
25
24
|
end
|
26
25
|
|
27
26
|
module ClassMethods
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Trax
|
2
|
+
module Model
|
3
|
+
module Mixins
|
4
|
+
module UniqueId
|
5
|
+
extend ::Trax::Model::Mixin
|
6
|
+
|
7
|
+
define_configuration_options! do
|
8
|
+
option :uuid_column, :default => :id
|
9
|
+
option :uuid_map, :default => {}
|
10
|
+
end
|
11
|
+
|
12
|
+
after_included do |options|
|
13
|
+
define_configuration_options!(:unique_id) do
|
14
|
+
option :uuid_prefix,
|
15
|
+
:validates => {
|
16
|
+
:exclusion => {
|
17
|
+
:in => ::Trax::Model::Registry.uuid_map.values
|
18
|
+
},
|
19
|
+
:inclusion => {
|
20
|
+
:in => ::Trax::Model::UUIDPrefix.all,
|
21
|
+
:message => "%{value} not a valid uuid prefix!\nRun Trax::Model::UUIDPrefix.all for valid prefix list"
|
22
|
+
},
|
23
|
+
:allow_nil => true
|
24
|
+
}
|
25
|
+
|
26
|
+
option :uuid_column, :default => ::Trax::Model::Mixins::UniqueId.config.uuid_column
|
27
|
+
|
28
|
+
klass do
|
29
|
+
def uuid_prefix=(prefix)
|
30
|
+
if(::Trax::Model::Mixins::UniqueId.config.uuid_map.values.include?(prefix) && ::Trax::Model::Mixins::UniqueId.config.uuid_map[self.source.name] != prefix)
|
31
|
+
raise ::Trax::Model::Errors::DuplicatePrefixRegistered.new(:prefix => prefix, :model => self.source.name)
|
32
|
+
end
|
33
|
+
|
34
|
+
::Trax::Model::Mixins::UniqueId.config.uuid_map[self.source.name] = prefix
|
35
|
+
super(::Trax::Model::UUIDPrefix.new(prefix))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
#grab prefix from uuid registry if uuids are defined in an initializer
|
42
|
+
if ::Trax::Model.mixin_registry.key?(:unique_id) && ::Trax::Model::UUID.klass_prefix_map.key?(self.name)
|
43
|
+
self.unique_id_config.uuid_prefix = ::Trax::Model::UUID.klass_prefix_map[self.name]
|
44
|
+
end
|
45
|
+
|
46
|
+
self.unique_id_config.merge!(options)
|
47
|
+
|
48
|
+
if(self.unique_id_config.uuid_prefix)
|
49
|
+
default_value_for(:"#{self.unique_id_config.uuid_column}") {
|
50
|
+
::Trax::Model::UUID.generate(self.unique_id_config.uuid_prefix)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def uuid
|
56
|
+
uuid_column = self.class.unique_id_config.uuid_column
|
57
|
+
uuid_value = (uuid_column == "uuid") ? super : __send__(uuid_column)
|
58
|
+
|
59
|
+
::Trax::Model::UUID.new(uuid_value)
|
60
|
+
end
|
61
|
+
|
62
|
+
#i.e. Blog::Post
|
63
|
+
def uuid_type
|
64
|
+
uuid.record_type
|
65
|
+
end
|
66
|
+
|
67
|
+
#i.e. 'Blog::Post'
|
68
|
+
def uuid_type_name
|
69
|
+
uuid.record_type.name
|
70
|
+
end
|
71
|
+
|
72
|
+
#i.e, Blog::Post will = post
|
73
|
+
def uuid_type_slug
|
74
|
+
uuid.record_type.name.demodulize.underscore
|
75
|
+
end
|
76
|
+
|
77
|
+
module ClassMethods
|
78
|
+
def uuid_prefix
|
79
|
+
self.unique_id_config.uuid_prefix
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/trax/model/railtie.rb
CHANGED
@@ -3,8 +3,10 @@ module Trax
|
|
3
3
|
class Railtie < ::Rails::Railtie
|
4
4
|
::ActiveSupport.on_load(:active_record) do
|
5
5
|
def self.inherited(subklass)
|
6
|
-
|
7
|
-
|
6
|
+
if ::Trax::Model.config.auto_include
|
7
|
+
subklass.include(::Trax::Model)
|
8
|
+
subklass.include(::Trax::Model::Attributes::Dsl)
|
9
|
+
end
|
8
10
|
|
9
11
|
super(subklass)
|
10
12
|
|
@@ -4,6 +4,7 @@
|
|
4
4
|
class JsonAttributeValidator < ActiveModel::EachValidator
|
5
5
|
def validate_each(object, attribute, value)
|
6
6
|
json_attribute = object.class.fields_module[attribute]
|
7
|
+
value = json_attribute.new(value || {}) unless value.is_a?(json_attribute)
|
7
8
|
|
8
9
|
value.instance_variable_set("@record", object)
|
9
10
|
|
data/lib/trax_model/version.rb
CHANGED
@@ -4,7 +4,7 @@ DEFAULT_TABLES = Proc.new do
|
|
4
4
|
t.integer "kind"
|
5
5
|
t.integer "make"
|
6
6
|
t.integer "model"
|
7
|
-
t.string "uuid"
|
7
|
+
t.string "uuid"
|
8
8
|
t.datetime "created_at", :null => false
|
9
9
|
t.datetime "updated_at", :null => false
|
10
10
|
end
|
@@ -58,20 +58,4 @@ DEFAULT_TABLES = Proc.new do
|
|
58
58
|
t.datetime "created_at", :null => false
|
59
59
|
t.datetime "updated_at", :null => false
|
60
60
|
end
|
61
|
-
|
62
|
-
create_table "staplers", :force => true do |t|
|
63
|
-
t.string "name"
|
64
|
-
t.string "type"
|
65
|
-
t.integer "attribute_set_id"
|
66
|
-
t.datetime "created_at", :null => false
|
67
|
-
t.datetime "updated_at", :null => false
|
68
|
-
end
|
69
|
-
|
70
|
-
create_table "swingline_stapler_attribute_sets", :force => true do |t|
|
71
|
-
t.float "speed"
|
72
|
-
t.string "owner"
|
73
|
-
|
74
|
-
t.datetime "created_at", :null => false
|
75
|
-
t.datetime "updated_at", :null => false
|
76
|
-
end
|
77
61
|
end
|
data/spec/db/schema/pg_tables.rb
CHANGED
@@ -16,6 +16,21 @@ PG_TABLES = Proc.new do
|
|
16
16
|
t.datetime "updated_at", :null => false
|
17
17
|
end
|
18
18
|
|
19
|
+
create_table "ecommerce_votes", :id => :uuid, :force => true do |t|
|
20
|
+
t.uuid "voteable_id"
|
21
|
+
t.jsonb "upvoter_ids"
|
22
|
+
t.jsonb "downvoter_ids"
|
23
|
+
t.datetime "created_at", :null => false
|
24
|
+
t.datetime "updated_at", :null => false
|
25
|
+
end
|
26
|
+
|
27
|
+
create_table "ecommerce_users", :id => :uuid, :force => true do |t|
|
28
|
+
t.string "name"
|
29
|
+
t.text "watched_product_ids", :array => true
|
30
|
+
t.datetime "created_at", :null => false
|
31
|
+
t.datetime "updated_at", :null => false
|
32
|
+
end
|
33
|
+
|
19
34
|
create_table "ecommerce_product_attribute_sets", :id => :uuid, :force => true do |t|
|
20
35
|
t.uuid "user_id"
|
21
36
|
t.uuid "product_id"
|
data/spec/support/models.rb
CHANGED
@@ -26,7 +26,7 @@ end
|
|
26
26
|
|
27
27
|
class Product < ::ActiveRecord::Base
|
28
28
|
include ::Trax::Model
|
29
|
-
include ::Trax::Model::Attributes::
|
29
|
+
include ::Trax::Model::Attributes::Dsl
|
30
30
|
|
31
31
|
mixins :unique_id => {
|
32
32
|
:uuid_column => "uuid",
|
@@ -34,6 +34,12 @@ class Product < ::ActiveRecord::Base
|
|
34
34
|
}
|
35
35
|
|
36
36
|
define_attributes do
|
37
|
+
string :name
|
38
|
+
# float :price
|
39
|
+
|
40
|
+
integer :in_stock_quantity
|
41
|
+
integer :out_of_stock_quantity
|
42
|
+
|
37
43
|
enum :status, :default => :in_stock do
|
38
44
|
define :in_stock, 1
|
39
45
|
define :out_of_stock, 2
|
@@ -47,12 +53,12 @@ end
|
|
47
53
|
module Products
|
48
54
|
class Shoes < Product
|
49
55
|
include ::Trax::Model
|
50
|
-
include ::Trax::Model::Attributes::
|
56
|
+
include ::Trax::Model::Attributes::Dsl
|
51
57
|
end
|
52
58
|
|
53
59
|
class MensShoes < Shoes
|
54
60
|
include ::Trax::Model
|
55
|
-
include ::Trax::Model::Attributes::
|
61
|
+
include ::Trax::Model::Attributes::Dsl
|
56
62
|
|
57
63
|
define_attributes do
|
58
64
|
enum :size, :default => :mens_9 do
|
@@ -72,7 +78,7 @@ end
|
|
72
78
|
|
73
79
|
class Vehicle < ::ActiveRecord::Base
|
74
80
|
include ::Trax::Model
|
75
|
-
include ::Trax::Model::Attributes::
|
81
|
+
include ::Trax::Model::Attributes::Dsl
|
76
82
|
|
77
83
|
mixins :unique_id => { :uuid_column => "uuid", :uuid_prefix => "9c" },
|
78
84
|
:sti_enum => true
|
@@ -138,19 +144,8 @@ class Person < ::ActiveRecord::Base
|
|
138
144
|
mixins :unique_id => { :uuid_column => "uuid", :uuid_prefix => "5a" }
|
139
145
|
end
|
140
146
|
|
141
|
-
class Stapler < ::ActiveRecord::Base
|
142
|
-
include ::Trax::Model
|
143
|
-
end
|
144
|
-
|
145
|
-
class SwinglineStapler < ::Stapler
|
146
|
-
include ::Trax::Model::STI::Attributes
|
147
|
-
end
|
148
|
-
|
149
|
-
class SwinglineStaplerAttributeSet < ::ActiveRecord::Base
|
150
|
-
end
|
151
|
-
|
152
147
|
class StoreCategory < ::Trax::Core::Types::Struct
|
153
|
-
include ::Trax::Model::
|
148
|
+
include ::Trax::Model::ExtensionsFor::Struct
|
154
149
|
|
155
150
|
string :name
|
156
151
|
struct :meta_attributes do
|