trax_core 0.0.6 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0ab417a5f629ffa26dd2ed8aa06606ad0ef8da8
4
- data.tar.gz: 0e40b82964838f3a67ce14188f88fa50a3f53b6b
3
+ metadata.gz: 0fea6e82d277b0d2b84405221ea0c6604efbc2d1
4
+ data.tar.gz: 19e536032336156466c42a90df643e080f2a584e
5
5
  SHA512:
6
- metadata.gz: 0fb3074b04d8a8d4aef67b29c74d0d26fdaf448aeef86e4840a41fd123f6882fce2d93257022440aab3f60678617166ce20e913cef86ebd92595c6fb5af7ced6
7
- data.tar.gz: cb0cc1e316457f2d1a8b62eca08c36de77011b8c752ab7fe364107f40a7b093b245f56de65c8acc90e6400877a5cd690406b80d1a6be2ae9230d972f0ec74e04
6
+ metadata.gz: 02861133c520bfb36217068f12ba983d865bf5d87d478d34e9486753a8e50073250f12ee3f4ddb72384593ceffdb5f629da35ec81220b3e84440154550d79a84
7
+ data.tar.gz: ef5faec34cb92cf6c37078f979911955f02c6c13a45320a1201479b8a061e532a3c7a90b161c5dba4af3b8d61d290da27b9b6c27092dabe989c68ccd1d0871fc
@@ -0,0 +1,68 @@
1
+ module Trax
2
+ module Core
3
+ module AbstractMethods
4
+ extend ::ActiveSupport::Concern
5
+
6
+ included do
7
+ private
8
+ class_attribute :_abstract_methods, :_abstract_class_methods, :_abstract_class_attributes
9
+ self._abstract_methods = []
10
+ self._abstract_class_methods = []
11
+ self._abstract_class_attributes = []
12
+ end
13
+
14
+ module ClassMethods
15
+ def abstract_method(*method_names)
16
+ _abstract_methods.push(*method_names)
17
+ end
18
+ alias :abstract_methods :abstract_method
19
+
20
+ def abstract_class_method(*method_names)
21
+ _abstract_class_methods.push(*method_names)
22
+ end
23
+ alias :abstract_class_methods :abstract_class_method
24
+
25
+ def abstract_class_attribute(*method_names)
26
+ _abstract_class_attributes.push(*method_names)
27
+ class_attribute(*method_names)
28
+ end
29
+ alias :abstract_class_attributes :abstract_class_attribute
30
+
31
+ def inherited(subklass)
32
+ klass = super(subklass)
33
+
34
+ trace = ::TracePoint.new(:end) do |tracepoint|
35
+ if tracepoint.self == subklass #modules also trace end we only care about the class end
36
+ trace.disable
37
+
38
+ if _abstract_methods.any?
39
+ missing_instance_methods = ( Array(_abstract_methods) - subklass.instance_methods(false) )
40
+
41
+ raise NotImplementedError, "#{subklass} must implement the following instance method(s) \n" \
42
+ << "#{missing_instance_methods}" if missing_instance_methods.any?
43
+ end
44
+
45
+ if _abstract_class_methods.any?
46
+ missing_class_methods = ( Array(_abstract_class_methods) - subklass.singleton_methods(false) )
47
+
48
+ raise NotImplementedError, "#{subklass} must implement the following class method(s) \n" \
49
+ << "#{missing_class_methods}" if missing_class_methods.any?
50
+ end
51
+
52
+ if _abstract_class_attributes.any?
53
+ missing_class_attributes = _abstract_class_attributes.select{|_property| subklass.__send__(_property).blank? }
54
+
55
+ raise NotImplementedError, "#{subklass} must set the following class attributes(s) \n" \
56
+ << "#{missing_class_attributes}" if missing_class_attributes.any?
57
+ end
58
+ end
59
+ end
60
+
61
+ trace.enable
62
+
63
+ klass
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,47 @@
1
+ module Trax
2
+ module Core
3
+ module Concern
4
+ def included(base = nil, &block)
5
+ super(base, &block)
6
+
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))
13
+ end
14
+ end
15
+ end
16
+
17
+ trace.enable
18
+ end
19
+
20
+ def self.extended(base)
21
+ base.extend(::ActiveSupport::Concern)
22
+
23
+ super(base)
24
+
25
+ trace = ::TracePoint.new(:end) do |tracepoint|
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
31
+ end
32
+ end
33
+ end
34
+
35
+ trace.enable
36
+ end
37
+
38
+ def after_extended(&block)
39
+ self.instance_variable_set(:@_after_extended_block, block)
40
+ end
41
+
42
+ def after_included(&block)
43
+ self.instance_variable_set(:@_after_included_block, block)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -7,10 +7,12 @@ module Trax
7
7
  class Configuration
8
8
  include ActiveModel::Validations
9
9
 
10
+ class_attribute :source
11
+
10
12
  def initialize
11
13
  set_default_values
12
14
 
13
- yield self
15
+ yield self if block_given?
14
16
 
15
17
  raise_errors unless self.valid?
16
18
  end
@@ -22,6 +24,8 @@ module Trax
22
24
  end
23
25
 
24
26
  def self.inherited(subklass)
27
+ super(subklass)
28
+
25
29
  subklass.class_attribute :configurable_options
26
30
  subklass.configurable_options = {}
27
31
  end
@@ -31,9 +35,30 @@ module Trax
31
35
 
32
36
  validates_presence_of(attr_name) if(options.key?(:required))
33
37
 
38
+ if(options.key?(:validates))
39
+ validates(attr_name, options[:validates])
40
+ end
41
+
42
+ define_method("#{attr_name}=") do |val|
43
+ value = options.key?(:setter) ? options[:setter].call(val) : val
44
+ instance_variable_set("@#{attr_name}", value)
45
+
46
+ raise_errors unless self.valid?
47
+ end
48
+
49
+ if(options.key?(:getter))
50
+ define_method(attr_name) do |val|
51
+ options[:getter].call(val)
52
+ end
53
+ end
54
+
34
55
  self.configurable_options[attr_name] = options
35
56
  end
36
57
 
58
+ def merge!(options = {})
59
+ options.each_pair{ |k,v| __send__("#{k}=", v) }
60
+ end
61
+
37
62
  def raise_errors
38
63
  raise Trax::Core::Errors::ConfigurationError.new(
39
64
  :messages => self.errors.full_messages,
@@ -4,7 +4,7 @@ module Trax
4
4
  def self.extended(base)
5
5
  source_file_path = caller[0].partition(":")[0]
6
6
 
7
- base.class_eval do
7
+ base.module_eval do
8
8
  extend ::ActiveSupport::Autoload
9
9
 
10
10
  @eager_autoload_filepath = source_file_path
@@ -0,0 +1,18 @@
1
+ module Trax
2
+ module Core
3
+ module EagerLoadNamespace
4
+ def self.extended(base)
5
+ source_file_path = caller[0].partition(":")[0]
6
+
7
+ base.module_attribute(:eager_autoload_filepath) { source_file_path }
8
+ base.module_attribute(:module_path) { ::Pathname.new(::File.path(base.eager_autoload_filepath).gsub(".rb", "")) }
9
+
10
+ ::Trax::Core::FS::Directory.new(base.module_path).files.each do |file|
11
+ load file
12
+ end
13
+
14
+ super(base)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -92,6 +92,17 @@ module Trax
92
92
  "#{messages.join('\n')}"
93
93
  }
94
94
  end
95
+
96
+ class MixinNotRegistered < ::Trax::Core::Errors::Base
97
+ argument :mixin
98
+ argument :source
99
+ argument :mixin_namespace
100
+
101
+ message {
102
+ "#{source} tried to load mixin: #{mixin}, whichdoes not exist in " \
103
+ "registry. Registered mixins were #{mixin_namespace.mixin_registry.keys.join(', ')} \n"
104
+ }
105
+ end
95
106
  end
96
107
  end
97
108
  end
@@ -0,0 +1,5 @@
1
+ module Enumerable
2
+ def group_by_count
3
+ ::Hash.new(0).tap{|hash| each{|item| hash[item] += 1 } }
4
+ end
5
+ end
@@ -1,4 +1,11 @@
1
1
  class Module
2
+ def module_attribute(*attribute_names, &block)
3
+ attribute_names.each do |_attribute_name|
4
+ singleton_class.__send__("attr_accessor", _attribute_name)
5
+ instance_variable_set("@#{_attribute_name}", block.call) if block_given?
6
+ end
7
+ end
8
+
2
9
  def recursively_define_namespaced_class(class_name, class_to_inherit_from = Object)
3
10
  paths = class_name.split("::")
4
11
  const_name = paths.shift
@@ -1,35 +1,55 @@
1
1
  require "active_support/core_ext/object/try"
2
-
2
+ require 'pry'
3
3
  class Object
4
4
  # Defines a Configuration Class within a target module namespace, or nested class
5
5
  # i.e. configuration_for(::Ecommerce::Cart) will define
6
6
  # Ecommerce::Cart::Configuration class, inherited form Trax::Core::Configuration
7
7
  # And we can then define specific configuration options, for that class, on that class
8
- def configuration_for(target, &blk)
9
- target.class_eval do
10
- class << self
11
- attr_accessor :_configuration
12
- end
8
+ def configuration_for(target, as = :configuration, run_configuration = false, &blk)
9
+ configuration_ivar_name = (as == :configuration) ? :configuration : :"#{as}_configuration"
10
+ configuration_ivar_name_shortcut = (as == :configuration) ? :config : :"#{as}_config"
11
+ target.const_set(configuration_ivar_name.to_s.classify, ::Class.new(::Trax::Core::Configuration))
12
+ configuration_klass = target.const_get(configuration_ivar_name.to_s.classify)
13
+ configuration_klass.source = target
13
14
 
14
- const_set("Configuration", ::Class.new(::Trax::Core::Configuration))
15
- const_get("Configuration").instance_eval(&blk)
15
+ configurer_method_name = (as == :configuration) ? :configure : :"configure_#{as}"
16
+ target.singleton_class.__send__(:attr_accessor, configuration_ivar_name)
17
+ target.singleton_class.instance_variable_set("@#{configuration_ivar_name}", configuration_klass.instance_eval(&blk))
18
+ target.singleton_class.__send__(:alias_method, configuration_ivar_name_shortcut, configuration_ivar_name)
16
19
 
17
- def self.configure(&block)
18
- @_configuration = const_get("Configuration").new(&block)
19
- end
20
-
21
- def self.config
22
- _configuration
20
+ target.define_singleton_method(configurer_method_name) do |&block|
21
+ if block
22
+ return instance_variable_set("@#{configuration_ivar_name}", configuration_klass.new(&block)) if !instance_variable_get("@#{configuration_ivar_name}")
23
+ return instance_variable_get("@#{configuration_ivar_name}").instance_eval(&block)
24
+ else
25
+ return instance_variable_set("@#{configuration_ivar_name}", configuration_klass.new) if !instance_variable_get("@#{configuration_ivar_name}")
26
+ return instance_variable_get("@#{configuration_ivar_name}")
23
27
  end
24
28
  end
29
+
30
+ target.__send__(configurer_method_name) if run_configuration
25
31
  end
26
32
 
27
- def define_configuration_options(&block)
28
- configuration_for(self, &block)
33
+ def define_configuration_options(as=:configuration, run_configuration = false, &block)
34
+ configuration_for(self, as, run_configuration, &block)
35
+ end
36
+
37
+ def define_configuration_options!(as=:configuration, &block)
38
+ define_configuration_options(as, true, &block)
29
39
  end
30
40
 
31
41
  alias_method :define_configuration, :define_configuration_options
32
42
  alias_method :has_configuration, :define_configuration_options
43
+ alias_method :has_configurable_options, :define_configuration_options
44
+ alias_method :has_configurable_options!, :define_configuration_options!
45
+
46
+ def remove_instance_variables(*args)
47
+ args.map{ |ivar_name|
48
+ remove_instance_variable(:"@#{ivar_name}") if instance_variable_defined?(:"@#{ivar_name}")
49
+ }
50
+ self
51
+ end
52
+ alias_method :reset_instance_variables, :remove_instance_variables
33
53
 
34
54
  #following method stolen from abrandoned https://rubygems.org/gems/try_chain
35
55
  def try_chain(*symbols)
@@ -0,0 +1,9 @@
1
+ class String
2
+ def translate(*args)
3
+ I18n.translate(self.underscore, *args)
4
+ end
5
+
6
+ def translate_words
7
+ self.split(" ").map(&:translate).join(" ")
8
+ end
9
+ end
@@ -0,0 +1,238 @@
1
+ # clearly this should be its own gem
2
+ # or at least parts of it
3
+ # But this is an advanced set of file tools built around ruby stdlib file/dir clases
4
+ # that lets you do stuff like collect all the files in the current directory
5
+ # and its a WIP I ripped out of my project hastily so u done been warned
6
+
7
+ # Examples:
8
+ #
9
+ # Get all files in the current dir
10
+ # ::Trax::Core::FS::CurrentDirectory.new.files
11
+ #
12
+ # Get all ruby files in current dir
13
+ # ::Trax::Core::FS::CurrentDirectory.new.files.by_extension(".rb")
14
+ #
15
+ # Get all ruby files in target directory
16
+ # ::Trax::Core::FS::Directory.new('/users/jayre/whatever').files.by_extension(".rb")
17
+ #
18
+ # RECURSIVELY get files + children files + childrens children (yarr)
19
+ # ::Trax::Core::FS::Directory.new('/users/jayre/whatever').files(true)
20
+ #
21
+
22
+ module Trax
23
+ module Core
24
+ module FS
25
+ module Scopes
26
+ def by_extension(*extensions)
27
+ matches = select{ |file|
28
+ extensions.include?(file.extension)
29
+ }
30
+ end
31
+ end
32
+
33
+ class Files < SimpleDelegator
34
+ include ::Enumerable
35
+ include ::Trax::Core::FS::Scopes
36
+
37
+ attr_accessor :files
38
+
39
+ def initialize(*args)
40
+ @files = (args || []).flatten.compact.uniq
41
+ end
42
+
43
+ def __getobj__
44
+ @files
45
+ end
46
+
47
+ def each(&block)
48
+ @files.each do |file|
49
+ block.call(file)
50
+ end
51
+ end
52
+ end
53
+
54
+ class Directory < SimpleDelegator
55
+ attr_accessor :files, :directories, :path
56
+
57
+ def self.[](path)
58
+ file_path = path.is_a?(Pathname) ? path : ::Pathname.new(path)
59
+ new(file_path)
60
+ end
61
+
62
+ def [](arg)
63
+ self.class.new(@path.join(arg).to_s)
64
+ end
65
+
66
+ def initialize(file_path)
67
+ @path = ::Pathname.new(file_path)
68
+ @dir = ::Dir[@path]
69
+ end
70
+
71
+ def all
72
+ @all ||= ::Dir[path.join("*")].map do |folder_or_file|
73
+ listing = ::Pathname.new(folder_or_file)
74
+ listing.directory? ? self.class.new(listing) : ::Trax::Core::FS::Listing.new(listing)
75
+ end
76
+ end
77
+
78
+ def directories(*args)
79
+ folders(*args)
80
+ end
81
+
82
+ def each
83
+ yield(entries)
84
+ end
85
+
86
+ def entries
87
+ @entries ||= ::Dir.entries(path).map do |file_path|
88
+ directory_file_path = ::Pathname.new(file_path) unless file_path.is_a?(Pathname)
89
+ directory_file_path.directory? ? ::Trax::Core::FS::Directory.new(directory_file_path) : ::Listing.new(directory_file_path)
90
+ end
91
+ end
92
+
93
+ def files(recurse = false)
94
+ @files ||= begin
95
+ if recurse
96
+ current_directory_files = Files.new(all.select{|file_path| file_path.is_a?(::Trax::Core::FS::Listing) })
97
+
98
+ directories.map do |dir|
99
+ next unless dir.files(true) && dir.files(true).any?
100
+ current_directory_files.files += dir.files(true)
101
+ end if directories.any?
102
+
103
+ current_directory_files || ::Trax::Core::FS::Files.new
104
+ else
105
+ Files.new(all.select{|file_path| file_path.is_a?(::Trax::Core::FS::Listing) })
106
+ end
107
+ end
108
+ end
109
+
110
+ def folders(recurse = false)
111
+ @folders ||= begin
112
+ if recurse
113
+ current_directory_directories = all.select{|file_path| file_path.is_a?(::Trax::Core::FS::Directory) }
114
+
115
+ current_directory_directories += folders(true).map do |dir|
116
+ dir.directories(true).any? ? dir.directories(true) : []
117
+ end if directories(true) && directories(true).any?
118
+
119
+ current_directory_directories
120
+ else
121
+ all.select{ |file_path| file_path.is_a?(::Trax::Core::FS::Directory) }
122
+ end
123
+ end
124
+ end
125
+
126
+ def glob(*args)
127
+ args.map do |arg|
128
+ self.dup[arg].flatten.compact.uniq.map{|_path| ::Trax::Core::FS::Listing.new(_path) }
129
+ end.flatten.compact.uniq
130
+ end
131
+
132
+ def __getobj__
133
+ @dir
134
+ end
135
+
136
+ def recursive_files
137
+ files(true)
138
+ end
139
+
140
+ def recursive_folders
141
+ folders(true)
142
+ end
143
+
144
+ def reload
145
+ remove_instance_variable(:@folders) if defined?(:@folders)
146
+ remove_instance_variable(:@files) if defined?(:@files)
147
+ self
148
+ end
149
+
150
+ def images
151
+ files.select{|file| file.image? }
152
+ end
153
+ end
154
+
155
+ class CurrentFileDirectory < SimpleDelegator
156
+ include ::Enumerable
157
+
158
+ def self.[](path)
159
+ file_path = path.is_a?(::Pathname) ? path : ::Pathname.new(path)
160
+ new(file_path)
161
+ end
162
+
163
+ attr_accessor :directory, :path
164
+
165
+ def initialize
166
+ source_file_path = caller[3].partition(":")[0]
167
+ @path = ::Pathname.new(::File.dirname(source_file_path))
168
+ @directory = ::Trax::Core::FS::Directory.new(@path)
169
+ end
170
+
171
+ def __getobj__
172
+ @directory
173
+ end
174
+
175
+ def each
176
+ yield @directory
177
+ end
178
+ end
179
+
180
+ class CurrentDirectory < CurrentFileDirectory
181
+
182
+ end
183
+
184
+ class CurrentWorkingDirectory < SimpleDelegator
185
+ include ::Enumerable
186
+
187
+ attr_accessor :directory, :path
188
+
189
+ def initialize
190
+ @path = ::Pathname.new(::Dir.pwd)
191
+ @directory = ::Trax::Core::FS::Directory.new(@path)
192
+ end
193
+
194
+ def __getobj__
195
+ @directory
196
+ end
197
+
198
+ def each
199
+ yield @directory
200
+ end
201
+ end
202
+
203
+ class Listing < Pathname
204
+ def bitmap?
205
+ return sample[0,2] == "MB"
206
+ end
207
+
208
+ def copy_to(destination)
209
+ ::FileUtils.cp(self, destination)
210
+ end
211
+
212
+ alias_method :extension, :extname
213
+ alias_method :ext, :extname
214
+
215
+ def gif?
216
+ return sample[0,4] == "GIF8"
217
+ end
218
+
219
+ def image?
220
+ bitmap? || gif? || jpeg?
221
+ end
222
+
223
+ def jpeg?
224
+ return sample[0,4] == "\xff\xd8\xff\xe0"
225
+ end
226
+
227
+ def sample
228
+ @sample ||= begin
229
+ f = ::File.open(self.to_s, 'rb')
230
+ result = f.read(9)
231
+ f.close
232
+ result
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,49 @@
1
+ module Trax
2
+ module Core
3
+ module HasMixins
4
+ module ClassMethods
5
+ def register_mixin(mixin_klass, key = nil)
6
+ mixin_key = mixin_klass.respond_to?(:mixin_registry_key) ? mixin_klass.mixin_registry_key : (key || mixin_klass.name.demodulize.underscore.to_sym)
7
+
8
+ return if mixin_registry.key?(mixin_key)
9
+ mixin_registry[mixin_key] = mixin_klass
10
+ end
11
+ end
12
+
13
+ def self.extended(base)
14
+ base.module_attribute(:mixin_registry) { Hash.new }
15
+ base.extend(ClassMethods)
16
+
17
+ base.define_configuration_options! do
18
+ option :auto_include, :default => false
19
+ option :auto_include_mixins, :default => []
20
+ end
21
+
22
+ mixin_module = base.const_set("Mixin", ::Module.new)
23
+ mixin_module.module_attribute(:mixin_namespace) { base }
24
+ mixin_module.extend(::Trax::Core::Mixin)
25
+
26
+ mixin_module.module_eval do
27
+ def self.extended(base)
28
+ base.extend(Trax::Core::Mixin)
29
+ super(base)
30
+ mixin_namespace.register_mixin(base)
31
+ end
32
+ end
33
+
34
+ mixable_module = base.const_set("Mixable", ::Module.new)
35
+ mixable_module.module_attribute(:mixin_namespace) { base }
36
+ mixable_module.extend(::ActiveSupport::Concern)
37
+
38
+ mixable_module.included do
39
+ class_attribute :mixin_namespace
40
+ self.mixin_namespace = base
41
+ end
42
+
43
+ mixable_module.include(::Trax::Core::Mixable)
44
+
45
+ super(base)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ module Trax
2
+ module Core
3
+ module Inheritance
4
+ extend ::ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def inherited(subklass)
8
+ klass = super(subklass)
9
+ klass.class_attribute(:_after_inherited_block)
10
+
11
+ trace = ::TracePoint.new(:end) do |tracepoint|
12
+ if tracepoint.self == subklass
13
+ trace.disable
14
+ end
15
+ end
16
+
17
+ trace.enable
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,77 @@
1
+ module Trax
2
+ module Core
3
+ module IsolatedMixin
4
+ def included(base = nil, &block)
5
+ unless base.respond_to?(:_concerns)
6
+ base.class_attribute :_concerns_config
7
+ base._concerns_confg = {}
8
+ end
9
+
10
+ base.extend(ClassMethods)
11
+
12
+ super(base, &block)
13
+
14
+ trace = ::TracePoint.new(:end) do |tracepoint|
15
+ if tracepoint.self == base
16
+ trace.disable
17
+
18
+ if self.instance_variable_defined?(:@_after_included_block)
19
+ base.instance_eval(&self.instance_variable_get(:@_after_included_block))
20
+ end
21
+
22
+ if self.instance_variable_defined?(:@_on_concern_included_block)
23
+ base.instance_exec(base._concerns_config[self.name.demodulize.underscore.to_sym], &self.instance_variable_get(:@_on_concern_included_block))
24
+ end
25
+ end
26
+ end
27
+
28
+ trace.enable
29
+ end
30
+
31
+ def self.extended(base)
32
+ base.extend(::ActiveSupport::Concern)
33
+ base.extend(::Trax::Core::IsolatedMixin::ClassMethods)
34
+
35
+ super(base)
36
+
37
+ trace = ::TracePoint.new(:end) do |tracepoint|
38
+ if tracepoint.self == base
39
+ trace.disable
40
+
41
+ if base.instance_variable_defined?(:@_after_extended_block)
42
+ base.instance_variable_get(:@_after_extended_block).call
43
+ end
44
+ end
45
+ end
46
+
47
+ trace.enable
48
+ end
49
+
50
+ module ClassMethods
51
+ def configure_concern(name, options = {})
52
+ _concerns_config[name] = options
53
+ end
54
+ end
55
+
56
+ def after_extended(&block)
57
+ self.instance_variable_set(:@_after_extended_block, block)
58
+ end
59
+
60
+ def after_included(&block)
61
+ self.instance_variable_set(:@_after_included_block, block)
62
+ end
63
+
64
+ def mixed_in(&block)
65
+ after_included(&block)
66
+ end
67
+
68
+ def mixed(&block)
69
+ after_included(&block)
70
+ end
71
+
72
+ def on_concern_included(&block)
73
+ self.instance_variable_set(:@_on_concern_included_block, block)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,57 @@
1
+ module Trax
2
+ module Core
3
+ module Mixable
4
+ extend ::ActiveSupport::Concern
5
+
6
+ included do
7
+ class_attribute :registered_mixins
8
+
9
+ self.registered_mixins = {}
10
+ end
11
+
12
+ module ClassMethods
13
+ def mixin(key, options = {})
14
+ raise ::Trax::Core::Errors::MixinNotRegistered.new(
15
+ source: self.name,
16
+ mixin: key,
17
+ mixin_namespace: mixin_namespace
18
+ ) unless mixin_namespace.mixin_registry.key?(key)
19
+
20
+ mixin_module = mixin_namespace.mixin_registry[key]
21
+ self.registered_mixins[key] = mixin_module
22
+
23
+ self.class_eval do
24
+ include(mixin_module) unless self.ancestors.include?(mixin_module)
25
+
26
+ options = {} if options.is_a?(TrueClass)
27
+ options = { options => true } if options.is_a?(Symbol)
28
+
29
+ if mixin_module.instance_variable_defined?(:@_before_mixed_in_block)
30
+ _before_mixed_in_block = mixin_module.instance_variable_get(:@_before_mixed_in_block)
31
+
32
+ instance_exec(&_before_mixed_in_block)
33
+ end
34
+
35
+ if mixin_module.instance_variable_defined?(:@_on_mixed_in_block)
36
+ _on_mixed_in_block = mixin_module.instance_variable_get(:@_on_mixed_in_block)
37
+
38
+ instance_exec(options, &_on_mixed_in_block)
39
+ end
40
+ end
41
+ end
42
+
43
+ def mixins(*args)
44
+ options = args.extract_options!
45
+
46
+ if(!options.blank?)
47
+ options.each_pair do |key, val|
48
+ self.mixin(key, val)
49
+ end
50
+ else
51
+ args.map{ |key| mixin(key) }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,42 @@
1
+ module Trax
2
+ module Core
3
+ module Mixin
4
+ def on_mixed_in(&block)
5
+ self.instance_variable_set(:@_on_mixed_in_block, block)
6
+ end
7
+
8
+ def before_mixed_in(&block)
9
+ self.instance_variable_set(:@_before_mixed_in_block, block)
10
+ end
11
+
12
+ def self.extended(base)
13
+ base.extend(::ActiveSupport::Concern)
14
+
15
+ super(base)
16
+
17
+ trace = ::TracePoint.new(:end) do |tracepoint|
18
+ if tracepoint.self == base
19
+ trace.disable
20
+
21
+ if base.instance_variable_defined?(:@_after_extended_block)
22
+ puts "CALLING AFTER EXTENDED"
23
+ base.instance_variable_get(:@_after_extended_block).call
24
+ end
25
+ end
26
+ end
27
+
28
+ trace.enable
29
+
30
+ super(base)
31
+
32
+ mixin_namespace.register_mixin(base) unless self == ::Trax::Core::Mixin
33
+ end
34
+
35
+ module ClassMethods
36
+ def on_mixed_in(&block)
37
+ self.instance_variable_set(:@_on_mixed_in_block, block)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ module Trax
2
+ module Core
3
+ class MixinRegistry
4
+ def self.extended(base)
5
+ base.extend(::ActiveSupport::PerThreadRegistry)
6
+ super(base)
7
+ end
8
+ end
9
+ end
10
+ end
data/lib/trax/core.rb CHANGED
@@ -1,14 +1,25 @@
1
1
  require 'active_support/all'
2
2
  require_relative './array'
3
+ require_relative './core/ext/enumerable'
3
4
  require_relative './core/ext/module'
4
5
  require_relative './core/ext/object'
6
+ require_relative './core/ext/string'
5
7
 
6
8
  module Trax
7
9
  module Core
8
10
  extend ::ActiveSupport::Autoload
9
11
 
12
+ autoload :AbstractMethods
10
13
  autoload :Configuration
14
+ autoload :Concern
15
+ autoload :EagerLoadNamespace
11
16
  autoload :EagerAutoloadNamespace
12
17
  autoload :Errors
18
+ autoload :FS
19
+ autoload :HasMixins
20
+ autoload :Inheritance
21
+ autoload :Mixin
22
+ autoload :Mixable
23
+ autoload :MixinRegistry
13
24
  end
14
25
  end
@@ -1,3 +1,3 @@
1
1
  module TraxCore
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -1,5 +1,4 @@
1
1
  module Ecom
2
2
  class Widget
3
-
4
3
  end
5
4
  end
@@ -0,0 +1,27 @@
1
+ module FakeNamespace
2
+ module Priceable
3
+ extend ::FakeNamespace::Mixin
4
+
5
+ included do
6
+ class_attribute :default_starting_price
7
+ end
8
+
9
+ on_mixed_in do |options|
10
+ self.default_starting_price = options[:default_starting_price]
11
+ end
12
+
13
+ def some_instance_method
14
+ "some_instance_method_return"
15
+ end
16
+
17
+ def starting_price
18
+ @starting_price || self.class.default_starting_price
19
+ end
20
+
21
+ module ClassMethods
22
+ def some_class_method
23
+ "some_class_method_return"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module FakeNamespace
2
+ extend ::Trax::Core::HasMixins
3
+ extend ::Trax::Core::EagerLoadNamespace
4
+
5
+ end
@@ -0,0 +1,4 @@
1
+ module Storefront
2
+ class Category
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Storefront
2
+ class Product
3
+ include ::FakeNamespace::Mixable
4
+
5
+ mixins :priceable => { :default_starting_price => 9.99 }
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module Storefront
2
+ extend ::Trax::Core::EagerLoadNamespace
3
+
4
+ end
@@ -3,6 +3,16 @@ require 'spec_helper'
3
3
  describe ::Module do
4
4
  subject { Trax::Core }
5
5
 
6
+ describe ".module_attribute" do
7
+ before(:all) do
8
+ Trax.module_attribute(:some_fake_hash) do
9
+ {}
10
+ end
11
+ end
12
+
13
+ it { Trax.some_fake_hash.should be_a(Hash) }
14
+ end
15
+
6
16
  describe ".recursively_define_namespaced_class" do
7
17
  context "when class namespace does not exist at global module level" do
8
18
  before do
@@ -23,4 +23,13 @@ describe ::Object do
23
23
  SomeFakeClass.new.try_chain(:class, :name, :underscore).should eq "some_fake_class"
24
24
  end
25
25
  end
26
+
27
+ describe ".remove_instance_variables" do
28
+ it "reset instance variables by symbol names" do
29
+ obj = SomeFakeClass.new
30
+ obj.instance_variable_set(:@someivar, "anything")
31
+ obj.reset_instance_variables(:someivar)
32
+ obj.instance_variable_get(:@someivar).should be nil
33
+ end
34
+ end
26
35
  end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Trax::Core::HasMixins do
4
+ subject { FakeNamespace }
5
+
6
+ it { expect(subject.const_defined?("Mixin")).to eq true }
7
+ it { expect(subject.mixin_registry).to be_a(Hash) }
8
+ it { expect(subject::Mixin.mixin_namespace).to eq FakeNamespace }
9
+
10
+ context "Priceable Mixin" do
11
+ it {
12
+ expect(::Storefront::Product.new.starting_price).to eq 9.99
13
+ }
14
+
15
+ it "includes class methods" do
16
+ expect(::Storefront::Product.some_class_method).to eq "some_class_method_return"
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trax_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
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-03-21 00:00:00.000000000 Z
11
+ date: 2015-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -265,11 +265,23 @@ files:
265
265
  - lib/trax.rb
266
266
  - lib/trax/array.rb
267
267
  - lib/trax/core.rb
268
+ - lib/trax/core/abstract_methods.rb
269
+ - lib/trax/core/concern.rb
268
270
  - lib/trax/core/configuration.rb
269
271
  - lib/trax/core/eager_autoload_namespace.rb
272
+ - lib/trax/core/eager_load_namespace.rb
270
273
  - lib/trax/core/errors.rb
274
+ - lib/trax/core/ext/enumerable.rb
271
275
  - lib/trax/core/ext/module.rb
272
276
  - lib/trax/core/ext/object.rb
277
+ - lib/trax/core/ext/string.rb
278
+ - lib/trax/core/fs.rb
279
+ - lib/trax/core/has_mixins.rb
280
+ - lib/trax/core/inheritance.rb
281
+ - lib/trax/core/isolated_mixin.rb
282
+ - lib/trax/core/mixable.rb
283
+ - lib/trax/core/mixin.rb
284
+ - lib/trax/core/mixin_registry.rb
273
285
  - lib/trax_core.rb
274
286
  - lib/trax_core/version.rb
275
287
  - spec/spec_helper.rb
@@ -277,11 +289,17 @@ files:
277
289
  - spec/support/ecom/widget.rb
278
290
  - spec/support/ecom/widget_category.rb
279
291
  - spec/support/errors.rb
292
+ - spec/support/fake_namespace.rb
293
+ - spec/support/fake_namespace/priceable.rb
294
+ - spec/support/storefront.rb
295
+ - spec/support/storefront/category.rb
296
+ - spec/support/storefront/product.rb
280
297
  - spec/trax/array_spec.rb
281
298
  - spec/trax/core/eager_autoload_namespace_spec.rb
282
299
  - spec/trax/core/errors_spec.rb
283
300
  - spec/trax/core/ext/module_spec.rb
284
301
  - spec/trax/core/ext/object_spec.rb
302
+ - spec/trax/core/has_mixins_spec.rb
285
303
  - spec/trax/core_spec.rb
286
304
  - trax_core.gemspec
287
305
  homepage: http://github.com/jasonayre/trax_core
@@ -304,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
322
  version: '0'
305
323
  requirements: []
306
324
  rubyforge_project:
307
- rubygems_version: 2.2.2
325
+ rubygems_version: 2.4.5
308
326
  signing_key:
309
327
  specification_version: 4
310
328
  summary: Core Trax Dependencies
@@ -314,9 +332,15 @@ test_files:
314
332
  - spec/support/ecom/widget.rb
315
333
  - spec/support/ecom/widget_category.rb
316
334
  - spec/support/errors.rb
335
+ - spec/support/fake_namespace.rb
336
+ - spec/support/fake_namespace/priceable.rb
337
+ - spec/support/storefront.rb
338
+ - spec/support/storefront/category.rb
339
+ - spec/support/storefront/product.rb
317
340
  - spec/trax/array_spec.rb
318
341
  - spec/trax/core/eager_autoload_namespace_spec.rb
319
342
  - spec/trax/core/errors_spec.rb
320
343
  - spec/trax/core/ext/module_spec.rb
321
344
  - spec/trax/core/ext/object_spec.rb
345
+ - spec/trax/core/has_mixins_spec.rb
322
346
  - spec/trax/core_spec.rb