trax_model 0.0.95 → 0.0.96
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/lib/trax/model/attributes/types/enum.rb +6 -3
- data/lib/trax/model/attributes/types/json.rb +130 -11
- data/lib/trax/model/struct.rb +0 -10
- data/lib/trax/model/unique_id.rb +0 -1
- data/lib/trax/validators/json_attribute_validator.rb +1 -1
- data/lib/trax_model/version.rb +1 -1
- data/trax_model.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41cea382b5de1b943f513df7167f86adb4912f94
|
|
4
|
+
data.tar.gz: 86a810a545fe00b3de9b759f1be14b82fa632069
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93c99a50811671b71bb4a4156ac3200e019d28a03611a80e8ddb0cc9184d830d8129d9f20f6c88c67ec2b93e03bfd82684bbdfb7df7da99c683ba54c1fd2b7bd
|
|
7
|
+
data.tar.gz: 2b90612a719954a3f0027c6792d14af4a5e445a99b15fd392b57ea597d5439354e54cec3530f223a44cdf46f5f0e5ca0a840e6ddf012cfac4a06ce937334b254
|
|
@@ -8,10 +8,13 @@ module Trax
|
|
|
8
8
|
#note: we dont validate enum attribute value because typecaster will turn it into nil which we allow
|
|
9
9
|
def self.define_attribute(klass, attribute_name, **options, &block)
|
|
10
10
|
klass_name = "#{klass.fields_module.name.underscore}/#{attribute_name}".camelize
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
attribute_klass = if options.key?(:extend)
|
|
13
|
+
_klass_prototype = options[:extend].constantize
|
|
14
|
+
_klass = ::Trax::Core::NamedClass.new(klass_name, _klass_prototype, :parent_definition => klass, &block)
|
|
15
|
+
_klass
|
|
13
16
|
else
|
|
14
|
-
::Trax::Core::NamedClass.new(klass_name, ::Enum, :parent_definition => klass, &block)
|
|
17
|
+
::Trax::Core::NamedClass.new(klass_name, ::Trax::Core::Types::Enum, :parent_definition => klass, &block)
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
klass.attribute(attribute_name, ::Trax::Model::Attributes::Types::Enum::TypeCaster.new(target_klass: attribute_klass))
|
|
@@ -8,6 +8,8 @@ module Trax
|
|
|
8
8
|
module ValueExtensions
|
|
9
9
|
extend ::ActiveSupport::Concern
|
|
10
10
|
|
|
11
|
+
include ::ActiveModel::Validations
|
|
12
|
+
|
|
11
13
|
def inspect
|
|
12
14
|
self.to_hash.inspect
|
|
13
15
|
end
|
|
@@ -16,20 +18,108 @@ module Trax
|
|
|
16
18
|
self.to_hash.to_json
|
|
17
19
|
end
|
|
18
20
|
|
|
21
|
+
def to_serializable_hash
|
|
22
|
+
_serializable_hash = to_hash
|
|
23
|
+
|
|
24
|
+
self.class.fields_module.enums.keys.each do |attribute_name|
|
|
25
|
+
_serializable_hash[attribute_name] = _serializable_hash[attribute_name].try(:to_i)
|
|
26
|
+
end if self.class.fields_module.enums.keys.any?
|
|
27
|
+
|
|
28
|
+
_serializable_hash
|
|
29
|
+
end
|
|
30
|
+
|
|
19
31
|
module ClassMethods
|
|
20
32
|
def type; :struct end;
|
|
21
33
|
|
|
22
34
|
def permitted_keys
|
|
23
35
|
@permitted_keys ||= properties.map(&:to_sym)
|
|
24
36
|
end
|
|
37
|
+
|
|
38
|
+
#this only supports properties 1 level deep, but works beautifully
|
|
39
|
+
#I.E. for this structure
|
|
40
|
+
# define_attributes do
|
|
41
|
+
# struct :custom_fields do
|
|
42
|
+
# enum :color, :default => :blue do
|
|
43
|
+
# define :blue, 1
|
|
44
|
+
# define :red, 2
|
|
45
|
+
# define :green, 3
|
|
46
|
+
# end
|
|
47
|
+
# end
|
|
48
|
+
# end
|
|
49
|
+
# ::Product.by_custom_fields_color(:blue, :red)
|
|
50
|
+
# will return #{Product color=blue}, #{Product color=red}
|
|
51
|
+
def define_scopes_for_enum(attribute_name, enum_klass)
|
|
52
|
+
return unless has_active_record_ancestry?(enum_klass)
|
|
53
|
+
|
|
54
|
+
model_class = model_class_for_property(enum_klass)
|
|
55
|
+
field_name = enum_klass.parent_definition.name.demodulize.underscore
|
|
56
|
+
attribute_name = enum_klass.name.demodulize.underscore
|
|
57
|
+
scope_name = :"by_#{field_name}_#{attribute_name}"
|
|
58
|
+
model_class.scope(scope_name, lambda{ |*_scope_values|
|
|
59
|
+
_integer_values = enum_klass.select_values(*_scope_values.flat_compact_uniq!)
|
|
60
|
+
_integer_values.map!(&:to_s)
|
|
61
|
+
model_class.where("#{field_name} -> '#{attribute_name}' IN(?)", _integer_values)
|
|
62
|
+
})
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def define_where_scopes_for_boolean_property(attribute_name, property_klass)
|
|
66
|
+
return unless has_active_record_ancestry?(property_klass)
|
|
67
|
+
|
|
68
|
+
model_class = model_class_for_property(property_klass)
|
|
69
|
+
field_name = property_klass.parent_definition.name.demodulize.underscore
|
|
70
|
+
attribute_name = property_klass.name.demodulize.underscore
|
|
71
|
+
scope_name = :"by_#{field_name}_#{attribute_name}"
|
|
72
|
+
model_class.scope(scope_name, lambda{ |*_scope_values|
|
|
73
|
+
_scope_values.map!(&:to_s).flat_compact_uniq!
|
|
74
|
+
model_class.where("#{field_name} -> '#{attribute_name}' IN(?)", _scope_values)
|
|
75
|
+
})
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def define_where_scopes_for_property(attribute_name, property_klass)
|
|
79
|
+
return unless has_active_record_ancestry?(property_klass)
|
|
80
|
+
|
|
81
|
+
model_class = model_class_for_property(property_klass)
|
|
82
|
+
field_name = property_klass.parent_definition.name.demodulize.underscore
|
|
83
|
+
attribute_name = property_klass.name.demodulize.underscore
|
|
84
|
+
scope_name = :"by_#{field_name}_#{attribute_name}"
|
|
85
|
+
|
|
86
|
+
model_class.scope(scope_name, lambda{ |*_scope_values|
|
|
87
|
+
_scope_values.map!(&:to_s).flat_compact_uniq!
|
|
88
|
+
model_class.where("#{field_name} ->> '#{attribute_name}' IN(?)", _scope_values)
|
|
89
|
+
})
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def has_active_record_ancestry?(property_klass)
|
|
93
|
+
return false unless property_klass.respond_to?(:parent_definition)
|
|
94
|
+
|
|
95
|
+
result = if property_klass.parent_definition.ancestors.include?(::ActiveRecord::Base)
|
|
96
|
+
true
|
|
97
|
+
else
|
|
98
|
+
has_active_record_ancestry?(property_klass.parent_definition)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
result
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def model_class_for_property(property_klass)
|
|
105
|
+
result = if property_klass.parent_definition.ancestors.include?(::ActiveRecord::Base)
|
|
106
|
+
property_klass.parent_definition
|
|
107
|
+
else
|
|
108
|
+
model_class_for_property(property_klass.parent_definition)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
result
|
|
112
|
+
end
|
|
113
|
+
|
|
25
114
|
end
|
|
26
115
|
end
|
|
27
116
|
|
|
28
117
|
def self.define_attribute(klass, attribute_name, **options, &block)
|
|
29
118
|
klass_name = "#{klass.fields_module.name.underscore}/#{attribute_name}".camelize
|
|
30
|
-
attribute_klass = if options.key?(:
|
|
31
|
-
|
|
32
|
-
_klass.
|
|
119
|
+
attribute_klass = if options.key?(:extend)
|
|
120
|
+
_klass_prototype = options[:extend].constantize
|
|
121
|
+
_klass = ::Trax::Core::NamedClass.new(klass_name, _klass_prototype, :parent_definition => klass, &block)
|
|
122
|
+
_klass.include(ValueExtensions) unless klass.const_defined?("ValueExtensions")
|
|
33
123
|
_klass
|
|
34
124
|
else
|
|
35
125
|
::Trax::Core::NamedClass.new(klass_name, Value, :parent_definition => klass, &block)
|
|
@@ -39,6 +129,7 @@ module Trax
|
|
|
39
129
|
klass.validates(attribute_name, :json_attribute => true) unless options.key?(:validate) && !options[:validate]
|
|
40
130
|
klass.default_value_for(attribute_name) { {} }
|
|
41
131
|
define_model_accessors(klass, attribute_name, attribute_klass, options[:model_accessors]) if options.key?(:model_accessors) && options[:model_accessors]
|
|
132
|
+
define_model_scopes(klass, attribute_name, attribute_klass, options[:model_scopes]) if options.key?(:model_scopes) && options[:model_scopes]
|
|
42
133
|
end
|
|
43
134
|
|
|
44
135
|
class Value < ::Trax::Model::Struct
|
|
@@ -59,11 +150,11 @@ module Trax
|
|
|
59
150
|
end
|
|
60
151
|
|
|
61
152
|
def type_cast_from_user(value)
|
|
62
|
-
value.is_a?(@target_klass) ?
|
|
153
|
+
value.is_a?(@target_klass) ? value : @target_klass.new(value || {})
|
|
63
154
|
end
|
|
64
155
|
|
|
65
156
|
def type_cast_from_database(value)
|
|
66
|
-
value.present? ? @target_klass.new(JSON.parse(value)) : value
|
|
157
|
+
value.present? ? @target_klass.new(::JSON.parse(value)) : value
|
|
67
158
|
end
|
|
68
159
|
|
|
69
160
|
def type_cast_for_database(value)
|
|
@@ -76,15 +167,43 @@ module Trax
|
|
|
76
167
|
|
|
77
168
|
private
|
|
78
169
|
|
|
170
|
+
def self.define_model_scopes(model, attribute_name, struct_attribute, option_value)
|
|
171
|
+
properties_to_define = if [ true ].include?(option_value)
|
|
172
|
+
struct_attribute.properties.to_a
|
|
173
|
+
elsif option_value.is_a?(Hash) && option_value.has_key?(:only)
|
|
174
|
+
struct_attribute.properties.to_a & option_value[:only]
|
|
175
|
+
elsif option_value.is_a?(Hash) && option_value.has_key?(:except)
|
|
176
|
+
struct_attribute.properties.to_a - option_value[:except]
|
|
177
|
+
elsif option_value.is_a?(Array)
|
|
178
|
+
struct_attribute.properties.to_a & option_value
|
|
179
|
+
else
|
|
180
|
+
raise Trax::Model::Errors::InvalidOption.new(
|
|
181
|
+
:option => :model_scopes,
|
|
182
|
+
:valid_choices => ["true", "array of properties", "hash with :only or :except keys"]
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
properties_to_define.each do |_property|
|
|
187
|
+
getter_method, setter_method = _property.to_sym, :"#{_property}="
|
|
188
|
+
|
|
189
|
+
model.__send__(:define_method, setter_method) do |val|
|
|
190
|
+
self[attribute_name] = {} unless self[attribute_name]
|
|
191
|
+
self.__send__(attribute_name).__send__(setter_method, val)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
model.delegate(getter_method, :to => attribute_name)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
79
198
|
def self.define_model_accessors(model, attribute_name, struct_attribute, option_value)
|
|
80
199
|
properties_to_define = if [ true ].include?(option_value)
|
|
81
200
|
struct_attribute.properties.to_a
|
|
82
|
-
elsif option_value.is_a(Hash) && option_value.has_key?(:only)
|
|
83
|
-
struct_attribute.properties.to_a
|
|
84
|
-
elsif option_value.is_a(Hash) && option_value.has_key?(:except)
|
|
85
|
-
struct_attribute.properties.to_a
|
|
86
|
-
elsif option_value.is_a(Array)
|
|
87
|
-
struct_attribute.properties.to_a
|
|
201
|
+
elsif option_value.is_a?(Hash) && option_value.has_key?(:only)
|
|
202
|
+
struct_attribute.properties.to_a & option_value[:only]
|
|
203
|
+
elsif option_value.is_a?(Hash) && option_value.has_key?(:except)
|
|
204
|
+
struct_attribute.properties.to_a - option_value[:except]
|
|
205
|
+
elsif option_value.is_a?(Array)
|
|
206
|
+
struct_attribute.properties.to_a & option_value
|
|
88
207
|
else
|
|
89
208
|
raise Trax::Model::Errors::InvalidOption.new(
|
|
90
209
|
:option => :model_accessors,
|
data/lib/trax/model/struct.rb
CHANGED
|
@@ -96,16 +96,6 @@ module Trax
|
|
|
96
96
|
|
|
97
97
|
def self.type; :struct end;
|
|
98
98
|
|
|
99
|
-
def to_serializable_hash
|
|
100
|
-
_serializable_hash = to_hash
|
|
101
|
-
|
|
102
|
-
self.class.fields_module.enums.keys.each do |attribute_name|
|
|
103
|
-
_serializable_hash[attribute_name] = _serializable_hash[attribute_name].try(:to_i)
|
|
104
|
-
end if self.class.fields_module.enums.keys.any?
|
|
105
|
-
|
|
106
|
-
_serializable_hash
|
|
107
|
-
end
|
|
108
|
-
|
|
109
99
|
class << self
|
|
110
100
|
alias :boolean :boolean_property
|
|
111
101
|
alias :enum :enum_property
|
data/lib/trax/model/unique_id.rb
CHANGED
|
@@ -10,7 +10,7 @@ class JsonAttributeValidator < ActiveModel::EachValidator
|
|
|
10
10
|
unless value.is_a?(json_attribute) && value.valid?
|
|
11
11
|
if value.is_a?(json_attribute)
|
|
12
12
|
value.errors.messages.each_pair do |k,v|
|
|
13
|
-
v.flatten.join(", ") if v.is_a?(Array)
|
|
13
|
+
v = v.flatten.join(", ") if v.is_a?(Array)
|
|
14
14
|
object.errors.add("#{attribute}.#{k}", v)
|
|
15
15
|
end
|
|
16
16
|
else
|
data/lib/trax_model/version.rb
CHANGED
data/trax_model.gemspec
CHANGED
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_dependency "trax_core", "~> 0.0.
|
|
21
|
+
spec.add_dependency "trax_core", "~> 0.0.80"
|
|
22
22
|
spec.add_dependency "default_value_for", "~> 3.0.0"
|
|
23
23
|
spec.add_dependency "simple_enum"
|
|
24
24
|
spec.add_development_dependency "hashie", ">= 3.4.2"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trax_model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.96
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jason Ayre
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-10-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: trax_core
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.0.
|
|
19
|
+
version: 0.0.80
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.0.
|
|
26
|
+
version: 0.0.80
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: default_value_for
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|