fun_with_patterns 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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