hash_out 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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