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