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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e9c4e45cdc76295880d1e087727ec1414889bdc
4
- data.tar.gz: eb26cfa1732eaa1e2ba69b3b5448e71e8c229837
3
+ metadata.gz: 41cea382b5de1b943f513df7167f86adb4912f94
4
+ data.tar.gz: 86a810a545fe00b3de9b759f1be14b82fa632069
5
5
  SHA512:
6
- metadata.gz: fc5388aaf9d9a351bc4412357e4d7d2b01ccac35934ac02d9b193aa8eb24814f852e482efa6ee455318c8fe4129c65fda97e2d2e11b19fd8a4a943372eec0dab
7
- data.tar.gz: 0847884f74518a4fe603b92d2e2366b08218ccf7a56a07d4ae057f5ebc783d952fefcfe532de86117fd7e02656e9b682bab9ee463aa94b5f40e8e30c15ecb696
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
- attribute_klass = if options.key?(:class_name)
12
- options[:class_name].constantize
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?(:class_name)
31
- _klass = options[:class_name].constantize
32
- _klass.include(ValueExtensions)
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) ? @target_klass : @target_klass.new(value || {})
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.only(*option_value[:only])
84
- elsif option_value.is_a(Hash) && option_value.has_key?(:except)
85
- struct_attribute.properties.to_a.except(*option_value[:except])
86
- elsif option_value.is_a(Array)
87
- struct_attribute.properties.to_a.only(*option_value[:only])
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,
@@ -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
@@ -10,7 +10,6 @@ module Trax
10
10
 
11
11
  after_included do |options|
12
12
  define_configuration_options!(:unique_id) do
13
-
14
13
  option :uuid_prefix,
15
14
  :validates => {
16
15
  :exclusion => {
@@ -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
@@ -1,3 +1,3 @@
1
1
  module TraxModel
2
- VERSION = '0.0.95'
2
+ VERSION = '0.0.96'
3
3
  end
@@ -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.76"
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.95
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-09-09 00:00:00.000000000 Z
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.76
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.76
26
+ version: 0.0.80
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: default_value_for
29
29
  requirement: !ruby/object:Gem::Requirement