hash_out 0.1.2 → 0.1.3

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: 09d4acf8885e3018d89507399d889841f5b67e34
4
- data.tar.gz: 180a33b85d8abd7cfc25b333d9649bd1c0465cb3
3
+ metadata.gz: b9a0ed8ed60004a223c24fb5c5d7dc878ce96de7
4
+ data.tar.gz: 49bfa30ee0655b9fbd206dfeef7881a24e9e2a18
5
5
  SHA512:
6
- metadata.gz: 2c7021e5425cefeef649cf02d1e4e291098ecb6636838f55b416a6eb74a1f4fb464108ef9d5b6d410e6b5e6fe37da6ec15159d042f1ff7d219f50383b3b1731c
7
- data.tar.gz: cd0abe87615671b457852adaf3a68b7138f4e9526d8d0d3a85f102a86665c60a2d2e92c9c29d25ad21a515386e58e477dd03c60bfa97d28eb2d0018d5ef3d84a
6
+ metadata.gz: 41a8055dd2e9f5f7ff7928b8760016d711eeeea3fd01b66adc3b2ab5322a3281098b718249fff71f092186bac3560a54aa014d989d7e30a8da9fb524d6e79e48
7
+ data.tar.gz: 7c7aa9a516d33a43ac4edd84de03ba540ca2a990786d8f1b739d254b985c3f94676e79e92116855251ae8817d61eb19cc88bd894a8607be06f7f2a133bd3bba9
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ ### version 0.1.3 - *July 17, 2013*
2
+ * Fixes bug: multiple calls to `#hash_out` that are from an internal method infinitely recurse
3
+ * Fixes bug: method not present in hash when outside caller of `#hash_out` has same name
4
+ * Makes behavior more object-oriented
5
+ * Divides features into separate files
6
+ * Improves README in terms of understanding different features
7
+
8
+ ### version 0.1.2 - *July 15, 2013*
9
+ * Fixes bug: internal calls to `#hash_out` infinitely recurse
10
+
11
+ ### version 0.1.1 - *July 15, 2013*
12
+ * Changes rake to a development dependency from a runtime dependency
13
+
14
+ # version 0.1.0 - *July 15, 2013*
15
+ * Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hash_out (0.1.1)
4
+ hash_out (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -16,15 +16,28 @@ $ gem install hash_out
16
16
  ```
17
17
 
18
18
  ## Usage
19
- 1. `require 'hash_out'`.
20
- 2. Include `HashOut` in your class.
21
- 3. If desired, exclude methods from `#hash_out` by adding `exclude_from_hash_out` to them.
22
- 4. Call `#hash_out` on the instance to return a hash of method names and their values.
19
+ `require 'hash_out'`, `include HashOut`, and call `#hash_out` on the instance.
23
20
 
24
- ##### `#hash_out` automatically excludes the following from the hash it returns:
25
- 1. private methods
26
- 2. methods that require arguments
27
- 3. instance methods in classes that include `HashOut` that wrap or otherwise call `#hash_out`
21
+ ```ruby
22
+ require 'hash_out'
23
+
24
+ class Movie
25
+ include HashOut
26
+
27
+ def title
28
+ 'Fire Walk With Me'
29
+ end
30
+
31
+ def director
32
+ 'David Lynch'
33
+ end
34
+ end
35
+
36
+ Movie.new.hash_out
37
+ # => {:title=>"Fire Walk With Me", :director=>'David Lynch'}
38
+ ```
39
+
40
+ To exclude public methods from `#hash_out`, put `exclude_from_hash_out` at the top of them.
28
41
 
29
42
  ```ruby
30
43
  require 'hash_out'
@@ -40,30 +53,80 @@ class Movie
40
53
  exclude_from_hash_out
41
54
  'David Lynch'
42
55
  end
56
+ end
57
+
58
+ Movie.new.hash_out
59
+ # => {:title=>"Fire Walk With Me"}
60
+ ```
61
+
62
+ Private methods are ignored.
63
+ ```ruby
64
+ require 'hash_out'
65
+
66
+ class Movie
67
+ include HashOut
43
68
 
44
- def available_instantly? catalog=TerribleStreamingService.new
45
- catalog.available_instantly? self
69
+ def title
70
+ 'Fire Walk With Me'
46
71
  end
47
72
 
48
- def has_actor? actor
49
- actors.include? actor
73
+ private
74
+
75
+ def director
76
+ 'David Lynch'
77
+ end
78
+ end
79
+
80
+ Movie.new.hash_out
81
+ # => {:title=>"Fire Walk With Me"}
82
+ ```
83
+
84
+ Public methods that require arguments are also ignored.
85
+ ```ruby
86
+ require 'hash_out'
87
+
88
+ class Movie
89
+ include HashOut
90
+
91
+ def title
92
+ 'Fire Walk With Me'
50
93
  end
51
94
 
52
95
  def chance_of_sequel? existing_sequels, strategy=FutureSequelStrategy
53
96
  strategy.new(self, existing_sequels).chance > 0.5
54
97
  end
98
+ end
55
99
 
56
- private
100
+ Movie.new.hash_out
101
+ # => {:title=>"Fire Walk With Me"}
102
+ ```
103
+
104
+ Public methods that call `#hash_out` are ignored, too.
57
105
 
58
- def actors
59
- ['Sheryl Lee', 'David Bowie', 'Ray Wise']
106
+ ```ruby
107
+ require 'hash_out'
108
+
109
+ class Movie
110
+ include HashOut
111
+
112
+ def title
113
+ 'Fire Walk With Me'
114
+ end
115
+
116
+ def director
117
+ 'David Lynch'
118
+ end
119
+
120
+ def attributes
121
+ hash_out
60
122
  end
61
123
  end
62
124
 
63
125
  movie = Movie.new
126
+ movie.attributes
127
+ # => {:title=>"Fire Walk With Me", :director=>'David Lynch'}
64
128
  movie.hash_out
65
- # => {:title=>"Fire Walk With Me", :available_instantly?=>false}
66
-
129
+ # => {:title=>"Fire Walk With Me", :director=>'David Lynch'}
67
130
  ```
68
131
 
69
132
  ## Contribute
@@ -73,6 +136,12 @@ movie.hash_out
73
136
  4. Ensure the specs are green (`$ rake`)
74
137
  5. Open a pull request.
75
138
 
139
+ ## TODO
140
+ * Bug: make `#hash_out` work with SimpleDelegator
141
+ * Provide class method that offers custom delegator for `#hash_out`
142
+ * Provide class method that offers alternative to `exclude_from_hash_out`
143
+ * Provide class method that allows for inclusion of protected and private methods in resulting hash.
144
+
76
145
  ## License
77
146
  The MIT License (MIT)
78
147
 
@@ -0,0 +1,24 @@
1
+ module HashOut
2
+ class CallRegistry
3
+ attr_reader :hash_out_caller
4
+
5
+ def initialize hash_out_caller
6
+ @times_called = 0
7
+ @hash_out_caller = hash_out_caller
8
+ end
9
+
10
+ def register_call
11
+ @times_called += 1
12
+ end
13
+
14
+ def delete_caller_from hash
15
+ hash.delete hash_out_caller if internal_call?
16
+ end
17
+
18
+ private
19
+
20
+ def internal_call?
21
+ @times_called > 1
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ require 'set'
2
+
3
+ module HashOut
4
+ class Hasher < Struct.new :object, :call_registry
5
+ def object_to_hash
6
+ prepare_hashable_methods
7
+ set_hash
8
+ delete_exclusions
9
+ @hash
10
+ end
11
+
12
+ def exclusions
13
+ @exclusions ||= Set.new
14
+ end
15
+
16
+ def exclude method
17
+ exclusions.add method
18
+ end
19
+
20
+ private
21
+
22
+ def prepare_hashable_methods
23
+ @hashable_methods = object.send :_methods_requiring_no_args
24
+ call_registry.delete_caller_from @hashable_methods
25
+ end
26
+
27
+ def set_hash
28
+ @hash = Hash[hashable_method_value_pairs]
29
+ end
30
+
31
+ def hashable_method_value_pairs
32
+ @hashable_methods.map do |method|
33
+ object.send :_method_value_pair, method
34
+ end
35
+ end
36
+
37
+ def delete_exclusions
38
+ exclusions.each { |exclusion| @hash.delete exclusion }
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module HashOut
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
data/lib/hash_out.rb CHANGED
@@ -1,63 +1,38 @@
1
- module HashOut
2
- require 'set'
1
+ require 'last_call'
2
+ require 'hash_out/call_registry'
3
+ require 'hash_out/hasher'
3
4
 
5
+ module HashOut
4
6
  def hash_out
5
- caller_method = caller_method_sym caller.first
6
-
7
- handle_recursion(caller_method) do
8
- if @called == 1
9
- set_hash_out
10
- delete_exclusions
11
- end
12
- end
13
-
14
- @hash_out
7
+ _register_call last_call
8
+ _hasher.object_to_hash
15
9
  end
16
10
 
17
11
  protected
18
12
 
19
13
  def exclude_from_hash_out
20
- excluded_method = caller_method_sym caller.first
21
- exclusions.add excluded_method
14
+ _hasher.exclude last_call
22
15
  end
23
16
 
24
17
  private
25
18
 
26
- def handle_recursion hash_out_caller
27
- @called ||= 0
28
- @called += 1
29
- exclusions.add hash_out_caller
30
- yield
31
- @called = 0
19
+ def _register_call hash_out_caller
20
+ _call_registry(hash_out_caller).register_call
32
21
  end
33
22
 
34
- def set_hash_out
35
- @hash_out = Hash[interesting_methods_and_values]
23
+ def _call_registry hash_out_caller=nil
24
+ @_call_registry ||= CallRegistry.new hash_out_caller
36
25
  end
37
26
 
38
- def interesting_methods_and_values
39
- methods_requiring_no_arguments.map do |method_name|
40
- name_value_pair method_name
41
- end
27
+ def _hasher
28
+ @_hasher ||= Hasher.new self, _call_registry
42
29
  end
43
30
 
44
- def methods_requiring_no_arguments
31
+ def _methods_requiring_no_args
45
32
  public_methods(false).select { |m| [-1, 0].include? method(m).arity }
46
33
  end
47
34
 
48
- def name_value_pair method_name
49
- [method_name, send(method_name)]
50
- end
51
-
52
- def delete_exclusions
53
- exclusions.each { |exclusion| @hash_out.delete exclusion }
54
- end
55
-
56
- def exclusions
57
- @exclusions ||= Set.new
58
- end
59
-
60
- def caller_method_sym caller_string
61
- caller_string.match(/`(.*)'/)[1].to_sym
35
+ def _method_value_pair method
36
+ [method, send(method)]
62
37
  end
63
38
  end
data/lib/last_call.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def last_call
3
+ caller[1].match(/`(.*)'/)[1].to_sym
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'ambiguous caller' do
4
+ class What
5
+ include HashOut
6
+
7
+ def huh
8
+ :yep
9
+ end
10
+ end
11
+
12
+ class Yep
13
+ def self.huh
14
+ What.new.hash_out
15
+ end
16
+ end
17
+
18
+ it "keeps the key of the name of another object's caller" do
19
+ hash_out = { huh: :yep }
20
+ expect(Yep.huh).to_equal hash_out
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'attribute mutation' do
4
+ class Ooze
5
+ include HashOut
6
+ attr_accessor :color
7
+ end
8
+
9
+ it 'accounts for it between calls to #hash_out' do
10
+ ooze = Ooze.new
11
+ ooze.color = :green
12
+ expect(ooze.hash_out).to_equal({color: :green})
13
+
14
+ ooze.color = :purple
15
+ expect(ooze.hash_out).to_equal({color: :purple})
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe '#exclude_from_hash_out' do
4
+ class Brawler
5
+ include HashOut
6
+
7
+ def fighting?
8
+ true
9
+ end
10
+
11
+ def pancakes
12
+ exclude_from_hash_out
13
+ 'yes please'
14
+ end
15
+ end
16
+
17
+ it 'ignores public methods that declare exclusion from public hash' do
18
+ brawler = Brawler.new
19
+ hash_out = { fighting?: brawler.fighting? }
20
+
21
+ expect(brawler.hash_out).to_equal hash_out
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "object's methods that call #hash_out" do
4
+ class SoMeta
5
+ include HashOut
6
+
7
+ def an_method
8
+ :result
9
+ end
10
+
11
+ def attributes
12
+ hash_out
13
+ hash_out
14
+ hash_out
15
+ end
16
+ end
17
+
18
+ it 'ignores internal public method that calls #hash_out any number of times' do
19
+ so_meta = SoMeta.new
20
+ hash_out = { an_method: :result }
21
+
22
+ expect(so_meta.attributes).to_equal hash_out
23
+ expect(so_meta.hash_out).to_equal hash_out
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "object's methods with arguments" do
4
+ class Beans; end;
5
+ class Grinder
6
+ include HashOut
7
+
8
+ def initialize
9
+ @beans = Beans.new
10
+ end
11
+
12
+ def grind settings, beans=@beans
13
+ with_settings(settings) do |grinder|
14
+ beans.krush_with grinder
15
+ end
16
+ end
17
+
18
+ def clean materials
19
+ clean_with materials
20
+ @cleaned = true
21
+ end
22
+
23
+ def blade edge=:sharp
24
+ edge
25
+ end
26
+
27
+ private
28
+
29
+ def with_settings settings
30
+ @settings = settings
31
+ yield self
32
+ end
33
+
34
+ def clean_with materials
35
+ end
36
+ end
37
+
38
+ it 'ignores public methods that require arguments' do
39
+ grinder = Grinder.new
40
+ hash_out = { blade: grinder.blade }
41
+
42
+ expect(grinder.hash_out).to_equal hash_out
43
+ end
44
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "object's private methods" do
4
+ class ShotCaller
5
+ include HashOut
6
+
7
+ def front
8
+ :chillin
9
+ end
10
+
11
+ private
12
+
13
+ def real_mood
14
+ :nervous
15
+ end
16
+ end
17
+
18
+ it 'ignores them' do
19
+ shot_caller = ShotCaller.new
20
+ hash_out = { front: shot_caller.front }
21
+
22
+ expect(shot_caller.hash_out).to_equal hash_out
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "object's public methods" do
4
+ class Baller
5
+ include HashOut
6
+
7
+ def mood
8
+ :ballin
9
+ end
10
+
11
+ def height
12
+ :tall
13
+ end
14
+ end
15
+
16
+ it 'returns a hash of name-values from them' do
17
+ baller = Baller.new
18
+ hash_out = {
19
+ mood: baller.mood,
20
+ height: baller.height
21
+ }
22
+
23
+ expect(baller.hash_out).to_equal hash_out
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ require_relative '../lib/hash_out'
2
+ require 'minitest/autorun'
3
+ require 'minitest/spec/expect'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_out
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Jachimiak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-15 00:00:00.000000000 Z
11
+ date: 2013-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -46,14 +46,25 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - .gitignore
48
48
  - .travis.yml
49
+ - CHANGELOG.md
49
50
  - Gemfile
50
51
  - Gemfile.lock
51
52
  - README.md
52
53
  - Rakefile
53
54
  - hash_out.gemspec
54
55
  - lib/hash_out.rb
56
+ - lib/hash_out/call_registry.rb
57
+ - lib/hash_out/hasher.rb
55
58
  - lib/hash_out/version.rb
56
- - spec/lib/integration_spec.rb
59
+ - lib/last_call.rb
60
+ - spec/features/ambiguous_caller_spec.rb
61
+ - spec/features/attribute_mutation_spec.rb
62
+ - spec/features/exclude_from_hash_out_spec.rb
63
+ - spec/features/objects_methods_that_call_hash_out_spec.rb
64
+ - spec/features/objects_methods_with_arguments_spec.rb
65
+ - spec/features/objects_private_methods_spec.rb
66
+ - spec/features/objects_public_methods_spec.rb
67
+ - spec/spec_helper.rb
57
68
  homepage: http://github.com/davejachimiak/hash_out
58
69
  licenses:
59
70
  - MIT
@@ -80,4 +91,11 @@ specification_version: 4
80
91
  summary: 'hash_out adds the #hash_out method to your class'' instance. It returns
81
92
  a hash of public method names and values.'
82
93
  test_files:
83
- - spec/lib/integration_spec.rb
94
+ - spec/features/ambiguous_caller_spec.rb
95
+ - spec/features/attribute_mutation_spec.rb
96
+ - spec/features/exclude_from_hash_out_spec.rb
97
+ - spec/features/objects_methods_that_call_hash_out_spec.rb
98
+ - spec/features/objects_methods_with_arguments_spec.rb
99
+ - spec/features/objects_private_methods_spec.rb
100
+ - spec/features/objects_public_methods_spec.rb
101
+ - spec/spec_helper.rb
@@ -1,130 +0,0 @@
1
- require_relative '../../lib/hash_out'
2
- require 'minitest/autorun'
3
- require 'minitest/spec/expect'
4
-
5
- describe 'HashOut#hash_out' do
6
- class Baller
7
- include HashOut
8
-
9
- def mood
10
- :ballin
11
- end
12
-
13
- def height
14
- :tall
15
- end
16
- end
17
-
18
- it 'returns a hash of name-values' do
19
- baller = Baller.new
20
- hash_out = {
21
- mood: baller.mood,
22
- height: baller.height
23
- }
24
-
25
- expect(baller.hash_out).to_equal hash_out
26
- end
27
-
28
- class ShotCaller
29
- include HashOut
30
-
31
- def front
32
- :chillin
33
- end
34
-
35
- private
36
-
37
- def real_mood
38
- :nervous
39
- end
40
- end
41
-
42
- it 'ignores private methods' do
43
- shot_caller = ShotCaller.new
44
- hash_out = { front: shot_caller.front }
45
-
46
- expect(shot_caller.hash_out).to_equal hash_out
47
- end
48
-
49
- class Brawler
50
- include HashOut
51
-
52
- def fighting?
53
- true
54
- end
55
-
56
- def pancakes
57
- exclude_from_hash_out
58
- 'yes please'
59
- end
60
- end
61
-
62
- it 'ignores public methods that declare exclusion from public hash' do
63
- brawler = Brawler.new
64
- hash_out = { fighting?: brawler.fighting? }
65
-
66
- expect(brawler.hash_out).to_equal hash_out
67
- end
68
-
69
- class Beans; end;
70
- class Grinder
71
- require 'ostruct'
72
- include HashOut
73
-
74
- def initialize
75
- @beans = Beans.new
76
- end
77
-
78
- def grind settings, beans=@beans
79
- with_settings(settings) do
80
- beans.krush
81
- end
82
- end
83
-
84
- def clean materials
85
- clean_with materials
86
- @cleaned = true
87
- end
88
-
89
- def blade edge=:sharp
90
- edge
91
- end
92
-
93
- private
94
-
95
- def with_settings settings
96
- @settings = settings
97
- yield self
98
- end
99
-
100
- def clean_with materials
101
- #
102
- end
103
- end
104
-
105
- it 'ignores public methods that require arguments' do
106
- grinder = Grinder.new
107
- hash_out = { blade: grinder.blade }
108
-
109
- expect(grinder.hash_out).to_equal hash_out
110
- end
111
-
112
- class SoMeta
113
- include HashOut
114
-
115
- def an_method
116
- :result
117
- end
118
-
119
- def attributes
120
- hash_out
121
- end
122
- end
123
-
124
- it "ignores internal public method that calls #hash_out" do
125
- so_meta = SoMeta.new
126
- hash_out = { an_method: :result }
127
-
128
- expect(so_meta.attributes).to_equal hash_out
129
- end
130
- end