fun_with_patterns 0.0.4 → 0.0.5

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.
Files changed (37) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.markdown +7 -0
  3. data/Gemfile +1 -1
  4. data/README.rdoc +54 -0
  5. data/VERSION +1 -1
  6. data/lib/fun_with/patterns/get_and_set.rb +16 -2
  7. data/lib/fun_with/patterns/get_and_set_api.rb +13 -4
  8. data/lib/fun_with/patterns/loader/class_methods.rb +182 -0
  9. data/lib/fun_with/patterns/loader/features/bracketwise_lookup.rb +17 -0
  10. data/lib/fun_with/patterns/loader/loading_styles/eval.rb +23 -0
  11. data/lib/fun_with/patterns/loader/loading_styles/instance_exec.rb +24 -0
  12. data/lib/fun_with/patterns/loader/loading_styles/yaml.rb +27 -0
  13. data/lib/fun_with/patterns/loader.rb +2 -155
  14. data/lib/fun_with_patterns.rb +2 -4
  15. data/test/helper.rb +2 -1
  16. data/test/test_get_and_set.rb +31 -2
  17. data/test/test_loader_pattern.rb +14 -6
  18. data/test/user.rb +25 -1
  19. data/test/users/{mary.rb → eval/mary.rb} +0 -0
  20. data/test/users/{more → eval/more}/gary.rb +0 -0
  21. data/test/users/{steve.rb → eval/steve.rb} +0 -0
  22. data/test/users/{wanda.rb → eval/wanda.rb} +0 -0
  23. data/test/users/instance_exec/mary.rb +2 -0
  24. data/test/users/instance_exec/more/gary.rb +2 -0
  25. data/test/users/instance_exec/steve.rb +2 -0
  26. data/test/users/instance_exec/wanda.rb +2 -0
  27. data/test/users/yaml/mary.yaml +3 -0
  28. data/test/users/yaml/more/gary.yml +3 -0
  29. data/test/users/yaml/steve.yaml +3 -0
  30. data/test/users/yaml/wanda.yml +3 -0
  31. data/test/yaml_obj.rb +2 -1
  32. metadata +25 -11
  33. data/lib/fun_with/patterns/hooks.rb +0 -47
  34. data/lib/fun_with/patterns/reloadable.rb +0 -33
  35. data/test/reloadable/my_reloadable.rb +0 -7
  36. data/test/test_hooks.rb +0 -25
  37. data/test/test_reloadable_pattern.rb +0 -33
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWZlYzlkNjQ2MzBkZjY3ZGUxOTUwZTI2MmY0MzYzNDE4MjI1MGJjNA==
4
+ MTQwYjliNzVlNWFkNmYxMjkxZTU4NTY1NmZjZDEwMmNmMTE5NDU0MQ==
5
5
  data.tar.gz: !binary |-
6
- ZDM0ZDUzMmY2ZTM2YmJmNTNhNDRhZjg1ODZlMDc3ZjBkOTc0NWRkOA==
6
+ NDAyMWQ1ZTU4M2JiYjdjODkwMGIwM2IwMjM0YjZlMDYxZGY2M2M5Ng==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YzRlM2IwOGMwNWNjN2RhOWJkYjNmYjgyMGU0YjgwMjE3NTU4NWViNDI2MDU2
10
- NjY3Yzg3OTRiMzNhZTA3ZGJiY2UwNzg1YzNmMDcwMTk5NDQ1NmFmZTEwMDAx
11
- NjU5Nzk5MDc0NDk0YTY1YTk2MzJmNDI1Y2MxMjA1YjE4M2EyMWE=
9
+ YmFkOTUzMWQ2MTViZDEzZjZjYTY2NzBmZDU5OTE2NjQ0NzgxODQ1ZGRjYjYx
10
+ MWFhMTgxOGMyMWE0MjVkYWRiNDcxOGYxODg4Y2VmMDQ2Y2JiYWY4MGQ1Mjc2
11
+ MDQxMzBiMTg4OGQ4YzM1YmJjZDcxM2MxYWY5OTZlNTdkYjg1ZWI=
12
12
  data.tar.gz: !binary |-
13
- NDZiNWMyOWQxMjUyZDk5ZWUwMWZlNjJjNDVhNmQ0OTk5NjdhY2FjMGIwMzBl
14
- ZGEyNDg2MzBlOGZkYTkxNjM1MjBiNjk5Y2M0MDBkNDVmZDA3YzQyM2Q0NTk1
15
- NjFlOThjNTNkNGM2YjgzOTE3MjQ1NjhjM2RjMzQzM2QxYzFjNTY=
13
+ N2EzZjE5OTNlN2YzZmNjMTAwNDE2YTU5NGYxMjFlN2JkMDE1OTJkMjVjNjBl
14
+ ODQ4YjY0MzI5YWFjYjgxYzg4ZDQ4ZTQ1YWM3OTljY2FlMzllYWZjZTk3ZTZi
15
+ N2RiNDBlN2EyMjY4ODM0YjU0ZDgxZThjMzM3MTk4MzdhM2VjMmY=
data/CHANGELOG.markdown CHANGED
@@ -1,6 +1,13 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.0.5
5
+ -----
6
+
7
+ Removed Reloadable and Hooks patterns.
8
+ Added `get_and_set_block()` to GetAndSet (declares or runs a block)
9
+ `get_and_set*()` methods can now be called in `Class` and `Module` themselves.
10
+
4
11
  0.0.4
5
12
  -----
6
13
 
data/Gemfile CHANGED
@@ -14,4 +14,4 @@ group :development do
14
14
  gem 'fun_with_testing', '~> 0.0'
15
15
  end
16
16
 
17
- gem "fun_with_gems", "~> 0.0"
17
+ gem "fun_with_gems", "~> 0.0", ">= 0.0.2"
data/README.rdoc CHANGED
@@ -63,9 +63,63 @@ For each directory you give it, it will:
63
63
 
64
64
  You can get some interesting behavior by overwriting individual methods. For example, loading individual configurations from YAML or JSON or XML. There's an example in the test/ folder.
65
65
 
66
+ The default "style" of loading a file is "eval the contents and return the result." This may not always be the desired behavior. Other built in loading styles:
67
+
68
+
69
+
70
+
71
+
66
72
  Note: If you want to manage your own registry by redefining loader_pattern_load_from_dir( dir ), loader_pattern_register_item( item ), etc., make sure you handle and report exceptions.
67
73
 
68
74
 
75
+ More example code!
76
+
77
+ class Klass
78
+
79
+ include FunWith::Patterns::Loader
80
+ loader_pattern_configure( :bracketwise_lookup,
81
+ :warn_on_key_change,
82
+ { :verbose => true, :load } )
83
+ end
84
+
85
+ loader_pattern_configure is a quickie method for setting up a variety of behaviors. Options so far:
86
+
87
+ :bracketwise_lookup : instead of calling Klass.loader_pattern_registry_lookup( "string" )
88
+ you can just call Klass["string"]
89
+
90
+ {:key => :<sym>} : loader determines registry key by calling this method
91
+
92
+ :warn_on_key_changes : If a newly loaded item has an existing registry key, it prints a warning as it overwrites
93
+
94
+ :dont_warn_on_key_changes : (default)
95
+ :style => :(eval|instance_exec|yaml) : Use one of the built-in loading styles. Otherwise, set custom loading
96
+ behavior by defining your own Klass.loader_pattern_register_item
97
+
98
+
99
+ The styles need some explanation:
100
+
101
+ :eval (default) : evals the contents of the file and returns the result
102
+
103
+ :instance_exec : The file contents will run as though inside the object
104
+
105
+ Klass.new do
106
+ # ----- file contents for boris.rb starts here
107
+ self.name "Boris"
108
+ self.age 23
109
+ self.kill_count 9
110
+ # ----- file contents for boris.rb end here
111
+ end
112
+
113
+ :yaml The file contents describe a YAML hash, with the topmost keys describing
114
+ the setter to call in order to set the attribute to that value. For example,
115
+
116
+ ---
117
+ - name: Boris
118
+
119
+ would end up calling klass_object.name=( "Boris" )
120
+
121
+
122
+ TODO: I feel like a default label should maybe come out of the filename (zero-config and all that), but haven't built it.
69
123
 
70
124
  == Reloadable ==
71
125
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.5
@@ -17,8 +17,7 @@ module FunWith
17
17
  end
18
18
 
19
19
  # Would also like to do a boolean version which creates
20
- # .bool? .bool! and .not_bool!
21
-
20
+ # .bool? .bool! and .not_bool!
22
21
  def get_and_set_boolean( *method_names )
23
22
  for name in method_names
24
23
  if self.is_a?(Class) || self.is_a?(Module)
@@ -45,6 +44,21 @@ module FunWith
45
44
  end
46
45
  end
47
46
  end
47
+
48
+ # the name() method can be called with a block (to change the block that is to be executed)
49
+ # or called with args to get the results of the block. Uses the internal object variable @name
50
+ def get_and_set_block( name, *args, &block )
51
+ eval "define_method( :#{name} ) do |*args, &block|
52
+ if block.is_a?( Proc ) # oddly, block_given? always returns false when defined this way
53
+ raise ArgumentError.new( 'Call #{name}() with either a block or args' ) unless args.length == 0
54
+ self.instance_variable_set( :@#{name}, block )
55
+ block
56
+ else
57
+ block = self.instance_variable_get( :@#{name} )
58
+ ( block || Proc.new{} ).call( *args )
59
+ end
60
+ end "
61
+ end
48
62
  end
49
63
  end
50
64
  end
@@ -1,11 +1,20 @@
1
1
  module FunWith
2
2
  module Patterns
3
3
  module GetAndSetAPI
4
- def activate( classes_to_activate = [Class, Module] )
5
- classes_to_activate = [classes_to_activate] unless classes_to_activate.is_a?(Array)
6
-
4
+ # Can pass in an array listing the classes to activate, or just pass in arguments
5
+ def activate( *classes_to_activate )
6
+ if classes_to_activate.length == 1 && classes_to_activate.first.is_a?(Array)
7
+ classes_to_activate = classes_to_activate.first
8
+ elsif classes_to_activate.length == 0
9
+ classes_to_activate = [Class, Module] # no arguments given
10
+ end
11
+
7
12
  for klass in classes_to_activate
8
- klass.send( :include, FunWith::Patterns::GetAndSet )
13
+ if klass == Class || klass == Module
14
+ klass.send( :include, GetAndSet ) # Because individual classes or modules are objects of class Class/Module
15
+ end
16
+
17
+ klass.send( :extend, GetAndSet )
9
18
  end
10
19
  end
11
20
  end
@@ -0,0 +1,182 @@
1
+ module FunWith
2
+ module Patterns
3
+ module Loader
4
+ module ClassMethods
5
+ # By default, looks for .rb files to evaluate
6
+ # ext => :all (or "*") to load every file from directory.
7
+ # ext => :rb (or "rb") to load all .rb files (this is default)
8
+ # call without arguments to inquire about current extension.
9
+ def loader_pattern_extension( ext = nil )
10
+ case ext
11
+ when nil
12
+ # do nothing
13
+ when "*", :all
14
+ @loader_pattern_extension = "*"
15
+ else
16
+ @loader_pattern_extension = ext
17
+ end
18
+
19
+ @loader_pattern_extension
20
+ end
21
+
22
+ def loader_pattern_verbose( verbosity = nil )
23
+ @loader_pattern_verbose = verbosity unless verbosity.nil?
24
+ @loader_pattern_verbose
25
+ end
26
+
27
+ def loader_pattern_rescue_failing_item_load( file, &block )
28
+ file = file.fwf_filepath.expand
29
+ if file.file?
30
+ obj = yield
31
+ STDOUT.puts( "Loaded file #{file}" ) if self.loader_pattern_verbose
32
+
33
+ obj
34
+ else
35
+ STDERR.puts( "(#{self.class}) Load failed, no such file: #{file}" )
36
+ end
37
+ rescue Exception => e
38
+ STDERR.puts( "Could not load file #{file}. Reason: #{e.class.name} #{e.message}" )
39
+
40
+ if self.loader_pattern_verbose
41
+ STDERR.puts( puts e.backtrace.map{|line| "\t\t#{line}"}.join("\n") )
42
+ STDERR.puts( "\n" )
43
+ end
44
+
45
+ nil
46
+ end
47
+
48
+ # Default, may want to override how the registry behaves.
49
+ # If you don't provide a key argument, then the object needs to
50
+ # respond to .loader_pattern_registry_key()
51
+ def loader_pattern_register_item( obj, key = nil )
52
+ return nil if obj.nil?
53
+ @loader_pattern_registry ||= {}
54
+
55
+ if key.nil?
56
+ if obj.respond_to?( :loader_pattern_registry_key )
57
+ key = obj.loader_pattern_registry_key
58
+ else
59
+ raise "#{self.class} not registered. No registry key given, and object does not respond to .loader_pattern_registry_key()."
60
+ end
61
+ end
62
+
63
+ if loader_pattern_is_item_registerable?( obj )
64
+ if @loader_pattern_warn_on_key_changes && loader_pattern_registry_lookup( key )
65
+ warn( "class #{self} is replacing lookup key #{key.inspect}" )
66
+ end
67
+
68
+ return @loader_pattern_registry[ key ] = obj
69
+ else
70
+ warn( "#{obj} is not an instance of a registerable class. Registerable classes: #{self.loader_pattern_only_register_classes.inspect}" )
71
+ return nil
72
+ end
73
+ end
74
+
75
+ def loader_pattern_registry_lookup( key )
76
+ @loader_pattern_registry ||= {}
77
+ @loader_pattern_registry[key]
78
+ end
79
+
80
+ def loader_pattern_registry
81
+ @loader_pattern_registry
82
+ end
83
+
84
+ def loader_pattern_only_register_classes( *args )
85
+ if args.length > 0
86
+ @loader_pattern_only_register_classes = args
87
+ end
88
+
89
+ @loader_pattern_only_register_classes || []
90
+ end
91
+
92
+ def loader_pattern_is_item_registerable?( item )
93
+ return true if loader_pattern_only_register_classes.fwf_blank?
94
+
95
+ for klass in @loader_pattern_only_register_classes
96
+ return true if item.is_a?( klass )
97
+ end
98
+
99
+ return false
100
+ end
101
+
102
+
103
+ # Assumes that every file in the directory and subdirectories contain ruby code that
104
+ # will yield an object that the loader is looking for. It also automatically
105
+ # adds the resulting object to a registry.
106
+ # You may want to override this if you're looking for different behavior.
107
+ def loader_pattern_load_from_dir( *dirs )
108
+ for dir in dirs
109
+ dir = dir.fwf_filepath
110
+ @loader_pattern_directories ||= []
111
+ @loader_pattern_directories << dir
112
+
113
+ for file in dir.glob( :ext => self.loader_pattern_extension, :recurse => true )
114
+ obj = self.loader_pattern_load_item( file )
115
+ self.loader_pattern_register_item( obj ) if self.loader_pattern_is_item_registerable?( obj )
116
+ end
117
+ end
118
+ end
119
+
120
+ def loader_pattern_loaded_directories
121
+ @loader_pattern_directories ||= []
122
+ end
123
+
124
+ # Handle the initial configuration of the class.
125
+ #
126
+ # :bracketwise_lookup : Instead of looking up an object by LoaderBearingClass.loader_pattern_registry_lookup(:keyword)
127
+ # you can simply use LoaderBearingClass[:keyword]
128
+ #
129
+ # :warn_on_key_changes : Warns whenever the registry overwrites an existing key. Useful for debugging, sometimes.
130
+ #
131
+ # Some configuration directives are given as hashes. Multiple directives may be combined into
132
+ # a single hash.
133
+ #
134
+ # {:key => <METHOD_SYM>} : The method for asking the object what name it should be lookupable under.
135
+ #
136
+ # {:verbose => (true|false)} : How noisy do you want the loading to be?
137
+ #
138
+ # {:style => :eval}
139
+ #
140
+ # {:style => :instance_exec}
141
+ #
142
+ # {:style => <PROC>}
143
+
144
+ def loader_pattern_configure( *args )
145
+ for arg in args
146
+ case arg
147
+ when :bracketwise_lookup
148
+ self.extend( Features::BracketwiseLookup )
149
+ when :warn_on_key_changes
150
+ @loader_pattern_warn_on_key_changes = true
151
+ when :dont_warn_on_key_changes
152
+ @loader_pattern_warn_on_key_changes = false
153
+ when Hash
154
+ for key, val in arg
155
+ case key
156
+ when :key
157
+ self.class_eval do
158
+ eval( "alias :loader_pattern_registry_key #{val.to_sym.inspect}" )
159
+ end
160
+ when :verbose
161
+ self.loader_pattern_verbose( val )
162
+ when :style
163
+ case val # styles allowed: :eval, :instance_exec
164
+ when :eval
165
+ self.extend( LoadingStyles::Eval )
166
+ when :instance_exec
167
+ self.extend( LoadingStyles::InstanceExec )
168
+ when :yaml
169
+ self.extend( LoadingStyles::YAML )
170
+ self.loader_pattern_extension( [:yml, :yaml] )
171
+ else
172
+ raise "Unknown Loader loading style: #{val.inspect}"
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,17 @@
1
+ module FunWith
2
+ module Patterns
3
+ module Loader
4
+ module Features
5
+ module BracketwiseLookup
6
+ def []( key )
7
+ loader_pattern_registry_lookup( key )
8
+ end
9
+
10
+ def []=( key, val )
11
+ loader_pattern_register_item( val, key )
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module FunWith
2
+ module Patterns
3
+ module Loader
4
+ module LoadingStyles
5
+ module Eval
6
+ # Default behavior: read the file, evaluate it, expect a ruby object
7
+ # of the class that the loader pattern is installed on. If anything goes
8
+ # wrong (file no exist, syntax error), returns a nil.
9
+ #
10
+ # Override in your class if you need your files translated
11
+ # into objects differently.
12
+ def loader_pattern_load_item( file )
13
+ self.loader_pattern_rescue_failing_item_load( file ) do
14
+ obj = eval( file.read )
15
+
16
+ return obj
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module FunWith
2
+ module Patterns
3
+ module Loader
4
+ module LoadingStyles
5
+ # Assumes the class does not take arguments in its initialize() method.
6
+ # The contents of the file are run via instance_exec to configure the object.
7
+ module InstanceExec
8
+ def loader_pattern_load_item( file )
9
+ self.loader_pattern_rescue_failing_item_load( file ) do
10
+ obj = self.new
11
+
12
+ # obj.instance_eval( file.read )
13
+ obj.instance_exec do
14
+ eval( file.read )
15
+ end
16
+
17
+ return obj
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ module FunWith
2
+ module Patterns
3
+ module Loader
4
+ module LoadingStyles
5
+ module YAML
6
+ def loader_pattern_load_item( file )
7
+ self.loader_pattern_rescue_failing_item_load( file ) do
8
+ obj = self.new
9
+
10
+ hash = Psych.load( file.read )
11
+
12
+ for method, val in hash
13
+ eq_method = :"#{method}="
14
+
15
+ if obj.respond_to?( eq_method )
16
+ obj.send( eq_method, val )
17
+ end
18
+ end
19
+
20
+ return obj
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,161 +3,8 @@ module FunWith
3
3
  module Loader
4
4
  def self.included( base )
5
5
  base.extend( ClassMethods )
6
- base.loader_pattern_extension("rb") if base.loader_pattern_extension.nil?
7
- end
8
-
9
- module ClassMethods
10
- # By default, looks for .rb files to evaluate
11
- # ext => :all (or "*") to load every file from directory.
12
- # ext => :rb (or "rb") to load all .rb files (this is default)
13
- # call without arguments to inquire about current extension.
14
- def loader_pattern_extension( ext = nil )
15
- case ext
16
- when nil
17
- # do nothing
18
- when "*", :all
19
- @loader_pattern_extension = "*"
20
- else
21
- @loader_pattern_extension = "*.#{ext}"
22
- end
23
-
24
- @loader_pattern_extension
25
- end
26
-
27
- def loader_pattern_verbose( verbosity = nil )
28
- @loader_pattern_verbose = verbosity unless verbosity.nil?
29
- @loader_pattern_verbose
30
- end
31
-
32
- # Default behavior: read the file, evaluate it, expect a ruby object
33
- # of the class that the loader pattern is installed on. If anything goes
34
- # wrong (file no exist, syntax error), returns a nil.
35
- #
36
- # Override in your class if you need your files translated
37
- # into objects differently.
38
- def loader_pattern_load_item( file )
39
- file = file.fwf_filepath
40
- if file.file?
41
- obj = eval( file.read )
42
-
43
- STDOUT.puts( "Loaded file #{file}" ) if self.loader_pattern_verbose
44
- return obj
45
- else
46
- STDERR.puts( "(#{self.class}) Load failed, no such file: #{file}" )
47
- return nil
48
- end
49
- rescue Exception => e
50
- STDERR.puts( "Could not load file #{file}. Reason: #{e.class.name} #{e.message}" )
51
-
52
- if self.loader_pattern_verbose
53
- STDERR.puts( puts e.backtrace.map{|line| "\t\t#{line}"}.join("\n") )
54
- STDERR.puts( "\n" )
55
- end
56
-
57
- nil
58
- end
59
-
60
- # Default, may want to override how the registry behaves.
61
- # If you don't provide a key argument, then the object needs to
62
- # respond to .loader_pattern_registry_key()
63
- def loader_pattern_register_item( obj, key = nil )
64
- return nil if obj.nil?
65
- @loader_pattern_registry ||= {}
66
-
67
- key = obj.loader_pattern_registry_key if key.nil?
68
-
69
- if loader_pattern_is_item_registerable?( obj )
70
- if @loader_pattern_warn_on_key_changes && loader_pattern_registry_lookup( key )
71
- warn( "class #{self} is replacing lookup key #{key.inspect}" )
72
- end
73
-
74
- return @loader_pattern_registry[ key ] = obj
75
- else
76
- warn( "#{obj} is not an instance of a registerable class. Registerable classes: #{self.loader_pattern_only_register_classes.inspect}" )
77
- return nil
78
- end
79
- end
80
-
81
- def loader_pattern_registry_lookup( key )
82
- @loader_pattern_registry ||= {}
83
- @loader_pattern_registry[key]
84
- end
85
-
86
- def loader_pattern_registry
87
- @loader_pattern_registry
88
- end
89
-
90
- def loader_pattern_only_register_classes( *args )
91
- if args.length > 0
92
- @loader_pattern_only_register_classes = args
93
- end
94
-
95
- @loader_pattern_only_register_classes || []
96
- end
97
-
98
- def loader_pattern_is_item_registerable?( item )
99
- return true if loader_pattern_only_register_classes.fwf_blank?
100
-
101
- for klass in @loader_pattern_only_register_classes
102
- return true if item.is_a?( klass )
103
- end
104
-
105
- return false
106
- end
107
-
108
-
109
- # Assumes that every file in the directory and subdirectories contain ruby code that
110
- # will yield an object that the loader is looking for. It also automatically
111
- # adds the resulting object to a registry.
112
- # You may want to override this if you're looking for different behavior.
113
- def loader_pattern_load_from_dir( *dirs )
114
- for dir in dirs
115
- dir = dir.fwf_filepath
116
- @loader_pattern_directories ||= []
117
- @loader_pattern_directories << dir
118
-
119
- for file in dir.glob( "**", self.loader_pattern_extension )
120
- obj = self.loader_pattern_load_item( file )
121
- self.loader_pattern_register_item( obj ) if self.loader_pattern_is_item_registerable?( obj )
122
- end
123
- end
124
- end
125
-
126
- def loader_pattern_loaded_directories
127
- @loader_pattern_directories ||= []
128
- end
129
-
130
- def loader_pattern_configure( *args )
131
- for arg in args
132
- case arg
133
- when :bracketwise_lookup
134
- self.class_eval do
135
- def self.[]( key )
136
- loader_pattern_registry_lookup( key )
137
- end
138
-
139
- def self.[]=( key, val )
140
- loader_pattern_register_item( val, key )
141
- end
142
- end
143
- when :warn_on_key_changes
144
- @loader_pattern_warn_on_key_changes = true
145
- when :dont_warn_on_key_changes
146
- @loader_pattern_warn_on_key_changes = false
147
- when Hash
148
- for key, val in arg
149
- case key
150
- when :key
151
- self.class_eval do
152
- eval( "alias :loader_pattern_registry_key #{val.inspect}" )
153
- end
154
- when :verbose
155
- self.loader_pattern_verbose( val )
156
- end
157
- end
158
- end
159
- end
160
- end
6
+ base.extend( LoadingStyles::Eval ) # provides a default load_item method
7
+ base.loader_pattern_extension( :rb ) if base.loader_pattern_extension.nil?
161
8
  end
162
9
  end
163
10
  end
@@ -2,9 +2,7 @@ require 'fun_with_gems'
2
2
 
3
3
  FunWith::Gems.make_gem_fun( "FunWith::Patterns" )
4
4
 
5
- Class.send( :include, FunWith::Patterns::MakeInstancesReloadable )
6
- Module.send( :include, FunWith::Patterns::MakeInstancesReloadable )
7
- FunWith::Patterns::Reloadable.extend( FunWith::Patterns::ClassReloaderMethod )
8
5
 
9
6
  # Activate Object#get_and_set / Module#get_and_set by calling GetAndSet.activate
10
- FunWith::Patterns::GetAndSet.extend( FunWith::Patterns::GetAndSetAPI )
7
+ FunWith::Patterns::GetAndSet.extend( FunWith::Patterns::GetAndSetAPI )
8
+
data/test/helper.rb CHANGED
@@ -15,8 +15,9 @@
15
15
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
16
  $LOAD_PATH.unshift(File.dirname(__FILE__))
17
17
 
18
- require 'fun_with_testing'
19
18
  require 'fun_with_patterns'
19
+ require 'fun_with_testing'
20
+
20
21
 
21
22
  require_relative 'user'
22
23
  require_relative 'yaml_obj'
@@ -1,7 +1,5 @@
1
1
  require 'helper'
2
2
 
3
- FunWith::Patterns::GetAndSet.activate
4
-
5
3
  class TestGetAndSet < FunWith::Patterns::TestCase
6
4
  context "basics" do
7
5
  should "be plumbed correctly" do
@@ -12,6 +10,8 @@ class TestGetAndSet < FunWith::Patterns::TestCase
12
10
  context "trial run" do
13
11
  should "get and set" do
14
12
  c = Class.new
13
+ FunWith::Patterns::GetAndSet.activate( c )
14
+
15
15
  c.get_and_set( :radio, :radius, :radium )
16
16
  c.get_and_set( :radiate )
17
17
  c.get_and_set_boolean( :stringy, :flurmish )
@@ -46,6 +46,8 @@ class TestGetAndSet < FunWith::Patterns::TestCase
46
46
  m = Module.new
47
47
  c = Class.new
48
48
 
49
+ FunWith::Patterns::GetAndSet.activate( m )
50
+
49
51
  c.send( :include, m )
50
52
 
51
53
  m.get_and_set( :radio, :radius, :radium )
@@ -73,5 +75,32 @@ class TestGetAndSet < FunWith::Patterns::TestCase
73
75
  assert_equal v2, o.radium( v2 ) # ==> "Madame Curie"
74
76
  assert_equal v2, o.radium() # ==> "Madame Curie"
75
77
  end
78
+
79
+ should "get and set blocks" do
80
+ c = Class.new
81
+ FunWith::Patterns::GetAndSet.activate( c )
82
+ c.get_and_set_block( :string_transformation )
83
+
84
+ doubler = c.new
85
+ assert_respond_to( doubler, :string_transformation )
86
+
87
+ assert_nil doubler.string_transformation( "hello" )
88
+
89
+ doubler.string_transformation do |input|
90
+ "#{input}#{input}"
91
+ end
92
+
93
+ assert_equal "hellohello", doubler.string_transformation( "hello" )
94
+ assert_equal "55", doubler.string_transformation( "5" )
95
+
96
+ stripper = c.new
97
+ stripper.string_transformation do |input|
98
+ input.strip
99
+ end
100
+
101
+ assert_equal "stripped", stripper.string_transformation( " stripped ")
102
+
103
+
104
+ end
76
105
  end
77
106
  end
@@ -11,8 +11,12 @@ class TestLoaderPattern < FunWith::Patterns::TestCase
11
11
 
12
12
  context "testing User" do
13
13
  setup do
14
- User.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users" ) )
15
- User2.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users" ) )
14
+ User.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users", "eval" ) )
15
+ User2.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users", "eval" ) )
16
+ User3.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users", "instance_exec" ) )
17
+ User4.loader_pattern_load_from_dir( FunWith::Patterns.root( "test", "users", "yaml" ) )
18
+
19
+ @user_classes = [User, User2, User3, User4]
16
20
  end
17
21
 
18
22
  should "have all the right methods" do
@@ -22,13 +26,17 @@ class TestLoaderPattern < FunWith::Patterns::TestCase
22
26
  :loader_pattern_register_item,
23
27
  :loader_pattern_load_from_dir,
24
28
  :loader_pattern_configure ]
25
- assert_respond_to( User, method )
29
+ for klass in @user_classes
30
+ assert_respond_to( klass, method, "#{klass} should respond to ##{method}" )
31
+ end
26
32
  end
27
33
  end
28
34
 
29
- should "load users from test/users and test/users/more" do
30
- assert User.loader_pattern_registry_lookup("Gary Milhouse")
31
- assert_equal 54, User.loader_pattern_registry_lookup("Gary Milhouse").age
35
+ should "load users from test/users into various classes" do
36
+ for klass in @user_classes
37
+ assert klass.loader_pattern_registry_lookup("Gary Milhouse"), "#{klass} did not load Gary. Poor Gary."
38
+ assert_equal 54, klass.loader_pattern_registry_lookup("Gary Milhouse").age, "#{klass} did not load Gary with proper age data."
39
+ end
32
40
  end
33
41
 
34
42
  should "lookup via brackets" do
data/test/user.rb CHANGED
@@ -22,4 +22,28 @@ class User2
22
22
  @name = name
23
23
  @age = age
24
24
  end
25
- end
25
+ end
26
+
27
+ class User3
28
+ FunWith::Patterns::GetAndSet.activate( self )
29
+
30
+ get_and_set :name, :age
31
+
32
+ include FunWith::Patterns::Loader
33
+ loader_pattern_configure( :bracketwise_lookup,
34
+ { :key => :name },
35
+ { :style => :instance_exec } # Create object, run code in configuration file inside the object's context.
36
+ )
37
+
38
+ end
39
+
40
+ class User4
41
+ attr_accessor :name, :age
42
+
43
+ include FunWith::Patterns::Loader
44
+ loader_pattern_configure( :bracketwise_lookup,
45
+ { :key => :name },
46
+ { :style => :yaml }
47
+ )
48
+ end
49
+
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ name "Mary Masterson"
2
+ age 27
@@ -0,0 +1,2 @@
1
+ name "Gary Milhouse"
2
+ age 54
@@ -0,0 +1,2 @@
1
+ name "Steve Sturmond"
2
+ age 72
@@ -0,0 +1,2 @@
1
+ name "Wanda Wimbledon"
2
+ age 53
@@ -0,0 +1,3 @@
1
+ ---
2
+ :name: Mary Masterson
3
+ :age: 27
@@ -0,0 +1,3 @@
1
+ ---
2
+ :name: Gary Milhouse
3
+ :age: 54
@@ -0,0 +1,3 @@
1
+ ---
2
+ :name: Steve Sturmond
3
+ :age: 72
@@ -0,0 +1,3 @@
1
+ ---
2
+ :name: Wanda Wimbledon
3
+ :age: 53
data/test/yaml_obj.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  require 'yaml'
2
2
 
3
3
 
4
- # Change the behavior by overriding
4
+ # Change the behavior by overriding loader_pattern_load_item( file )
5
+ # Uses custom method, not LoadingStyle::YAML
5
6
  class YamlObj
6
7
  include FunWith::Patterns::Loader
7
8
 
metadata CHANGED
@@ -1,19 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fun_with_patterns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryce Anderson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-31 00:00:00.000000000 Z
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fun_with_gems
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.2
17
20
  - - ~>
18
21
  - !ruby/object:Gem::Version
19
22
  version: '0.0'
@@ -21,6 +24,9 @@ dependencies:
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.0.2
24
30
  - - ~>
25
31
  - !ruby/object:Gem::Version
26
32
  version: '0.0'
@@ -48,21 +54,29 @@ extra_rdoc_files:
48
54
  files:
49
55
  - ./lib/fun_with/patterns/get_and_set.rb
50
56
  - ./lib/fun_with/patterns/get_and_set_api.rb
51
- - ./lib/fun_with/patterns/hooks.rb
52
57
  - ./lib/fun_with/patterns/loader.rb
53
- - ./lib/fun_with/patterns/reloadable.rb
58
+ - ./lib/fun_with/patterns/loader/class_methods.rb
59
+ - ./lib/fun_with/patterns/loader/features/bracketwise_lookup.rb
60
+ - ./lib/fun_with/patterns/loader/loading_styles/eval.rb
61
+ - ./lib/fun_with/patterns/loader/loading_styles/instance_exec.rb
62
+ - ./lib/fun_with/patterns/loader/loading_styles/yaml.rb
54
63
  - ./lib/fun_with_patterns.rb
55
64
  - ./test/helper.rb
56
- - ./test/reloadable/my_reloadable.rb
57
65
  - ./test/test_get_and_set.rb
58
- - ./test/test_hooks.rb
59
66
  - ./test/test_loader_pattern.rb
60
- - ./test/test_reloadable_pattern.rb
61
67
  - ./test/user.rb
62
- - ./test/users/mary.rb
63
- - ./test/users/more/gary.rb
64
- - ./test/users/steve.rb
65
- - ./test/users/wanda.rb
68
+ - ./test/users/eval/mary.rb
69
+ - ./test/users/eval/more/gary.rb
70
+ - ./test/users/eval/steve.rb
71
+ - ./test/users/eval/wanda.rb
72
+ - ./test/users/instance_exec/mary.rb
73
+ - ./test/users/instance_exec/more/gary.rb
74
+ - ./test/users/instance_exec/steve.rb
75
+ - ./test/users/instance_exec/wanda.rb
76
+ - ./test/users/yaml/mary.yaml
77
+ - ./test/users/yaml/more/gary.yml
78
+ - ./test/users/yaml/steve.yaml
79
+ - ./test/users/yaml/wanda.yml
66
80
  - ./test/yaml_obj.rb
67
81
  - ./test/yamls/mike/mike_amazon.yaml
68
82
  - ./test/yamls/mike/mike_gmail.yaml
@@ -1,47 +0,0 @@
1
- module FunWith
2
- module Patterns
3
- module Hooks
4
- def add_hook_before( method, &block )
5
- hook_pattern_install_hooks_for_method( method )
6
- end
7
-
8
- def add_hook_after( method, &block )
9
- hook_pattern_install_hooks_for_method( method )
10
-
11
- end
12
-
13
- def hook_pattern_hooks_installed_for_method?( method )
14
- self.respond_to?( :"#{method}_method_without_hooks" )
15
- end
16
-
17
- def hook_pattern_install_hooks_for_method( method )
18
- return false if hook_pattern_hooks_installed_for_method?( method )
19
-
20
- alias :"#{method}_method_without_hooks" :"#{method}"
21
-
22
- @hook_pattern_hooks ||= {}
23
- @hook_pattern_hooks[method] ||= {}
24
- @hook_pattern_hooks[method][:before] ||= []
25
- @hook_pattern_hooks[method][:after] ||= []
26
-
27
-
28
- # http://stackoverflow.com/questions/4470108/when-monkey-patching-a-method-can-you-call-the-overridden-method-from-the-new-i
29
- old_method = instance_method(method)
30
-
31
- # define_method(:bar) do
32
- # old_bar.bind(self).() + ' World'
33
- # end
34
-
35
- define_method( method ) do |*args, &block|
36
- self.hook_pattern_run( @hook_pattern_hooks[method][:before], *args, &block )
37
- old_method.bind( self ).call( *args, &block )
38
- self.hook_pattern_run( @hook_pattern_hooks[method][:after], *args, &block )
39
- end
40
- end
41
-
42
- def hook_pattern_run( hookset, *args, &block )
43
- puts "running hookset"
44
- end
45
- end
46
- end
47
- end
@@ -1,33 +0,0 @@
1
- warn( "Something wrong with the Reloadable class. Flaky. Not recommended for use." )
2
- module FunWith
3
- module Patterns
4
- # A bare-bones reloading system. Useful when the entire file defines exactly one
5
- # class or module, with no dependencies or side-effects.
6
- module Reloadable
7
- def reload!
8
- FunWith::Patterns::Reloadable.reload_class( self )
9
- end
10
-
11
- def reloader_filepath
12
- @reloader_filepath
13
- end
14
- end
15
-
16
- module MakeInstancesReloadable
17
- def reloadable!
18
- self.extend( FunWith::Patterns::Reloadable )
19
- kaller = caller.first.gsub(/:\d+:in.*/, '')
20
- @reloader_filepath = kaller.fwf_filepath.expand
21
- end
22
- end
23
-
24
- module ClassReloaderMethod
25
- def reload_class( klass )
26
- if file = klass.reloader_filepath
27
- Object.send( :remove_const, klass.name.to_sym )
28
- file.load
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,7 +0,0 @@
1
- class MyReloadable
2
- reloadable!
3
-
4
- def square( x )
5
- x * x
6
- end
7
- end
data/test/test_hooks.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'helper'
2
-
3
- class TestHooksPattern < FunWith::Patterns::TestCase
4
- _context "first try" do
5
- should "set up a class with hooks" do
6
- class A
7
- include FunWith::Patterns::Hooks
8
-
9
- def called_x_times()
10
- @called_x_times ||= 0
11
- @called_x_times
12
- end
13
-
14
- add_hook_before( :called_x_times ) do
15
- @called_x_times ||= 0
16
- @called_x_times += 1
17
- end
18
- end
19
-
20
- a = A.new
21
-
22
- assert_one( a.called_x_times() )
23
- end
24
- end
25
- end
@@ -1,33 +0,0 @@
1
- require 'helper'
2
-
3
- class TestReloadablePattern < FunWith::Patterns::TestCase
4
- context "testing basics" do
5
- setup do
6
- Class.send( :include, FunWith::Patterns::Reloadable )
7
- assert_has_instance_method( Class, :reload! )
8
- assert_has_instance_method( Class, :reloadable! )
9
-
10
- assert_respond_to( Object, :reload!)
11
- assert_respond_to( Object, :reloadable!)
12
- end
13
-
14
- should "reload MyReloadable" do
15
- refute defined?(MyReloadable)
16
- FunWith::Patterns.root( "test", "reloadable", "my_reloadable.rb" ).requir
17
- assert defined?(MyReloadable)
18
- assert_respond_to( MyReloadable.new, :square )
19
-
20
- MyReloadable.class_eval do
21
- remove_method :square
22
- end
23
-
24
- refute_respond_to( MyReloadable.new, :square )
25
-
26
- MyReloadable.reload!
27
-
28
- assert defined?(MyReloadable)
29
-
30
- assert_respond_to( MyReloadable.new, :square )
31
- end
32
- end
33
- end