kamerling 0.0.2 → 0.0.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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -13
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +64 -64
  5. data/README.md +18 -1
  6. data/Rakefile +5 -3
  7. data/bin/kamerling +1 -1
  8. data/config/reek.yml +20 -3
  9. data/kamerling.gemspec +16 -13
  10. data/lib/kamerling.rb +2 -28
  11. data/lib/kamerling/addr.rb +17 -3
  12. data/lib/kamerling/client.rb +10 -11
  13. data/lib/kamerling/core_extensions/main.rb +14 -14
  14. data/lib/kamerling/dispatch.rb +13 -0
  15. data/lib/kamerling/handler.rb +16 -25
  16. data/lib/kamerling/http_api.rb +50 -34
  17. data/lib/kamerling/logging.rb +36 -16
  18. data/lib/kamerling/mapper.rb +33 -0
  19. data/lib/kamerling/message.rb +50 -37
  20. data/lib/kamerling/migrations/2_results_received_at.rb +7 -0
  21. data/lib/kamerling/migrations/3_dispatches.rb +17 -0
  22. data/lib/kamerling/migrations/4_registrations_registered_at.rb +7 -0
  23. data/lib/kamerling/migrations/5_clients_type.rb +7 -0
  24. data/lib/kamerling/net_dispatcher.rb +12 -7
  25. data/lib/kamerling/project.rb +7 -3
  26. data/lib/kamerling/receiver.rb +38 -10
  27. data/lib/kamerling/registrar.rb +45 -8
  28. data/lib/kamerling/registration.rb +9 -10
  29. data/lib/kamerling/repo.rb +33 -26
  30. data/lib/kamerling/repos.rb +52 -45
  31. data/lib/kamerling/result.rb +10 -11
  32. data/lib/kamerling/server/http.rb +28 -21
  33. data/lib/kamerling/server/sock.rb +32 -24
  34. data/lib/kamerling/server/tcp.rb +23 -15
  35. data/lib/kamerling/server/udp.rb +24 -16
  36. data/lib/kamerling/server_runner.rb +30 -41
  37. data/lib/kamerling/settings.rb +28 -0
  38. data/lib/kamerling/task.rb +7 -7
  39. data/lib/kamerling/task_dispatcher.rb +31 -22
  40. data/lib/kamerling/uuid.rb +13 -11
  41. data/lib/kamerling/uuid_entity.rb +23 -9
  42. data/lib/kamerling/value.rb +13 -0
  43. data/lib/kamerling/views/clients.slim +3 -1
  44. data/lib/kamerling/views/project.slim +8 -4
  45. data/lib/kamerling/views/projects.slim +7 -1
  46. data/spec/kamerling/addr_spec.rb +32 -22
  47. data/spec/kamerling/client_spec.rb +9 -5
  48. data/spec/kamerling/core_extensions/main_spec.rb +18 -13
  49. data/spec/kamerling/dispatch_spec.rb +16 -0
  50. data/spec/kamerling/handler_spec.rb +24 -34
  51. data/spec/kamerling/http_api_spec.rb +94 -73
  52. data/spec/kamerling/logging_spec.rb +93 -62
  53. data/spec/kamerling/mapper_spec.rb +151 -0
  54. data/spec/kamerling/message_spec.rb +73 -49
  55. data/spec/kamerling/net_dispatcher_spec.rb +22 -16
  56. data/spec/kamerling/receiver_spec.rb +29 -19
  57. data/spec/kamerling/registrar_spec.rb +43 -15
  58. data/spec/kamerling/registration_spec.rb +17 -0
  59. data/spec/kamerling/repo_spec.rb +63 -47
  60. data/spec/kamerling/repos_spec.rb +121 -109
  61. data/spec/kamerling/result_spec.rb +16 -0
  62. data/spec/kamerling/server/http_spec.rb +19 -14
  63. data/spec/kamerling/server/tcp_spec.rb +41 -35
  64. data/spec/kamerling/server/udp_spec.rb +40 -34
  65. data/spec/kamerling/server_runner_spec.rb +62 -53
  66. data/spec/kamerling/settings_spec.rb +36 -0
  67. data/spec/kamerling/task_dispatcher_spec.rb +38 -15
  68. data/spec/kamerling/task_spec.rb +9 -5
  69. data/spec/kamerling/uuid_entity_spec.rb +53 -25
  70. data/spec/kamerling/uuid_spec.rb +19 -16
  71. data/spec/kamerling/value_spec.rb +21 -0
  72. data/spec/spec_helper.rb +3 -6
  73. metadata +54 -8
  74. data/lib/kamerling/core_extensions.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9be4e3ac2863218c3d390f4afb2e80f8da0c93be
4
- data.tar.gz: 98c18518041d91d383daa9c79c5bd46999de4b75
3
+ metadata.gz: 7e6dbf946f5fa033f8c544564030c65e230ac10c
4
+ data.tar.gz: 8dd41ffe1684f4ec003a63fed7e8058bfdc8dc88
5
5
  SHA512:
6
- metadata.gz: e1b0aeb3ea6a079fd8999f326e6800edcc9f6b56ad1ab0ed997fbf71223e571ae44a7e8c02dc0f5d7d11c65e4dc98b0eae55be57e532bfd90a8d9e61030a56b6
7
- data.tar.gz: ffe10141b36930b5bf9b4b904312ca96e62e652b51b35f1fceab122fabd7a77258cd9a137936ce6af9c48fefc5968784f189c619cb3685c53091fea66fabcde0
6
+ metadata.gz: 2c6994c506f7bc2af1b96ac2e3f74cb2fdafe08b7efb1a46c10340c6bdc1829bcb1151b4898be5094ad9d00cf07955b0fc1fa3136b0acdea727c10871e3a3377
7
+ data.tar.gz: 30e1fd388e616fab264f7d4d56652f093638cf88601b68cedf65158a888cafcb81e45da173c13775e33770959cde970c0b5e249b1a5551278e5e3291efd7b0b0
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
- AccessModifierIndentation:
2
- Enabled: false
1
+ AllCops:
2
+ Exclude:
3
+ - tmp/**/*
3
4
 
4
5
  AndOr:
5
6
  Enabled: false
@@ -7,18 +8,8 @@ AndOr:
7
8
  Documentation:
8
9
  Enabled: false
9
10
 
10
- EndAlignment:
11
+ SingleSpaceBeforeFirstArg:
11
12
  Enabled: false
12
13
 
13
- HandleExceptions:
14
- Exclude:
15
- - lib/kamerling/server/sock.rb
16
-
17
- IndentationWidth:
18
- Enabled: false
19
-
20
- MethodDefParentheses:
21
- EnforcedStyle: require_no_parentheses
22
-
23
14
  TrailingComma:
24
15
  EnforcedStyleForMultiline: comma
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
- gem 'virtus', github: 'solnic/virtus'
data/Gemfile.lock CHANGED
@@ -1,18 +1,9 @@
1
- GIT
2
- remote: git://github.com/solnic/virtus.git
3
- revision: c31940a63d1a4a2ac30032a0c01a9a217b5f5f82
4
- specs:
5
- virtus (1.0.2)
6
- axiom-types (~> 0.1)
7
- coercible (~> 1.0)
8
- descendants_tracker (~> 0.0.3)
9
- equalizer (~> 0.0.9)
10
-
11
1
  PATH
12
2
  remote: .
13
3
  specs:
14
- kamerling (0.0.2)
4
+ kamerling (0.0.3)
15
5
  after_do (~> 0.3.0)
6
+ equalizer (~> 0.0.9)
16
7
  sequel (~> 4.4)
17
8
  sinatra (~> 1.4)
18
9
  slim (~> 2.0)
@@ -22,88 +13,97 @@ PATH
22
13
  GEM
23
14
  remote: https://rubygems.org/
24
15
  specs:
25
- after_do (0.3.0)
26
- ast (1.1.0)
27
- atomic (1.1.16)
28
- axiom-types (0.1.0)
29
- descendants_tracker (~> 0.0.3)
16
+ after_do (0.3.1)
17
+ ast (2.0.0)
18
+ astrolabe (1.3.0)
19
+ parser (>= 2.2.0.pre.3, < 3.0)
20
+ axiom-types (0.1.1)
21
+ descendants_tracker (~> 0.0.4)
30
22
  ice_nine (~> 0.11.0)
31
- thread_safe (~> 0.1.3)
32
- bogus (0.1.4)
23
+ thread_safe (~> 0.3, >= 0.3.1)
24
+ bogus (0.1.5)
33
25
  dependor (>= 0.0.4)
34
- celluloid (0.15.2)
35
- timers (~> 1.1.0)
36
- celluloid-io (0.15.0)
37
- celluloid (>= 0.15.0)
38
- nio4r (>= 0.5.0)
26
+ celluloid (0.16.0)
27
+ timers (~> 4.0.0)
28
+ coderay (1.1.0)
39
29
  coercible (1.0.0)
40
30
  descendants_tracker (~> 0.0.1)
41
31
  dependor (1.0.1)
42
- descendants_tracker (0.0.3)
32
+ descendants_tracker (0.0.4)
33
+ thread_safe (~> 0.3, >= 0.3.1)
43
34
  equalizer (0.0.9)
44
- ffi (1.9.3)
35
+ ffi (1.9.6)
36
+ hitimes (1.2.2)
45
37
  ice_nine (0.11.0)
46
- json (1.8.1)
47
- listen (2.7.1)
38
+ listen (2.7.11)
48
39
  celluloid (>= 0.15.2)
49
- celluloid-io (>= 0.15.0)
50
40
  rb-fsevent (>= 0.9.3)
51
41
  rb-inotify (>= 0.9)
52
- mini_portile (0.5.2)
53
- minitest (5.3.1)
42
+ method_source (0.8.2)
43
+ mini_portile (0.6.1)
44
+ minitest (5.4.2)
54
45
  minitest-focus (1.1.0)
55
46
  minitest (>= 4, < 6)
56
- nio4r (1.0.0)
57
- nokogiri (1.6.1)
58
- mini_portile (~> 0.5.0)
59
- parser (2.1.7)
60
- ast (~> 1.1)
47
+ nokogiri (1.6.4.1)
48
+ mini_portile (~> 0.6.0)
49
+ parser (2.2.0.pre.7)
50
+ ast (>= 1.1, < 3.0)
61
51
  slop (~> 3.4, >= 3.4.5)
62
52
  powerpack (0.0.9)
53
+ pry (0.10.1)
54
+ coderay (~> 1.1.0)
55
+ method_source (~> 0.8.1)
56
+ slop (~> 3.4)
63
57
  rack (1.5.2)
64
- rack-protection (1.5.2)
58
+ rack-protection (1.5.3)
65
59
  rack
66
60
  rack-test (0.6.2)
67
61
  rack (>= 1.0)
68
62
  rainbow (2.0.0)
69
- rake (10.1.1)
63
+ rake (10.3.2)
70
64
  rb-fsevent (0.9.4)
71
- rb-inotify (0.9.3)
65
+ rb-inotify (0.9.5)
72
66
  ffi (>= 0.5.0)
73
- reek (1.3.6)
74
- ruby2ruby (~> 2.0.7)
75
- ruby_parser (~> 3.2)
76
- sexp_processor
77
- rerun (0.9.0)
78
- listen (~> 2.7)
79
- rubocop (0.19.1)
80
- json (>= 1.7.7, < 2)
81
- parser (~> 2.1.7)
67
+ reek (1.4.0)
68
+ rainbow (>= 1.99, < 3.0)
69
+ ruby2ruby (>= 2.0.8, < 3.0)
70
+ ruby_parser (>= 3.5.0, < 4.0)
71
+ sexp_processor (~> 4.4)
72
+ rerun (0.10.0)
73
+ listen (~> 2.7, >= 2.7.3)
74
+ rubocop (0.27.1)
75
+ astrolabe (~> 1.3)
76
+ parser (>= 2.2.0.pre.7, < 3.0)
82
77
  powerpack (~> 0.0.6)
83
78
  rainbow (>= 1.99.1, < 3.0)
84
79
  ruby-progressbar (~> 1.4)
85
- ruby-progressbar (1.4.2)
86
- ruby2ruby (2.0.7)
80
+ ruby-progressbar (1.7.0)
81
+ ruby2ruby (2.1.3)
87
82
  ruby_parser (~> 3.1)
88
83
  sexp_processor (~> 4.0)
89
- ruby_parser (3.4.1)
84
+ ruby_parser (3.6.3)
90
85
  sexp_processor (~> 4.1)
91
- sequel (4.8.0)
92
- sexp_processor (4.4.2)
93
- sinatra (1.4.4)
86
+ sequel (4.16.0)
87
+ sexp_processor (4.4.4)
88
+ sinatra (1.4.5)
94
89
  rack (~> 1.4)
95
90
  rack-protection (~> 1.4)
96
91
  tilt (~> 1.3, >= 1.3.4)
97
- slim (2.0.2)
98
- temple (~> 0.6.6)
92
+ slim (2.1.0)
93
+ temple (~> 0.6.9)
99
94
  tilt (>= 1.3.3, < 2.1)
100
- slop (3.5.0)
101
- sqlite3 (1.3.9)
102
- temple (0.6.7)
103
- thread_safe (0.1.3)
104
- atomic
95
+ slop (3.6.0)
96
+ sqlite3 (1.3.10)
97
+ temple (0.6.10)
98
+ thread_safe (0.3.4)
105
99
  tilt (1.4.1)
106
- timers (1.1.0)
100
+ timers (4.0.1)
101
+ hitimes
102
+ virtus (1.0.3)
103
+ axiom-types (~> 0.1)
104
+ coercible (~> 1.0)
105
+ descendants_tracker (~> 0.0, >= 0.0.3)
106
+ equalizer (~> 0.0, >= 0.0.9)
107
107
 
108
108
  PLATFORMS
109
109
  ruby
@@ -114,9 +114,9 @@ DEPENDENCIES
114
114
  minitest (~> 5.0)
115
115
  minitest-focus (~> 1.1)
116
116
  nokogiri (~> 1.6)
117
+ pry (~> 0.10.0)
117
118
  rack-test (~> 0.6.2)
118
119
  rake (~> 10.1)
119
120
  reek (~> 1.3)
120
- rerun (~> 0.9.0)
121
- rubocop (~> 0.19.0)
122
- virtus!
121
+ rerun (~> 0.10.0)
122
+ rubocop (~> 0.27.0)
data/README.md CHANGED
@@ -3,4 +3,21 @@ Kamerling
3
3
 
4
4
  Kamerling is a lightweight server for managing a network of computation clients.
5
5
 
6
- © MMXIII Piotr Szotkowski <p.szotkowski@tele.pw.edu.pl>, licensed under AGPL 3 (see LICENCE)
6
+ HTTP API
7
+ --------
8
+
9
+ Minimal docs on the HTTP API (which happens to use XHTML and so should be mostly usable through a browser):
10
+
11
+ `GET /` returns links to clients (at `#clients [href]`) and project (at `#projects [href]`).
12
+
13
+ `GET /clients` contains information on and links to clients (at `#clients [data-class=client]`).
14
+
15
+ `GET /projects` contains links to projects (at `#projects [data-class=project]`).
16
+
17
+ `GET /projects/{uuid}` contains client (at `#clients [data-class=client]` and task (at `#tasks [data-class=task]`) information on a given project.
18
+
19
+ `POST /projects` creates a new project (given a `name` and an `uuid`).
20
+
21
+ `POST /projects/dispatch` dispatches tasks to all free clients.
22
+
23
+ © MMXIII-MMXIV Piotr Szotkowski <p.szotkowski@tele.pw.edu.pl>, licensed under AGPL 3 (see LICENCE)
data/Rakefile CHANGED
@@ -2,9 +2,9 @@ require 'rake/testtask'
2
2
  require 'reek/rake/task'
3
3
  require 'rubocop/rake_task'
4
4
 
5
- task default: %i[spec rubocop reek]
5
+ task default: %i(spec rubocop reek)
6
6
 
7
- Rake::TestTask.new :spec do |task|
7
+ Rake::TestTask.new(:spec) do |task|
8
8
  task.test_files = FileList['spec/**/*_spec.rb']
9
9
  task.warning = true
10
10
  end
@@ -15,4 +15,6 @@ Reek::Rake::Task.new do |task|
15
15
  task.reek_opts = '--quiet'
16
16
  end
17
17
 
18
- Rubocop::RakeTask.new
18
+ RuboCop::RakeTask.new do |task|
19
+ task.options << '--display-cop-names'
20
+ end
data/bin/kamerling CHANGED
@@ -4,6 +4,6 @@ require_relative '../lib/kamerling'
4
4
 
5
5
  Thread.abort_on_exception = true
6
6
 
7
- Kamerling::Logging.log_to Logger.new $stdout
7
+ Kamerling::Logging.log_to Logger.new($stdout)
8
8
 
9
9
  Kamerling::ServerRunner.new(ARGV).start.join
data/config/reek.yml CHANGED
@@ -1,7 +1,17 @@
1
1
  DuplicateMethodCall:
2
2
  exclude:
3
- - Kamerling#self.class_definition_from
4
- - Kamerling::Handler#handle
3
+ - Kamerling::Handler#handle
4
+ - Kamerling::Handler#process
5
+ - Kamerling::Logging#log_dispatcher
6
+ - Kamerling::Logging#log_server
7
+ - Kamerling::Mapper#to_h
8
+ - Kamerling::TaskDispatcher#dispatch_task
9
+
10
+ FeatureEnvy:
11
+ exclude:
12
+ # https://github.com/troessner/reek/issues/53
13
+ - Kamerling::NetDispatcher
14
+ - Kamerling::UUID
5
15
 
6
16
  IrresponsibleModule:
7
17
  enabled: false
@@ -11,4 +21,11 @@ NestedIterators:
11
21
 
12
22
  UnusedParameters:
13
23
  exclude:
14
- - Kamerling::Server::HTTP#initialize
24
+ - Kamerling::Server::HTTP#initialize
25
+
26
+ UtilityFunction:
27
+ exclude:
28
+ # https://github.com/troessner/reek/issues/27
29
+ - Kamerling::Mapper
30
+ - Kamerling::NetDispatcher
31
+ - Kamerling::UUID
data/kamerling.gemspec CHANGED
@@ -1,31 +1,34 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.author = 'Piotr Szotkowski'
3
- gem.description = 'A network server for distributing computations across different clients speaking TCP or UDP.'
3
+ gem.description = 'A network server for distributing computations across ' \
4
+ 'different clients speaking TCP or UDP.'
4
5
  gem.email = 'p.szotkowski@tele.pw.edu.pl'
5
6
  gem.homepage = 'https://github.com/chastell/kamerling'
6
7
  gem.license = 'AGPL-3.0'
7
8
  gem.name = 'kamerling'
8
9
  gem.summary = 'Kamerling: a computation network server'
9
- gem.version = '0.0.2'
10
+ gem.version = '0.0.3'
10
11
 
11
- gem.files = `git ls-files -z`.split "\0"
12
- gem.executables = gem.files.grep(%r{^bin/}).map { |path| File.basename path }
13
- gem.test_files = gem.files.grep %r{^spec/.*\.rb$}
12
+ gem.files = `git ls-files -z`.split("\0")
13
+ gem.executables = gem.files.grep(/^bin\//).map { |path| File.basename(path) }
14
+ gem.test_files = gem.files.grep(/^spec\/.*\.rb$/)
14
15
 
15
- gem.add_dependency 'after_do', '~> 0.3.0'
16
- gem.add_dependency 'sequel', '~> 4.4'
17
- gem.add_dependency 'sinatra', '~> 1.4'
18
- gem.add_dependency 'slim', '~> 2.0'
19
- gem.add_dependency 'sqlite3', '~> 1.3'
20
- gem.add_dependency 'virtus', '~> 1.0'
16
+ gem.add_dependency 'after_do', '~> 0.3.0'
17
+ gem.add_dependency 'equalizer', '~> 0.0.9'
18
+ gem.add_dependency 'sequel', '~> 4.4'
19
+ gem.add_dependency 'sinatra', '~> 1.4'
20
+ gem.add_dependency 'slim', '~> 2.0'
21
+ gem.add_dependency 'sqlite3', '~> 1.3'
22
+ gem.add_dependency 'virtus', '~> 1.0'
21
23
 
22
24
  gem.add_development_dependency 'bogus', '~> 0.1.3'
23
25
  gem.add_development_dependency 'minitest', '~> 5.0'
24
26
  gem.add_development_dependency 'minitest-focus', '~> 1.1'
25
27
  gem.add_development_dependency 'nokogiri', '~> 1.6'
28
+ gem.add_development_dependency 'pry', '~> 0.10.0'
26
29
  gem.add_development_dependency 'rack-test', '~> 0.6.2'
27
30
  gem.add_development_dependency 'rake', '~> 10.1'
28
31
  gem.add_development_dependency 'reek', '~> 1.3'
29
- gem.add_development_dependency 'rerun', '~> 0.9.0'
30
- gem.add_development_dependency 'rubocop', '~> 0.19.0'
32
+ gem.add_development_dependency 'rerun', '~> 0.10.0'
33
+ gem.add_development_dependency 'rubocop', '~> 0.27.0'
31
34
  end
data/lib/kamerling.rb CHANGED
@@ -1,29 +1,3 @@
1
- require 'socket'
2
-
3
- require_relative 'kamerling/core_extensions'
4
-
5
- include Kamerling::CoreExtensions::Main
6
-
7
- require_relative 'kamerling/addr'
8
- require_relative 'kamerling/handler'
9
- require_relative 'kamerling/message'
10
- require_relative 'kamerling/net_dispatcher'
11
- require_relative 'kamerling/receiver'
12
- require_relative 'kamerling/registrar'
13
- require_relative 'kamerling/repo'
14
- require_relative 'kamerling/repos'
15
- require_relative 'kamerling/http_api'
16
- require_relative 'kamerling/server/http'
17
- require_relative 'kamerling/server/sock'
18
- require_relative 'kamerling/server/tcp'
19
- require_relative 'kamerling/server/udp'
20
- require_relative 'kamerling/server_runner'
21
- require_relative 'kamerling/task_dispatcher'
22
- require_relative 'kamerling/uuid'
23
- require_relative 'kamerling/uuid_entity'
24
- require_relative 'kamerling/client'
25
- require_relative 'kamerling/project'
26
- require_relative 'kamerling/registration'
27
- require_relative 'kamerling/task'
28
- require_relative 'kamerling/result'
1
+ require_relative 'kamerling/core_extensions/main'
29
2
  require_relative 'kamerling/logging'
3
+ require_relative 'kamerling/server_runner'
@@ -1,5 +1,15 @@
1
+ require 'socket'
2
+ require 'uri'
3
+ require_relative 'value'
4
+
1
5
  module Kamerling
2
- Addr = Struct.new :host, :port, :prot do
6
+ class Addr < Value
7
+ vals host: String, port: Integer, prot: Symbol
8
+
9
+ def self.[](host, port, prot)
10
+ new(host: host, port: port, prot: prot)
11
+ end
12
+
3
13
  def connectable?
4
14
  TCPSocket.open(*self).close
5
15
  true
@@ -12,11 +22,15 @@ module Kamerling
12
22
  end
13
23
 
14
24
  def to_h
15
- super.merge prot: prot.to_s
25
+ attributes.merge(prot: prot.to_s)
16
26
  end
17
27
 
18
28
  def to_s
19
- "#{host}:#{port} (#{prot})"
29
+ uri.to_s
30
+ end
31
+
32
+ def uri
33
+ URI.parse("#{prot.downcase}://#{host}:#{port}")
20
34
  end
21
35
  end
22
36
  end
@@ -1,14 +1,13 @@
1
- module Kamerling class Client < UUIDEntity
2
- attribute :addr, Addr
3
- attribute :busy, Boolean, default: false
1
+ require_relative 'addr'
2
+ require_relative 'uuid_entity'
4
3
 
5
- def self.from_h hash
6
- super.tap do |client|
7
- client.addr = Addr[hash[:host], hash[:port], hash[:prot]]
8
- end
9
- end
4
+ module Kamerling
5
+ class Client < UUIDEntity
6
+ attrs addr: Addr, busy: Boolean, type: Symbol
7
+ defaults busy: false
10
8
 
11
- def to_h
12
- super.reject { |key, _| key == :addr }.merge addr.to_h
9
+ def to_h
10
+ attributes.merge(type: type.to_s)
11
+ end
13
12
  end
14
- end end
13
+ end