trax_core 0.0.6 → 0.0.7

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: 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