trax_core 0.0.71 → 0.0.72

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: 00148fce6abf94b4bae0f495890d58d637c7ef7c
4
- data.tar.gz: 6b997761c5627bef815cadab245859c82b08e1d1
3
+ metadata.gz: c6d1154c6a3219971c25e70ac2c4a820f313740d
4
+ data.tar.gz: ba70a2bd38733dc7c401d4750e1ce4f86313df9c
5
5
  SHA512:
6
- metadata.gz: 5135d5b5f0937409b9149c47c9b38fc813192d7b0bd3637a10181ceea66aabc5f833ed60bad04aec99c380265dc0462d58eed83d177b9a67910d4fd0656aa234
7
- data.tar.gz: fd4d5910f334c643e5b1120098f1d601dab9a1facd9473359f1211df0dbeda18ffee17ac95408c91f3b3e753f187f0d8ba204010873fd7d62df382d80dc6fc49
6
+ metadata.gz: 9c3ef17bf573140d83ab0d9f7f67de7d3d6c70174f28fca5db8c38cfb2fa19f7fc06c0be3165499e55820773360dd2769e75313c758c9e121aed3cb3067ef2a2
7
+ data.tar.gz: df4bb2354da8d72a729e951193dbe2d640c8d4b6c6b6a8ebd4e446025d726858e68a0802aa2325a425795125d0bf2c2e4e5026467df66c1473a1cdbaebb49cb8
@@ -1,47 +1,49 @@
1
1
  module Trax
2
2
  module Core
3
3
  module Concern
4
- def included(base = nil, &block)
5
- super(base, &block)
4
+ def self.extended(base)
5
+ base.extend(::ActiveSupport::Concern)
6
6
 
7
7
  trace = ::TracePoint.new(:end) do |tracepoint|
8
- if tracepoint.self == base
9
- trace.disable
10
-
11
- if self.instance_variable_defined?(:@_after_included_block)
12
- base.instance_eval(&self.instance_variable_get(:@_after_included_block))
8
+ if tracepoint.self.singleton_class.included_modules.first == base
9
+ if base.instance_variable_defined?(:@_after_extended_block)
10
+ tracepoint.self.module_exec(base, &base.instance_variable_get(:@_after_extended_block))
13
11
  end
12
+
13
+ trace.disable
14
14
  end
15
15
  end
16
16
 
17
17
  trace.enable
18
- end
19
18
 
20
- def self.extended(base)
21
- base.extend(::ActiveSupport::Concern)
19
+ base
20
+ end
22
21
 
23
- super(base)
22
+ def included(base = nil, &block)
23
+ super(base, &block) if defined?(super)
24
24
 
25
25
  trace = ::TracePoint.new(:end) do |tracepoint|
26
26
  if tracepoint.self == base
27
- trace.disable
28
-
29
- if base.instance_variable_defined?(:@_after_extended_block)
30
- base.instance_variable_get(:@_after_extended_block).call
27
+ if self.instance_variable_defined?(:@_after_included_block)
28
+ base.instance_eval(&self.instance_variable_get(:@_after_included_block))
31
29
  end
30
+
31
+ trace.disable
32
32
  end
33
33
  end
34
34
 
35
35
  trace.enable
36
- end
37
36
 
38
- def after_extended(&block)
39
- self.instance_variable_set(:@_after_extended_block, block)
37
+ base
40
38
  end
41
39
 
42
40
  def after_included(&block)
43
41
  self.instance_variable_set(:@_after_included_block, block)
44
42
  end
43
+
44
+ def after_extended(&block)
45
+ self.instance_variable_set(:@_after_extended_block, block)
46
+ end
45
47
  end
46
48
  end
47
49
  end
@@ -9,52 +9,92 @@ module Trax
9
9
 
10
10
  class_attribute :source
11
11
 
12
- def initialize
13
- set_default_values
14
-
15
- yield self if block_given?
16
-
17
- raise_errors unless self.valid?
18
- end
19
-
20
- def set_default_values
21
- self.class.configurable_options.select{|attr_name, hash| hash.key?(:default) }.each_pair do |attr_name,hash|
22
- __send__("#{attr_name}=", hash[:default])
23
- end
12
+ def self.after_configured(&block)
13
+ self.instance_variable_set("@_after_configured_block", block)
24
14
  end
25
15
 
26
16
  def self.inherited(subklass)
27
17
  super(subklass)
28
18
 
19
+ subklass.class_attribute :options_module
20
+ subklass.options_module = subklass.const_set("Options", ::Module.new)
21
+ subklass.include(subklass.options_module)
22
+
29
23
  subklass.class_attribute :configurable_options
30
24
  subklass.configurable_options = {}
31
25
  end
32
26
 
27
+ #the reason for defining the methods in the options module which gets
28
+ #dynamically created is to preserve the inheritance chain
29
+ #so def something= can be overwritten, and call super, an example is in
30
+ #Trax::Model::UniqueId
31
+ #there probably is a cleaner way to do it though.
33
32
  def self.option(attr_name, options = {})
34
- attr_accessor attr_name
35
-
36
33
  validates_presence_of(attr_name) if(options.key?(:required))
37
-
38
34
  if(options.key?(:validates))
39
35
  validates(attr_name, options[:validates])
40
36
  end
41
37
 
42
- define_method("#{attr_name}=") do |val|
43
- value = options.key?(:setter) ? options[:setter].call(val) : val
44
- instance_variable_set("@#{attr_name}", value)
38
+ options_module.module_eval do
39
+ attr_reader(attr_name)
45
40
 
46
- raise_errors unless self.valid?
47
- end
41
+ define_method(:"#{attr_name}=") do |val|
42
+ value = options.key?(:setter) ? options[:setter].call(val) : val
43
+ instance_variable_set("@#{attr_name}", value)
44
+
45
+ raise_errors unless self.valid?
46
+ end
48
47
 
49
- if(options.key?(:getter))
50
- define_method(attr_name) do |val|
51
- options[:getter].call(val)
48
+ if(options.key?(:getter))
49
+ define_method(attr_name) do |val|
50
+ options[:getter].call(val)
51
+ end
52
52
  end
53
53
  end
54
54
 
55
55
  self.configurable_options[attr_name] = options
56
56
  end
57
57
 
58
+ def self.klass(&block)
59
+ #so we can properly resolve super lookups, we define new module and include
60
+ mod = ::Module.new
61
+ mod.module_eval(&block)
62
+ include(mod)
63
+ end
64
+
65
+ def initialize
66
+ set_default_values
67
+
68
+ yield self if block_given?
69
+
70
+ raise_errors unless self.valid?
71
+
72
+ self.class.instance_variable_get("@_after_configured_block").call(self) if self.class.instance_variable_defined?("@_after_configured_block")
73
+ end
74
+
75
+ def compact
76
+ cached_hash.compact
77
+ end
78
+
79
+ def cached_hash
80
+ @cached_hash ||= hash
81
+ end
82
+
83
+ def hash
84
+ configurable_options.keys.each_with_object({}) do |key, result|
85
+ result[key] = __send__(key)
86
+ end
87
+ end
88
+
89
+ def set_default_values
90
+ self.class.configurable_options.select{|attr_name, hash| hash.key?(:default) }.each_pair do |attr_name, hash|
91
+ parent_context = self.class.parent_name.try(:constantize) if self.class.try(:parent_name)
92
+
93
+ default_value_for_option = hash[:default].is_a?(Proc) ? self.instance_exec(parent_context, &hash[:default]) : hash[:default]
94
+ __send__("#{attr_name}=", default_value_for_option)
95
+ end
96
+ end
97
+
58
98
  def merge!(options = {})
59
99
  options.each_pair{ |k,v| __send__("#{k}=", v) }
60
100
  end
@@ -0,0 +1,6 @@
1
+ module Trax
2
+ module Core
3
+ class Definition < ::Hashie::Mash
4
+ end
5
+ end
6
+ end
@@ -6,16 +6,8 @@ module Trax
6
6
  source_file_path = caller[0].partition(":")[0]
7
7
 
8
8
  base.module_eval do
9
- extend ::ActiveSupport::Autoload
10
-
11
9
  @eager_autoload_filepath = source_file_path
12
10
  end
13
-
14
- base.autoload_class_names.each do |klass|
15
- base.autoload :"#{klass}"
16
- end
17
-
18
- base.eager_load!
19
11
  end
20
12
 
21
13
  def all
@@ -72,7 +72,7 @@ module Trax
72
72
 
73
73
  attr_reader :arguments_instance
74
74
 
75
- def initialize(_attributes = {})
75
+ def initialize(**_attributes)
76
76
  @arguments_instance = self.class.permitted_arguments_klass.new(_attributes)
77
77
 
78
78
  super(message)
@@ -103,6 +103,22 @@ module Trax
103
103
  "registry. Registered mixins were #{mixin_namespace.mixin_registry.keys.join(', ')} \n"
104
104
  }
105
105
  end
106
+
107
+ class DuplicateEnumValue < ::Trax::Core::Errors::Base
108
+ argument :value
109
+ argument :klass
110
+ message {
111
+ "#{klass} duplicate value #{value}"
112
+ }
113
+ end
114
+
115
+ class InvalidEnumValue < ::Trax::Core::Errors::Base
116
+ argument :field
117
+ argument :value
118
+ message {
119
+ "#{field} Invalid enum value for #{value} "
120
+ }
121
+ end
106
122
  end
107
123
  end
108
124
  end
@@ -0,0 +1,26 @@
1
+ class Array
2
+ #inspired by: http://thepugautomatic.com/2014/11/array-to-proc-for-hash-access/
3
+ def to_proc
4
+ ->(hash_or_object) {
5
+ if hash_or_object.is_a?(::Hash)
6
+ length == 1 ? hash_or_object[first] : hash_or_object.values_at(*self)
7
+ else
8
+ length == 1 ? hash_or_object.__send__(first) : self.each_with_object({}){ |method_name,result|
9
+ result[method_name] = hash_or_object.__send__(method_name)
10
+ }
11
+ end
12
+ }
13
+ end
14
+
15
+ def flat_compact_uniq!
16
+ self.flatten!
17
+ self.compact!
18
+ self.uniq!
19
+ self
20
+ end
21
+ alias :flatten_compact_uniq! :flat_compact_uniq!
22
+
23
+ def to_single_quoted_list
24
+ "\'#{self.join("', '")}\'"
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ class Class
2
+ def superclasses_until(klass, bottom_klass=self, superclass_chain = [])
3
+ if bottom_klass.superclass != klass
4
+ superclass_chain.unshift(bottom_klass.superclass)
5
+ return superclasses_until(klass, bottom_klass.superclass, superclass_chain)
6
+ else
7
+ return superclass_chain
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,50 @@
1
+ class Hash
2
+ ## Returns selected keys, named or renamed as specified
3
+ # myproduct = {:name => "something", :price => "20"}
4
+ # liability = myproduct.tap(&{:cost => :price})
5
+ # liability[:cost] == 20
6
+ ## Note: Tap only works where source is a hash object, so use as otherwise
7
+ # (because tap always returns the object you are tapping)
8
+ # myproduct = ::OpenStruct.new({:name => "something", :price => "20"})
9
+ # liability.as!(&{:cost => :price})
10
+ # liability[:cost] == 20
11
+ #
12
+ # Transforming values:
13
+ # Pass a hash as the value with the key being the source key/method
14
+ # myproduct = ::OpenStruct.new({:name => "something", :price => "20"})
15
+ # my_sale_product = myproduct.as!(&{:sale_price => {:price => ->(val){ val / 2 } } })
16
+ # my_sale_product[:sale_price] == 10
17
+
18
+ def to_proc
19
+ ->(hash_or_object) {
20
+ new_hash = {}
21
+
22
+ if hash_or_object.is_a?(::Hash)
23
+ self.each_pair do |k,v|
24
+ if v.is_a?(Hash)
25
+ new_hash[k] = v.values.first.call(hash_or_object[v.keys.first])
26
+ elsif v.is_a?(Proc)
27
+ new_hash[k] = v.call(hash_or_object[k])
28
+ else
29
+ new_hash[k] = hash_or_object[v]
30
+ end
31
+ end
32
+
33
+ hash_or_object.keys.map{ |k| hash_or_object.delete(k) }
34
+ hash_or_object.merge!(new_hash)
35
+ else
36
+ self.each_pair do |k,v|
37
+ if v.is_a?(Hash)
38
+ new_hash[k] = v.values.first.call(hash_or_object.__send__(v.keys.first))
39
+ elsif v.is_a?(Proc)
40
+ new_hash[k] = v.call(hash_or_object.__send__(k))
41
+ else
42
+ new_hash[k] = hash_or_object.__send__(v)
43
+ end
44
+ end
45
+ end
46
+
47
+ return new_hash
48
+ }
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ class Is
2
+ def self.truthy?(val)
3
+ [true, false].include?(val)
4
+ end
5
+
6
+ def self.numeric?(val)
7
+ val.is_a?(::Numeric)
8
+ end
9
+
10
+ def self.string?(val)
11
+ val.is_a?(::String)
12
+ end
13
+
14
+ def self.symbol?(val)
15
+ val.is_a?(::Symbol)
16
+ end
17
+
18
+ def self.symbolic?(val)
19
+ val.is_a?(::String) || val.is_a?(::Symbol)
20
+ end
21
+ end
@@ -1,6 +1,10 @@
1
1
  require "active_support/core_ext/object/try"
2
- require 'pry'
2
+
3
3
  class Object
4
+ def as!
5
+ yield self
6
+ end
7
+
4
8
  # Defines a Configuration Class within a target module namespace, or nested class
5
9
  # i.e. configuration_for(::Ecommerce::Cart) will define
6
10
  # Ecommerce::Cart::Configuration class, inherited form Trax::Core::Configuration
@@ -45,8 +49,10 @@ class Object
45
49
 
46
50
  def remove_instance_variables(*args)
47
51
  args.map{ |ivar_name|
48
- remove_instance_variable(:"@#{ivar_name}") if instance_variable_defined?(:"@#{ivar_name}")
52
+ ivar_name = ivar_name.ivar? ? ivar_name : :"@#{ivar_name}"
53
+ remove_instance_variable(ivar_name) if instance_variable_defined?(ivar_name)
49
54
  }
55
+
50
56
  self
51
57
  end
52
58
  alias_method :reset_instance_variables, :remove_instance_variables
@@ -1,4 +1,8 @@
1
1
  class String
2
+ def symbolize
3
+ self.try_chain(:demodulize, :underscore, :to_sym)
4
+ end
5
+
2
6
  def translate(*args)
3
7
  I18n.translate(self.underscore, *args)
4
8
  end
@@ -0,0 +1,6 @@
1
+ class Symbol
2
+ def is_ivar?
3
+ id2name.starts_with?("@")
4
+ end
5
+ alias :ivar? :is_ivar?
6
+ end
@@ -0,0 +1,9 @@
1
+ module URIExtensions
2
+ def join(*args)
3
+ self + args.map{ |arg| arg.is_a?(::String) ? arg : arg.to_s }.join("/")
4
+ end
5
+ end
6
+
7
+ class URI::Generic
8
+ include URIExtensions
9
+ end
@@ -0,0 +1,56 @@
1
+ module Trax
2
+ module Core
3
+ module InheritanceHooks
4
+ extend ::ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def inherited(subklass)
8
+ super(subklass)
9
+
10
+ if self.instance_variable_defined?(:@_on_inherited_block)
11
+ subklass.instance_eval(&self.instance_variable_get(:@_on_inherited_block))
12
+ end
13
+
14
+ if subklass.class == Class
15
+ #this supports anonymous classes created with a block passed, i.e.
16
+ # Class.new(Enum, &Proc.new{VAL=1})
17
+ # otherwise Class.new wont be caught by tracepoint statement below
18
+ trace = ::TracePoint.new(:b_return) do |tracepoint|
19
+ if tracepoint.self.class == Class
20
+ if self.instance_variable_defined?(:@_after_inherited_block)
21
+ subklass.instance_eval(&self.instance_variable_get(:@_after_inherited_block))
22
+ end
23
+
24
+ trace.disable
25
+ end
26
+ end
27
+
28
+ trace.enable
29
+ else
30
+ trace = ::TracePoint.new(:end) do |tracepoint|
31
+ if tracepoint.self == subklass
32
+ if self.instance_variable_defined?(:@_after_inherited_block)
33
+ subklass.instance_eval(&self.instance_variable_get(:@_after_inherited_block))
34
+ end
35
+
36
+ trace.disable
37
+ end
38
+ end
39
+
40
+ trace.enable
41
+
42
+ self
43
+ end
44
+ end
45
+
46
+ def after_inherited(&block)
47
+ self.instance_variable_set(:@_after_inherited_block, block)
48
+ end
49
+
50
+ def on_inherited(&block)
51
+ self.instance_variable_set(:@_on_inherited_block, block)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,219 @@
1
+ # require 'trax/core/inheritance_hooks'
2
+ # require 'active_model/attribute_methods'
3
+ ### Examples
4
+ # ProductCategory < Enum
5
+ # CLOTHING = 1
6
+ # SHOES = 2
7
+ # ACCESSORIES = 3
8
+ # end
9
+ # ProductCategory.keys => [:clothing, :shoes, :accessories]
10
+
11
+ # StoreYearlyRevenue < Enum
12
+ # :'0_100000' = 1
13
+ # :'100000_999999' = 2
14
+ # :'1000000_99999999' = 3
15
+ # end
16
+
17
+ ### Accepts either an integer or the name when setting a value
18
+ # ProductCategory.new(1) => #{name: :clothing, :value => 1}
19
+
20
+ class Enum < SimpleDelegator
21
+ class_attribute :allow_nil, :raise_on_invalid
22
+
23
+ ### Class Methods ###
24
+ def self.define_enum_value(const_name, val=nil)
25
+ name = "#{const_name}".underscore.to_sym
26
+ const_name = name.to_s.camelize
27
+ val = (self._values_hash.length + 1) if val.nil?
28
+
29
+ raise ::Trax::Core::Errors::DuplicateEnumValue.new(:klass => self.class.name, :value => const_name) if self === name
30
+ raise ::Trax::Core::Errors::DuplicateEnumValue.new(:klass => self.class.name, :value => val) if self === val
31
+
32
+ value_klass = self.const_set(const_name, Class.new(::EnumValue){
33
+ self.tag = name
34
+ self.value = val
35
+ })
36
+
37
+ self._values_hash[val] = value_klass
38
+ self._names_hash[name] = value_klass
39
+ end
40
+
41
+ def self.[](val)
42
+ if ::Is.numeric?(val)
43
+ self._values_hash[val]
44
+ elsif ::Is.symbolic?(val)
45
+ val = val.to_sym if val.is_a?(String)
46
+ self._names_hash[val]
47
+ elsif val.superclass.name == "EnumValue"
48
+ val = val.to_sym
49
+ self._names_hash[val]
50
+ end
51
+ end
52
+
53
+ def self.as_json(options={})
54
+ choice.to_s
55
+ end
56
+
57
+ def self.choices
58
+ @choices ||= self._values_hash.values
59
+ end
60
+
61
+ def self.formatted_choices
62
+ @formatted_choices ||= choices.each_with_object({}) do |choice, hash|
63
+ hash[choice.to_i] = choice.to_s
64
+ end
65
+ end
66
+
67
+ def self.select_values(*args)
68
+ args.flat_compact_uniq!
69
+ args.map{|arg| self[arg].to_i }
70
+ end
71
+
72
+ def self.define(*args)
73
+ define_enum_value(*args)
74
+ end
75
+
76
+ #define multiple values if its iterable
77
+ def self.define_values(*args)
78
+ args.each_with_index do |arg, i|
79
+ define_enum_value(arg, (i + 1))
80
+ end
81
+ end
82
+
83
+ def self.each(&block)
84
+ keys.each(&block)
85
+ end
86
+
87
+ def self.each_pair(&block)
88
+ self._names_hash.each_pair(&block)
89
+ end
90
+
91
+ def self.keys
92
+ _names_hash.keys
93
+ end
94
+
95
+ def self.key?(name)
96
+ _names_hash.key?(name)
97
+ end
98
+
99
+ def self.names
100
+ _names_hash.values
101
+ end
102
+
103
+ def self.no_raise_mode?
104
+ !raise_on_invalid
105
+ end
106
+
107
+ def self.valid_name?(val)
108
+ _names_as_strings.include?(val)
109
+ end
110
+
111
+ def self.valid_value?(val)
112
+ values.include?(val)
113
+ end
114
+
115
+ #because calling valid_value? in the define_enum_value method is unclear
116
+ def self.value?(val)
117
+ valid_value?(val)
118
+ end
119
+
120
+ def self.values
121
+ _names_hash.values.map(&:to_i)
122
+ end
123
+
124
+ def self.===(val)
125
+ _names_hash.values.any?{|v| v === val }
126
+ end
127
+
128
+ def self.type
129
+ :enum
130
+ end
131
+
132
+ def self.to_schema
133
+ ::Trax::Core::Definition.new(
134
+ :name => self.name.demodulize.underscore,
135
+ :source => self.name,
136
+ :type => :enum,
137
+ :choices => choices.map(&:to_schema),
138
+ :values => keys
139
+ )
140
+ end
141
+
142
+ class << self
143
+ alias :enum_value :define_enum_value
144
+ alias :define :define_enum_value
145
+ attr_accessor :_values_hash
146
+ attr_accessor :_names_hash
147
+ attr_accessor :_names_as_strings
148
+ end
149
+
150
+ ### Hooks ###
151
+ def self.inherited(subklass)
152
+ subklass.instance_variable_set(:@_values_hash, ::Hash.new)
153
+ subklass.instance_variable_set(:@_names_hash, ::Hash.new)
154
+ subklass.allow_nil = false
155
+ subklass.raise_on_invalid = false
156
+ end
157
+
158
+ ### Instance Methods ###
159
+ attr_reader :choice
160
+
161
+ def initialize(val)
162
+ self.choice = val unless val.nil? && self.class.allow_nil
163
+ end
164
+
165
+ def current_index
166
+ self.class.names.index(choice)
167
+ end
168
+
169
+ def choice=(val)
170
+ @choice = valid_choice?(val) ? self.class[val] : nil
171
+
172
+ raise ::Trax::Core::Errors::InvalidEnumValue.new(
173
+ :field => self.class.name,
174
+ :value => val
175
+ ) if self.class.raise_on_invalid && !@choice
176
+
177
+ @choice
178
+ end
179
+
180
+ def __getobj__
181
+ @choice || nil
182
+ end
183
+
184
+ def next_value
185
+ return choice if self.class.names.length == current_index
186
+ self.class.names[(current_index + 1)]
187
+ end
188
+
189
+ def next_value?
190
+ !(current_index == (self.class.names.length - 1))
191
+ end
192
+
193
+ #set choice if next value exists, return selected choi
194
+ def select_next_value
195
+ self.choice = next_value.to_sym if next_value?
196
+ self
197
+ end
198
+
199
+ def select_previous_value
200
+ self.choice = previous_value.to_sym if previous_value?
201
+ self
202
+ end
203
+
204
+ def previous_value
205
+ self.class.names[(current_index - 1)]
206
+ end
207
+
208
+ def previous_value?
209
+ !!current_index
210
+ end
211
+
212
+ def to_s
213
+ choice.to_s
214
+ end
215
+
216
+ def valid_choice?(val)
217
+ self.class === val
218
+ end
219
+ end