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