ar_protobuf_store 0.1.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.
@@ -0,0 +1,124 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ ar_protobuf_store (0.1.0)
5
+ activerecord (>= 3.0, <= 4.1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.1.1)
11
+ actionpack (= 4.1.1)
12
+ actionview (= 4.1.1)
13
+ mail (~> 2.5.4)
14
+ actionpack (4.1.1)
15
+ actionview (= 4.1.1)
16
+ activesupport (= 4.1.1)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ actionview (4.1.1)
20
+ activesupport (= 4.1.1)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ activemodel (4.1.1)
24
+ activesupport (= 4.1.1)
25
+ builder (~> 3.1)
26
+ activerecord (4.1.1)
27
+ activemodel (= 4.1.1)
28
+ activesupport (= 4.1.1)
29
+ arel (~> 5.0.0)
30
+ activesupport (4.1.1)
31
+ i18n (~> 0.6, >= 0.6.9)
32
+ json (~> 1.7, >= 1.7.7)
33
+ minitest (~> 5.1)
34
+ thread_safe (~> 0.1)
35
+ tzinfo (~> 1.1)
36
+ appraisal (1.0.0)
37
+ bundler
38
+ rake
39
+ thor (>= 0.14.0)
40
+ arel (5.0.1.20140414130214)
41
+ builder (3.2.2)
42
+ coderay (1.1.0)
43
+ diff-lcs (1.2.5)
44
+ erubis (2.7.0)
45
+ hike (1.2.3)
46
+ i18n (0.6.9)
47
+ json (1.8.1)
48
+ mail (2.5.4)
49
+ mime-types (~> 1.16)
50
+ treetop (~> 1.4.8)
51
+ method_source (0.8.2)
52
+ mime-types (1.25.1)
53
+ minitest (5.3.4)
54
+ multi_json (1.10.1)
55
+ polyglot (0.3.4)
56
+ pry (0.9.12.6)
57
+ coderay (~> 1.0)
58
+ method_source (~> 0.8)
59
+ slop (~> 3.4)
60
+ rack (1.5.2)
61
+ rack-test (0.6.2)
62
+ rack (>= 1.0)
63
+ rails (4.1.1)
64
+ actionmailer (= 4.1.1)
65
+ actionpack (= 4.1.1)
66
+ actionview (= 4.1.1)
67
+ activemodel (= 4.1.1)
68
+ activerecord (= 4.1.1)
69
+ activesupport (= 4.1.1)
70
+ bundler (>= 1.3.0, < 2.0)
71
+ railties (= 4.1.1)
72
+ sprockets-rails (~> 2.0)
73
+ railties (4.1.1)
74
+ actionpack (= 4.1.1)
75
+ activesupport (= 4.1.1)
76
+ rake (>= 0.8.7)
77
+ thor (>= 0.18.1, < 2.0)
78
+ rake (10.3.2)
79
+ rspec (2.14.1)
80
+ rspec-core (~> 2.14.0)
81
+ rspec-expectations (~> 2.14.0)
82
+ rspec-mocks (~> 2.14.0)
83
+ rspec-core (2.14.8)
84
+ rspec-expectations (2.14.5)
85
+ diff-lcs (>= 1.1.3, < 2.0)
86
+ rspec-mocks (2.14.6)
87
+ ruby-protocol-buffers (1.5.1)
88
+ ruby_protobuf (0.4.11)
89
+ rubygems-tasks (0.2.4)
90
+ slop (3.5.0)
91
+ sprockets (2.12.1)
92
+ hike (~> 1.2)
93
+ multi_json (~> 1.0)
94
+ rack (~> 1.0)
95
+ tilt (~> 1.1, != 1.3.0)
96
+ sprockets-rails (2.1.3)
97
+ actionpack (>= 3.0)
98
+ activesupport (>= 3.0)
99
+ sprockets (~> 2.8)
100
+ sqlite3 (1.3.9)
101
+ thor (0.19.1)
102
+ thread_safe (0.3.3)
103
+ tilt (1.4.1)
104
+ treetop (1.4.15)
105
+ polyglot
106
+ polyglot (>= 0.3.1)
107
+ tzinfo (1.1.0)
108
+ thread_safe (~> 0.1)
109
+ yard (0.8.7.4)
110
+
111
+ PLATFORMS
112
+ ruby
113
+
114
+ DEPENDENCIES
115
+ appraisal (~> 1.0.0)
116
+ ar_protobuf_store!
117
+ pry (~> 0.9)
118
+ rails (~> 4.0)
119
+ rspec (~> 2.4)
120
+ ruby-protocol-buffers (~> 1.5)
121
+ ruby_protobuf (~> 0.4)
122
+ rubygems-tasks (~> 0.2)
123
+ sqlite3 (~> 1.3)
124
+ yard (~> 0.8)
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1"
6
+ gem "protobuf", "~> 3.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,129 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ ar_protobuf_store (0.1.0)
5
+ activerecord (>= 3.0, <= 4.1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.1.1)
11
+ actionpack (= 4.1.1)
12
+ actionview (= 4.1.1)
13
+ mail (~> 2.5.4)
14
+ actionpack (4.1.1)
15
+ actionview (= 4.1.1)
16
+ activesupport (= 4.1.1)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ actionview (4.1.1)
20
+ activesupport (= 4.1.1)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ activemodel (4.1.1)
24
+ activesupport (= 4.1.1)
25
+ builder (~> 3.1)
26
+ activerecord (4.1.1)
27
+ activemodel (= 4.1.1)
28
+ activesupport (= 4.1.1)
29
+ arel (~> 5.0.0)
30
+ activesupport (4.1.1)
31
+ i18n (~> 0.6, >= 0.6.9)
32
+ json (~> 1.7, >= 1.7.7)
33
+ minitest (~> 5.1)
34
+ thread_safe (~> 0.1)
35
+ tzinfo (~> 1.1)
36
+ appraisal (1.0.0)
37
+ bundler
38
+ rake
39
+ thor (>= 0.14.0)
40
+ arel (5.0.1.20140414130214)
41
+ builder (3.2.2)
42
+ coderay (1.1.0)
43
+ diff-lcs (1.2.5)
44
+ erubis (2.7.0)
45
+ hike (1.2.3)
46
+ i18n (0.6.9)
47
+ json (1.8.1)
48
+ mail (2.5.4)
49
+ mime-types (~> 1.16)
50
+ treetop (~> 1.4.8)
51
+ method_source (0.8.2)
52
+ middleware (0.1.0)
53
+ mime-types (1.25.1)
54
+ minitest (5.3.4)
55
+ multi_json (1.10.1)
56
+ polyglot (0.3.4)
57
+ protobuf (3.0.4)
58
+ activesupport (>= 3.2)
59
+ middleware
60
+ multi_json
61
+ thor
62
+ pry (0.9.12.6)
63
+ coderay (~> 1.0)
64
+ method_source (~> 0.8)
65
+ slop (~> 3.4)
66
+ rack (1.5.2)
67
+ rack-test (0.6.2)
68
+ rack (>= 1.0)
69
+ rails (4.1.1)
70
+ actionmailer (= 4.1.1)
71
+ actionpack (= 4.1.1)
72
+ actionview (= 4.1.1)
73
+ activemodel (= 4.1.1)
74
+ activerecord (= 4.1.1)
75
+ activesupport (= 4.1.1)
76
+ bundler (>= 1.3.0, < 2.0)
77
+ railties (= 4.1.1)
78
+ sprockets-rails (~> 2.0)
79
+ railties (4.1.1)
80
+ actionpack (= 4.1.1)
81
+ activesupport (= 4.1.1)
82
+ rake (>= 0.8.7)
83
+ thor (>= 0.18.1, < 2.0)
84
+ rake (10.3.2)
85
+ rspec (2.14.1)
86
+ rspec-core (~> 2.14.0)
87
+ rspec-expectations (~> 2.14.0)
88
+ rspec-mocks (~> 2.14.0)
89
+ rspec-core (2.14.8)
90
+ rspec-expectations (2.14.5)
91
+ diff-lcs (>= 1.1.3, < 2.0)
92
+ rspec-mocks (2.14.6)
93
+ ruby-protocol-buffers (1.5.1)
94
+ rubygems-tasks (0.2.4)
95
+ slop (3.5.0)
96
+ sprockets (2.12.1)
97
+ hike (~> 1.2)
98
+ multi_json (~> 1.0)
99
+ rack (~> 1.0)
100
+ tilt (~> 1.1, != 1.3.0)
101
+ sprockets-rails (2.1.3)
102
+ actionpack (>= 3.0)
103
+ activesupport (>= 3.0)
104
+ sprockets (~> 2.8)
105
+ sqlite3 (1.3.9)
106
+ thor (0.19.1)
107
+ thread_safe (0.3.3)
108
+ tilt (1.4.1)
109
+ treetop (1.4.15)
110
+ polyglot
111
+ polyglot (>= 0.3.1)
112
+ tzinfo (1.1.0)
113
+ thread_safe (~> 0.1)
114
+ yard (0.8.7.4)
115
+
116
+ PLATFORMS
117
+ ruby
118
+
119
+ DEPENDENCIES
120
+ appraisal (~> 1.0.0)
121
+ ar_protobuf_store!
122
+ protobuf (~> 3.0)
123
+ pry (~> 0.9)
124
+ rails (~> 4.1)
125
+ rspec (~> 2.4)
126
+ ruby-protocol-buffers (~> 1.5)
127
+ rubygems-tasks (~> 0.2)
128
+ sqlite3 (~> 1.3)
129
+ yard (~> 0.8)
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1"
6
+ gem "ruby_protobuf", "~> 0.4"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,124 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ ar_protobuf_store (0.1.0)
5
+ activerecord (>= 3.0, <= 4.1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.1.1)
11
+ actionpack (= 4.1.1)
12
+ actionview (= 4.1.1)
13
+ mail (~> 2.5.4)
14
+ actionpack (4.1.1)
15
+ actionview (= 4.1.1)
16
+ activesupport (= 4.1.1)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ actionview (4.1.1)
20
+ activesupport (= 4.1.1)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ activemodel (4.1.1)
24
+ activesupport (= 4.1.1)
25
+ builder (~> 3.1)
26
+ activerecord (4.1.1)
27
+ activemodel (= 4.1.1)
28
+ activesupport (= 4.1.1)
29
+ arel (~> 5.0.0)
30
+ activesupport (4.1.1)
31
+ i18n (~> 0.6, >= 0.6.9)
32
+ json (~> 1.7, >= 1.7.7)
33
+ minitest (~> 5.1)
34
+ thread_safe (~> 0.1)
35
+ tzinfo (~> 1.1)
36
+ appraisal (1.0.0)
37
+ bundler
38
+ rake
39
+ thor (>= 0.14.0)
40
+ arel (5.0.1.20140414130214)
41
+ builder (3.2.2)
42
+ coderay (1.1.0)
43
+ diff-lcs (1.2.5)
44
+ erubis (2.7.0)
45
+ hike (1.2.3)
46
+ i18n (0.6.9)
47
+ json (1.8.1)
48
+ mail (2.5.4)
49
+ mime-types (~> 1.16)
50
+ treetop (~> 1.4.8)
51
+ method_source (0.8.2)
52
+ mime-types (1.25.1)
53
+ minitest (5.3.4)
54
+ multi_json (1.10.1)
55
+ polyglot (0.3.4)
56
+ pry (0.9.12.6)
57
+ coderay (~> 1.0)
58
+ method_source (~> 0.8)
59
+ slop (~> 3.4)
60
+ rack (1.5.2)
61
+ rack-test (0.6.2)
62
+ rack (>= 1.0)
63
+ rails (4.1.1)
64
+ actionmailer (= 4.1.1)
65
+ actionpack (= 4.1.1)
66
+ actionview (= 4.1.1)
67
+ activemodel (= 4.1.1)
68
+ activerecord (= 4.1.1)
69
+ activesupport (= 4.1.1)
70
+ bundler (>= 1.3.0, < 2.0)
71
+ railties (= 4.1.1)
72
+ sprockets-rails (~> 2.0)
73
+ railties (4.1.1)
74
+ actionpack (= 4.1.1)
75
+ activesupport (= 4.1.1)
76
+ rake (>= 0.8.7)
77
+ thor (>= 0.18.1, < 2.0)
78
+ rake (10.3.2)
79
+ rspec (2.14.1)
80
+ rspec-core (~> 2.14.0)
81
+ rspec-expectations (~> 2.14.0)
82
+ rspec-mocks (~> 2.14.0)
83
+ rspec-core (2.14.8)
84
+ rspec-expectations (2.14.5)
85
+ diff-lcs (>= 1.1.3, < 2.0)
86
+ rspec-mocks (2.14.6)
87
+ ruby-protocol-buffers (1.5.1)
88
+ ruby_protobuf (0.4.11)
89
+ rubygems-tasks (0.2.4)
90
+ slop (3.5.0)
91
+ sprockets (2.12.1)
92
+ hike (~> 1.2)
93
+ multi_json (~> 1.0)
94
+ rack (~> 1.0)
95
+ tilt (~> 1.1, != 1.3.0)
96
+ sprockets-rails (2.1.3)
97
+ actionpack (>= 3.0)
98
+ activesupport (>= 3.0)
99
+ sprockets (~> 2.8)
100
+ sqlite3 (1.3.9)
101
+ thor (0.19.1)
102
+ thread_safe (0.3.3)
103
+ tilt (1.4.1)
104
+ treetop (1.4.15)
105
+ polyglot
106
+ polyglot (>= 0.3.1)
107
+ tzinfo (1.1.0)
108
+ thread_safe (~> 0.1)
109
+ yard (0.8.7.4)
110
+
111
+ PLATFORMS
112
+ ruby
113
+
114
+ DEPENDENCIES
115
+ appraisal (~> 1.0.0)
116
+ ar_protobuf_store!
117
+ pry (~> 0.9)
118
+ rails (~> 4.1)
119
+ rspec (~> 2.4)
120
+ ruby-protocol-buffers (~> 1.5)
121
+ ruby_protobuf (~> 0.4)
122
+ rubygems-tasks (~> 0.2)
123
+ sqlite3 (~> 1.3)
124
+ yard (~> 0.8)
@@ -0,0 +1,67 @@
1
+ module ArProtobufStore
2
+ class CodekitchenProtobufParser
3
+ def initialize(pb_class, opts = nil)
4
+ @klass = pb_class
5
+ @opts = opts
6
+ @opts ||= { :default => Proc.new { pb_class.new() } }
7
+ end
8
+
9
+ def load(str)
10
+ if str.nil?
11
+ return default_value
12
+ else
13
+ return @klass.new.tap { |o| o.parse(str) }
14
+ end
15
+ rescue Exception
16
+ if defined?(Rails)
17
+ Rails.logger.error("Failed to deserialize: #{$!}")
18
+ else
19
+ puts "Failed to deserialize: #{$!}"
20
+ end
21
+
22
+ return default_value
23
+ end
24
+
25
+ def dump(str)
26
+ str.serialize_to_string
27
+ end
28
+
29
+ def extract_fields(accessors = nil)
30
+ fields = @klass.fields.values
31
+
32
+ if !accessors.nil?
33
+ accessors = accessors.dup.map { |a| a.to_s }
34
+ fields = fields.select { |field|
35
+ accessors.include?(field.name.to_s)
36
+ }
37
+ end
38
+
39
+ typed_fields = fields.map do |field|
40
+ t = case field
41
+ when ProtocolBuffers::Field::StringField
42
+ :string
43
+ when ProtocolBuffers::Field::VarintField
44
+ :int
45
+ when ProtocolBuffers::Field::FloatField, ProtocolBuffers::Field::DoubleField
46
+ :float
47
+ else
48
+ nil
49
+ end
50
+ { :name => field.name.to_s, :type => t }
51
+ end
52
+
53
+ return typed_fields
54
+ end
55
+
56
+ private
57
+ def default_value
58
+ if @opts[:default].respond_to? :call
59
+ @opts[:default].call
60
+ elsif @opts[:default].duplicable?
61
+ @opts[:default].dup
62
+ else
63
+ @opts[:default]
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,68 @@
1
+ module ArProtobufStore
2
+ class ProtobufParser
3
+ def initialize(pb_class, opts = nil)
4
+ @klass = pb_class
5
+ @opts = opts
6
+ @opts ||= { :default => Proc.new { pb_class.new() } }
7
+ end
8
+
9
+ def load(str)
10
+ if str.nil?
11
+ return default_value
12
+ else
13
+ return @klass.new.tap { |o| o.parse_from_string(str) }
14
+ end
15
+ rescue Exception
16
+ if defined?(Rails)
17
+ Rails.logger.error("Failed to deserialize: #{$!}")
18
+ else
19
+ puts "Failed to deserialize: #{$!}"
20
+ end
21
+
22
+ return default_value
23
+ end
24
+
25
+ def dump(str)
26
+ str.serialize_to_string
27
+ end
28
+
29
+ def extract_fields(accessors = nil)
30
+ fields = @klass.fields
31
+ fields = fields.values if fields.respond_to?(:values)
32
+
33
+ if !accessors.nil?
34
+ accessors = accessors.dup.map { |a| a.to_s }
35
+ fields = fields.select { |field|
36
+ accessors.include?(field.name.to_s)
37
+ }
38
+ end
39
+
40
+ typed_fields = fields.map do |field|
41
+ t = case field
42
+ when Protobuf::Field::StringField
43
+ :string
44
+ when Protobuf::Field::VarintField
45
+ :int
46
+ when Protobuf::Field::FloatField
47
+ :float
48
+ else
49
+ nil
50
+ end
51
+ { :name => field.name.to_s, :type => t }
52
+ end
53
+
54
+ return typed_fields
55
+ end
56
+
57
+ private
58
+ def default_value
59
+ if @opts[:default].respond_to? :call
60
+ @opts[:default].call
61
+ elsif @opts[:default].duplicable?
62
+ @opts[:default].dup
63
+ else
64
+ @opts[:default]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,12 @@
1
+ require 'ar_protobuf_store'
2
+ require 'rails'
3
+
4
+ module ArProtobufStore
5
+ class Railtie < ::Rails::Railtie
6
+ initializer "ar_protobuf_store.active_record" do |app|
7
+ ActiveSupport.on_load :active_record do
8
+ Ar::Base.send :include, ArProtobufStore
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module ArProtobufStore
2
+ # ar_protobuf_store version
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,57 @@
1
+ require 'ar_protobuf_store/version'
2
+
3
+ require 'ar_protobuf_store/railtie.rb' if defined?(Rails)
4
+
5
+ module ArProtobufStore
6
+ autoload(:CodekitchenProtobufParser,
7
+ "ar_protobuf_store/codekitchen_protobuf_parser")
8
+ autoload(:ProtobufParser,
9
+ "ar_protobuf_store/protobuf_parser")
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ def self.find_parser!(pb_class)
16
+ if defined?(ProtocolBuffers) && ::ProtocolBuffers::Message > pb_class
17
+ return ArProtobufStore::CodekitchenProtobufParser.new(pb_class)
18
+ elsif defined?(Protobuf) && ::Protobuf::Message > pb_class
19
+ return ArProtobufStore::ProtobufParser.new(pb_class)
20
+ else
21
+ raise "Could not identify protocol buffer library for #{pb_class}"
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ def protobuf_store(store_attribute, pb_class, options={})
27
+ parser = ArProtobufStore.find_parser!(pb_class)
28
+ serialize(store_attribute, parser)
29
+ protobuf_store_accessor(store_attribute, parser.extract_fields(options[:accessors]))
30
+ end
31
+
32
+ def protobuf_store_accessor(store_attribute, *keys)
33
+ Array(keys).flatten.each do |key|
34
+ name = key[:name]
35
+ coercer = case key[:type]
36
+ when :int
37
+ ".to_i"
38
+ when :float
39
+ ".to_f"
40
+ when :string
41
+ ".to_s"
42
+ else
43
+ ""
44
+ end
45
+ class_eval <<-"END_EVAL", __FILE__, __LINE__
46
+ def #{name}=(value)
47
+ self.#{store_attribute}_will_change!
48
+ self.#{store_attribute}.#{name} = value#{coercer}
49
+ end
50
+ def #{name}
51
+ self.#{store_attribute}.#{name}
52
+ end
53
+ END_EVAL
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'ar_protobuf_store'
3
+ require 'protocol_buffers'
4
+
5
+ describe ArProtobufStore do
6
+ it "should have a VERSION constant" do
7
+ subject.const_get('VERSION').should_not be_empty
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+ require "ar_protobuf_store"
3
+
4
+ begin
5
+ require "protocol_buffers"
6
+
7
+ describe ArProtobufStore::CodekitchenProtobufParser do
8
+ around(:each) do |example|
9
+ setup_db do
10
+ create_table :foos do |t|
11
+ t.column :extras, :binary
12
+ end
13
+ end
14
+
15
+ example.run
16
+
17
+ teardown_db
18
+ end
19
+
20
+ let(:ar_klass) {
21
+ # Define everything using anonymous classes to reduce leakage.
22
+ extras = Class.new(::ProtocolBuffers::Message) do
23
+ optional :uint64, :int_attr, 1
24
+ optional :string, :str_attr, 2
25
+ end
26
+
27
+ Class.new(::ActiveRecord::Base) do
28
+ self.table_name = "foos"
29
+
30
+ include ArProtobufStore
31
+
32
+ protobuf_store :extras, extras
33
+ end
34
+ }
35
+
36
+ describe ArProtobufStore::ClassMethods do
37
+ it "should allow setting fields individually" do
38
+ record = ar_klass.create!
39
+ record.int_attr = 2
40
+ record.str_attr = "TEST"
41
+ record.save
42
+ expect(record.persisted?).to eq(true)
43
+ record_id = record.id
44
+
45
+ record = ar_klass.find(record_id)
46
+ expect(record.int_attr).to eq(2)
47
+ expect(record.str_attr).to eq("TEST")
48
+ end
49
+
50
+ it "should allow setting fields in constructor" do
51
+ record = ar_klass.create!(:int_attr => 2, :str_attr => "TEST")
52
+ expect(record.persisted?).to eq(true)
53
+ record_id = record.id
54
+
55
+ record = ar_klass.find(record_id)
56
+ expect(record.int_attr).to eq(2)
57
+ expect(record.str_attr).to eq("TEST")
58
+ end
59
+ end
60
+ end
61
+ rescue LoadError
62
+ # Ignore: protobuf isn't loaded!
63
+ end