ishin 0.3.0 → 0.4.0

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: 916893740198856f3e8461ad709f9764bf1d286e
4
- data.tar.gz: 6fdf9f93f7300115d3f6423e5784a48a39e3a366
3
+ metadata.gz: aed7e81440ced692b2e59a4b78c09953ca67c087
4
+ data.tar.gz: 97aa7d2105d7cf9288c655f32ff7595812b60ee5
5
5
  SHA512:
6
- metadata.gz: bad9f801b6189842d1a1bc57627de382d3fe22ed5847230e082d4a12ff40a289b72198ac0f8fdb59b079fbe9caef3cf5aa6b89819b0695149a08adc247d43184
7
- data.tar.gz: a4412fccee7db64485611fca3ef02182985101ca635ec935bab2af393972e78e0ac8624bf0732184d05948280380e3d3b55f96d866dac7c7f510f1de0ede2fcf
6
+ metadata.gz: e2b8de58b950995ca73c59fc4238a017346280f47ae84ee2e8c645b7b6d5ee9c49dd628d70f099bc7a385add3fe2d079bea692ab5c9afa596410bb037883a94f
7
+ data.tar.gz: 125a4421ca4a9c4102f0a50ad2ec00e4c2398534500af87a6a89b3b2ee463e0f459962584db9efd62d1ab6f5a88aacc6d0ff88ebff4167f9b1ee3314a9430424
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'spec/**/*'
4
+ Style/ClassVars:
5
+ Exclude:
6
+ - 'spec/spec_helper.rb'
data/README.md CHANGED
@@ -5,7 +5,9 @@
5
5
 
6
6
  # Ishin
7
7
 
8
- Ishin converts Ruby objects into their Hash representations. It works with plain old classes, extended classes, classes with mixins, and hashes (see Usage for more on that).
8
+ Ishin converts Ruby objects into their Hash representations. It works with plain
9
+ old classes, extended classes, classes with mixins, and hashes (see Usage for
10
+ more information).
9
11
 
10
12
  ## Installation
11
13
 
@@ -23,6 +25,12 @@ Or install it manually by:
23
25
 
24
26
  gem install ishin
25
27
 
28
+ ## Requirements
29
+
30
+ Ishin does not require any other gems to run. There are a few gems used during
31
+ development only, but don't affect runtime performance. For details, see
32
+ `ishin.gemspec` in the root directory of the project.
33
+
26
34
  ## Example
27
35
 
28
36
  As a class method callable on any object:
@@ -66,7 +74,9 @@ dog_hash = Ishin.to_hash(dog)
66
74
 
67
75
  ### Recursion
68
76
 
69
- Ishin also handles object instances nested within other object instances. By default, recursive hash conversion is turned off. To enable recursion, set the `recursive` option to `true`:
77
+ Ishin also handles object instances nested within other object instances. By
78
+ default, recursive hash conversion is turned off. To enable recursion, set the
79
+ `recursive` option to `true`:
70
80
 
71
81
  ```ruby
72
82
  test_struct = Struct.new(:value)
@@ -79,7 +89,9 @@ Ishin.to_hash(nested_structs, recursive: true)
79
89
 
80
90
  ### Recursion Depth
81
91
 
82
- For deeply nested object instances, a maximum recursion depth can be provided in combination with the `recursive` option. The default recursion depth is one (initial call + 1).
92
+ For deeply nested object instances, a maximum recursion depth can be provided in
93
+ combination with the `recursive` option. The default recursion depth is one
94
+ (initial call + 1).
83
95
 
84
96
  ```ruby
85
97
  nest_me = Struct.new(:value)
@@ -89,11 +101,18 @@ Ishin.to_hash(deep_nesting, recursive: true, recursion_depth: 2)
89
101
  # => {:value=>{:value=>{:value=>#<struct value="such depth">}}}
90
102
  ```
91
103
 
92
- Notice in the above example that the recursion stopped after 3 steps (initial call + 2).
104
+ Notice in the above example that the recursion stopped after 3 steps (initial
105
+ call + 2).
106
+
107
+ **Warning:** Increasing the recursion depth will affect the runtime of the
108
+ conversion process significantly. To see how drastic increased recursion levels
109
+ affect performance, run `ruby benchmarks/recursive_bench.rb`
93
110
 
94
111
  ### Expanding Hashes using Recursion
95
112
 
96
- Using recursion, it is also possible to convert hashes containing object instances to a hash-only representation as well. Notice that this only works if the `recursive` option is provided.
113
+ Using recursion, it is also possible to convert hashes containing object
114
+ instances to a hash-only representation as well. Notice that this only works if
115
+ the `recursive` option is provided.
97
116
 
98
117
  ```ruby
99
118
  another_struct = Struct.new(:value)
@@ -105,11 +124,13 @@ Ishin.to_hash(my_hash, recursive: true)
105
124
  # => {:my_struct=>{:value=>"yup, it's a struct"}}
106
125
  ```
107
126
 
108
- Keep in mind that the `recursive` option works in conjunction with the `recursion_depth` option.
127
+ Keep in mind that the `recursive` option works in conjunction with the
128
+ `recursion_depth` option.
109
129
 
110
130
  ### Symbolizing Keys
111
131
 
112
- By default, Ishin stores key names as symbols. This behavior can be disabled by setting the `symbolize` option to `false`.
132
+ By default, Ishin stores key names as symbols. This behavior can be disabled by
133
+ setting the `symbolize` option to `false`.
113
134
 
114
135
  ```ruby
115
136
  class Dog
@@ -127,11 +148,14 @@ Ishin.to_hash(lassie)
127
148
  Ishin.to_hash(lassie, symbolize: false)
128
149
  # => {"says"=>"Timmy is stuck in a well!"}
129
150
  ```
130
- When setting the `symbolize` option to `false`, the explicit conversion of strings to symbols is prevented. This, however, does *not* mean that hashes whose keys are already symbols are converted into string-based keys.
151
+ When setting the `symbolize` option to `false`, the explicit conversion of
152
+ strings to symbols is prevented. This, however, does *not* mean that hashes
153
+ whose keys are already symbols are converted into string-based keys.
131
154
 
132
155
  ### Evaluating Methods
133
156
 
134
- Normally, Ishin does not evaluate methods, but is possible to do so through the optional `evaluate` option by passing it an array of method names to evaluate.
157
+ Normally, Ishin does not evaluate methods, but is possible to do so through the
158
+ optional `evaluate` option by passing it an array of method names to evaluate.
135
159
 
136
160
  ```ruby
137
161
  class Speaker
@@ -159,7 +183,15 @@ class MyObject
159
183
  end
160
184
  ```
161
185
 
162
- Your object now exposes a method named `to_hash` taking the same options at the `Ishin::to_hash` class method documented above.
186
+ Your object now exposes a method named `to_hash` taking the same options at the
187
+ `Ishin::to_hash` class method documented above.
188
+
189
+ ## Running Code Quality Tools
190
+
191
+ To run the code quality tools Rubocop, Reek, and RSpec, run the following
192
+ command:
193
+
194
+ rake
163
195
 
164
196
  ## Running the Specs
165
197
 
@@ -167,6 +199,14 @@ Once `bundle` is executed, simply run:
167
199
 
168
200
  rake spec
169
201
 
202
+ ## Running the Benchmarks
203
+
204
+ To give an idea on what kind of performance can be expected from Ishin, there
205
+ are a few IPS (iterations per second) benchmarks located in the `benchmarks`
206
+ directory. These can all be executed in series by running:
207
+
208
+ rake bench
209
+
170
210
  ## Changelog
171
211
 
172
212
  * 0.1.0
@@ -175,3 +215,7 @@ Once `bundle` is executed, simply run:
175
215
  * Added `Ishin::Mixin`.
176
216
  * 0.2.1
177
217
  * Now using `Struct.to_h` when converting a `Struct` instance.
218
+ * 0.3.0
219
+ * Added support for evaluating object methods.
220
+ * 0.4.0
221
+ * Cleanup: preparing an overhaul
data/Rakefile CHANGED
@@ -1,6 +1,20 @@
1
1
  require 'rspec/core/rake_task'
2
2
  require 'bundler/gem_tasks'
3
+ require 'rubocop/rake_task'
4
+ require 'reek/rake/task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new
8
+ Reek::Rake::Task.new
5
9
 
6
- task :default => :spec
10
+ task :bench do
11
+ sh 'ruby ./benchmarks/simple_bench.rb'
12
+ sh 'ruby ./benchmarks/recursive_bench.rb'
13
+ sh 'ruby ./benchmarks/symbolize_bench.rb'
14
+ end
15
+
16
+ task :default do
17
+ Rake::Task[:rubocop].invoke
18
+ Rake::Task[:spec].invoke
19
+ Rake::Task[:reek].invoke
20
+ end
@@ -0,0 +1,39 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'benchmark/ips'
3
+ require 'ishin'
4
+
5
+ # A dummy class used for simply holding some data
6
+ class Test
7
+ attr_reader :value
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+ end
12
+
13
+ Benchmark.ips do |x|
14
+ x.config(time: 5, warmup: 2)
15
+
16
+ test_object = Test.new(Test.new(Test.new(Test.new('value'))))
17
+
18
+ one_level_options = { recursive: true, recursion_depth: 2 }
19
+ two_level_options = { recursive: true, recursion_depth: 3 }
20
+ three_level_options = { recursive: true, recursion_depth: 4 }
21
+
22
+ x.report('no recursion') do
23
+ Ishin.to_hash(test_object)
24
+ end
25
+
26
+ x.report('one level of recursion') do
27
+ Ishin.to_hash(test_object, one_level_options)
28
+ end
29
+
30
+ x.report('two levels of recursion') do
31
+ Ishin.to_hash(test_object, two_level_options)
32
+ end
33
+
34
+ x.report('three levels of recursion') do
35
+ Ishin.to_hash(test_object, three_level_options)
36
+ end
37
+
38
+ x.compare!
39
+ end
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'benchmark/ips'
3
+ require 'ishin'
4
+
5
+ # Non-mixin version to be used with .to_hash
6
+ class Simple
7
+ attr_reader :test
8
+
9
+ def initialize
10
+ @test = rand
11
+ end
12
+ end
13
+
14
+ # Mixed-in version
15
+ class MixedIn
16
+ include Ishin::Mixin
17
+
18
+ attr_reader :test
19
+
20
+ def initialize
21
+ @test = rand
22
+ end
23
+ end
24
+
25
+ Benchmark.ips do |x|
26
+ x.config(time: 5, warmup: 2)
27
+
28
+ x.report('.to_hash class method') do
29
+ Ishin.to_hash(Simple.new)
30
+ end
31
+
32
+ x.report('.to_hash mixin method') do
33
+ MixedIn.new.to_hash
34
+ end
35
+
36
+ x.compare!
37
+ end
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'benchmark/ips'
3
+ require 'ishin'
4
+
5
+ # Non-mixin version to be used with .to_hash
6
+ class Simple
7
+ attr_reader :test
8
+
9
+ def initialize
10
+ @test = rand
11
+ end
12
+ end
13
+
14
+ Benchmark.ips do |x|
15
+ x.config(time: 5, warmup: 2)
16
+
17
+ x.report('symbolize: true') do
18
+ Ishin.to_hash(Simple.new, symbolize: true)
19
+ end
20
+
21
+ x.report('symbolize: false') do
22
+ Ishin.to_hash(Simple.new, symbolize: false)
23
+ end
24
+
25
+ x.compare!
26
+ end
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "ishin"
3
+ require 'bundler/setup'
4
+ require 'ishin'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
10
+ # require 'pry'
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start
@@ -5,22 +5,27 @@ require 'ishin/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'ishin'
8
- spec.version = Ishin::VERSION
8
+ spec.version = Ishin::Version::STRING
9
9
  spec.authors = ['Eddy Luten']
10
10
  spec.email = ['eddyluten@gmail.com']
11
11
 
12
- spec.summary = %q{Ishin is an object to hash converter.}
13
- spec.description = %q{Ishin converts objects into their Hash representations.}
12
+ spec.summary = 'Ishin is an object to hash converter.'
13
+ spec.description = 'Ishin converts objects into their Hash representations.'
14
14
  spec.homepage = 'https://github.com/EddyLuten/ishin'
15
15
  spec.license = 'MIT'
16
16
  spec.platform = Gem::Platform::RUBY
17
17
 
18
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |file|
19
+ file.match(%r{^(test|spec|features)/})
20
+ end
19
21
  spec.bindir = 'exe'
20
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
23
  spec.require_paths = ['lib']
22
24
 
23
- spec.add_development_dependency 'rake', '~> 10.0'
24
- spec.add_development_dependency 'rspec'
25
- spec.add_development_dependency 'codeclimate-test-reporter'
25
+ spec.add_development_dependency 'benchmark-ips', '~> 2.3'
26
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.8'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'reek', '~> 3.7'
29
+ spec.add_development_dependency 'rspec', '~> 3.4'
30
+ spec.add_development_dependency 'rubocop', '~> 0.35.1'
26
31
  end
@@ -1,28 +1,29 @@
1
1
  require 'ishin/version'
2
+ require 'ishin/mixin'
2
3
 
4
+ # Ishin is an object to hash converter Ruby Gem
3
5
  module Ishin
4
- module Mixin
5
- def to_hash(options = {})
6
- Ishin.to_hash(self, options)
7
- end
8
- end
9
-
6
+ # Converts objects into their hash representations.
7
+ # @param object [Object] an object to convert
8
+ # @param options [Hash] a hash containing conversion options
10
9
  def self.to_hash(object, options = {})
11
10
  options = defaults.merge(options)
12
11
  result = {}
12
+ type_to_hash(result, object, options)
13
+ evaluate_methods(result, object, options)
14
+ result
15
+ end
13
16
 
17
+ private
18
+
19
+ def self.type_to_hash(result, object, options)
14
20
  case object
15
21
  when Struct then struct_to_hash(result, object, options)
16
22
  when Hash then hash_to_hash(result, object, options)
17
23
  else object_to_hash(result, object, options)
18
24
  end
19
-
20
- evaluate_methods(result, object, options)
21
- result
22
25
  end
23
26
 
24
- private
25
-
26
27
  def self.decrement_recursion_depth(options)
27
28
  options[:recursion_depth] = [0, options[:recursion_depth] - 1].max
28
29
  options
@@ -36,12 +37,18 @@ module Ishin
36
37
  new_options = decrement_recursion_depth(options.clone)
37
38
 
38
39
  object.each do |key, value|
39
- key = key.to_sym if options[:symbolize] && key.is_a?(String)
40
-
41
- result[key] = native_type?(value) ? value : to_hash(value, new_options)
40
+ result[hash_key(key, options)] = hash_value(value, new_options)
42
41
  end
43
42
  end
44
43
 
44
+ def self.hash_key(key, options)
45
+ options[:symbolize] && key.is_a?(String) ? key.to_sym : key
46
+ end
47
+
48
+ def self.hash_value(value, new_options)
49
+ native_type?(value) ? value : to_hash(value, new_options)
50
+ end
51
+
45
52
  def self.struct_to_hash(result, object, options)
46
53
  result.replace(object.to_h)
47
54
  return unless should_recurse?(options)
@@ -58,33 +65,45 @@ module Ishin
58
65
 
59
66
  object.instance_variables.each do |var|
60
67
  value = object.instance_variable_get(var)
61
- key = var.to_s.delete('@')
62
- key = key.to_sym if options[:symbolize]
68
+ key = instance_variable_to_key(var, options)
69
+ result[key] = object_value(value, options, new_options)
70
+ end
71
+ end
63
72
 
64
- if should_recurse?(options) && !native_type?(value)
65
- result[key] = to_hash(value, new_options)
66
- else
67
- result[key] = value
68
- end
73
+ def self.instance_variable_to_key(instance_variable, options)
74
+ key = instance_variable.to_s.delete('@')
75
+ options[:symbolize] ? key.to_sym : key
76
+ end
77
+
78
+ def self.object_value(value, options, new_options)
79
+ if should_recurse?(options) && !native_type?(value)
80
+ to_hash(value, new_options)
81
+ else
82
+ value
69
83
  end
70
84
  end
71
85
 
72
86
  def self.evaluate_methods(result, object, options)
73
- return if options[:evaluate].nil? || options[:evaluate].empty?
87
+ evaluate = options[:evaluate]
88
+ return if !evaluate || evaluate.empty?
74
89
 
75
- options[:evaluate].each do |method|
76
- next unless object.methods.include?(method)
77
- key_name = options[:symbolize] ? method : method.to_s
78
- result[key_name] = object.send(method)
90
+ evaluate.each do |method|
91
+ if object.methods.include?(method)
92
+ result[method_name_to_key(method, options)] = object.send(method)
93
+ end
79
94
  end
80
95
  end
81
96
 
97
+ def self.method_name_to_key(method, options)
98
+ options[:symbolize] ? method : method.to_s
99
+ end
100
+
82
101
  def self.should_recurse?(options)
83
102
  options[:recursive] && options[:recursion_depth] > 0
84
103
  end
85
104
 
86
105
  def self.native_type?(value)
87
- [String, Numeric, TrueClass, FalseClass].any? { |i| value.is_a?(i) }
106
+ [String, Numeric, TrueClass, FalseClass].any? { |type| value.is_a?(type) }
88
107
  end
89
108
 
90
109
  def self.defaults
@@ -0,0 +1,12 @@
1
+ module Ishin
2
+ # Can be used to include the Ishin functionality into your class and provides
3
+ # a `.to_hash` method.
4
+ module Mixin
5
+ # Calls `Ishin.to_hash` and passes the parameters on.
6
+ # @param options [Hash]
7
+ # @see Ishin.to_hash
8
+ def to_hash(options = {})
9
+ Ishin.to_hash(self, options)
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,10 @@
1
1
  module Ishin
2
- VERSION = '0.3.0'
2
+ # Contains the version number for the gem.
3
+ module Version
4
+ MAJOR = '0'.freeze
5
+ MINOR = '4'.freeze
6
+ PATCH = '0'.freeze
7
+
8
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
+ end
3
10
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ishin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eddy Luten
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-14 00:00:00.000000000 Z
11
+ date: 2015-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: benchmark-ips
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: codeclimate-test-reporter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.8
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.4.8
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rake
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -24,34 +52,48 @@ dependencies:
24
52
  - - "~>"
25
53
  - !ruby/object:Gem::Version
26
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: reek
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.7'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: rspec
29
71
  requirement: !ruby/object:Gem::Requirement
30
72
  requirements:
31
- - - ">="
73
+ - - "~>"
32
74
  - !ruby/object:Gem::Version
33
- version: '0'
75
+ version: '3.4'
34
76
  type: :development
35
77
  prerelease: false
36
78
  version_requirements: !ruby/object:Gem::Requirement
37
79
  requirements:
38
- - - ">="
80
+ - - "~>"
39
81
  - !ruby/object:Gem::Version
40
- version: '0'
82
+ version: '3.4'
41
83
  - !ruby/object:Gem::Dependency
42
- name: codeclimate-test-reporter
84
+ name: rubocop
43
85
  requirement: !ruby/object:Gem::Requirement
44
86
  requirements:
45
- - - ">="
87
+ - - "~>"
46
88
  - !ruby/object:Gem::Version
47
- version: '0'
89
+ version: 0.35.1
48
90
  type: :development
49
91
  prerelease: false
50
92
  version_requirements: !ruby/object:Gem::Requirement
51
93
  requirements:
52
- - - ">="
94
+ - - "~>"
53
95
  - !ruby/object:Gem::Version
54
- version: '0'
96
+ version: 0.35.1
55
97
  description: Ishin converts objects into their Hash representations.
56
98
  email:
57
99
  - eddyluten@gmail.com
@@ -61,14 +103,19 @@ extra_rdoc_files: []
61
103
  files:
62
104
  - ".gitignore"
63
105
  - ".rspec"
106
+ - ".rubocop.yml"
64
107
  - ".travis.yml"
65
108
  - Gemfile
66
109
  - LICENSE.txt
67
110
  - README.md
68
111
  - Rakefile
112
+ - benchmarks/recursive_bench.rb
113
+ - benchmarks/simple_bench.rb
114
+ - benchmarks/symbolize_bench.rb
69
115
  - bin/console
70
116
  - ishin.gemspec
71
117
  - lib/ishin.rb
118
+ - lib/ishin/mixin.rb
72
119
  - lib/ishin/version.rb
73
120
  homepage: https://github.com/EddyLuten/ishin
74
121
  licenses:
@@ -90,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
137
  version: '0'
91
138
  requirements: []
92
139
  rubyforge_project:
93
- rubygems_version: 2.4.5
140
+ rubygems_version: 2.4.5.1
94
141
  signing_key:
95
142
  specification_version: 4
96
143
  summary: Ishin is an object to hash converter.