skylight 0.2.7 → 0.3.0.rc.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 +4 -4
- data/ext/checksums.yml +3 -0
- data/ext/extconf.rb +90 -0
- data/ext/skylight.map +4 -0
- data/ext/skylight_native.c +613 -0
- data/lib/skylight.rb +50 -7
- data/lib/skylight/config.rb +7 -1
- data/lib/skylight/helpers.rb +2 -2
- data/lib/skylight/instrumenter.rb +9 -5
- data/lib/skylight/messages.rb +13 -13
- data/lib/skylight/messages/error.rb +10 -6
- data/lib/skylight/messages/hello.rb +4 -45
- data/lib/skylight/messages/trace.rb +62 -103
- data/lib/skylight/messages/trace_envelope.rb +19 -0
- data/lib/skylight/native.rb +80 -0
- data/lib/skylight/normalizers/process_action.rb +1 -3
- data/lib/skylight/probes.rb +1 -1
- data/lib/skylight/subscriber.rb +1 -1
- data/lib/skylight/util/clock.rb +13 -6
- data/lib/skylight/version.rb +1 -1
- data/lib/skylight/worker/builder.rb +1 -1
- data/lib/skylight/worker/collector.rb +20 -32
- data/lib/skylight/worker/connection.rb +2 -2
- data/lib/skylight/worker/embedded.rb +18 -0
- data/lib/skylight/worker/server.rb +3 -3
- data/lib/skylight/worker/standalone.rb +9 -10
- data/lib/sql_lexer.rb +0 -1
- data/lib/sql_lexer/lexer.rb +50 -4
- data/lib/sql_lexer/version.rb +1 -1
- metadata +19 -22
- data/lib/skylight/messages/annotation.rb +0 -13
- data/lib/skylight/messages/base.rb +0 -24
- data/lib/skylight/messages/batch.rb +0 -12
- data/lib/skylight/messages/endpoint.rb +0 -12
- data/lib/skylight/messages/event.rb +0 -12
- data/lib/skylight/messages/span.rb +0 -166
- data/lib/skylight/vendor/beefcake.rb +0 -292
- data/lib/skylight/vendor/beefcake/buffer.rb +0 -119
- data/lib/skylight/vendor/beefcake/decode.rb +0 -107
- data/lib/skylight/vendor/beefcake/encode.rb +0 -132
data/lib/sql_lexer/version.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skylight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.rc.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tilde, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.0.0
|
27
27
|
description:
|
@@ -29,9 +29,17 @@ email:
|
|
29
29
|
- engineering@tilde.io
|
30
30
|
executables:
|
31
31
|
- skylight
|
32
|
-
extensions:
|
32
|
+
extensions:
|
33
|
+
- ext/extconf.rb
|
33
34
|
extra_rdoc_files: []
|
34
35
|
files:
|
36
|
+
- CHANGELOG.md
|
37
|
+
- README.md
|
38
|
+
- bin/skylight
|
39
|
+
- ext/checksums.yml
|
40
|
+
- ext/extconf.rb
|
41
|
+
- ext/skylight.map
|
42
|
+
- ext/skylight_native.c
|
35
43
|
- lib/skylight.rb
|
36
44
|
- lib/skylight/api.rb
|
37
45
|
- lib/skylight/cli.rb
|
@@ -43,16 +51,12 @@ files:
|
|
43
51
|
- lib/skylight/helpers.rb
|
44
52
|
- lib/skylight/instrumenter.rb
|
45
53
|
- lib/skylight/messages.rb
|
46
|
-
- lib/skylight/messages/annotation.rb
|
47
|
-
- lib/skylight/messages/base.rb
|
48
|
-
- lib/skylight/messages/batch.rb
|
49
|
-
- lib/skylight/messages/endpoint.rb
|
50
54
|
- lib/skylight/messages/error.rb
|
51
|
-
- lib/skylight/messages/event.rb
|
52
55
|
- lib/skylight/messages/hello.rb
|
53
|
-
- lib/skylight/messages/span.rb
|
54
56
|
- lib/skylight/messages/trace.rb
|
57
|
+
- lib/skylight/messages/trace_envelope.rb
|
55
58
|
- lib/skylight/middleware.rb
|
59
|
+
- lib/skylight/native.rb
|
56
60
|
- lib/skylight/normalizers.rb
|
57
61
|
- lib/skylight/normalizers/default.rb
|
58
62
|
- lib/skylight/normalizers/moped.rb
|
@@ -81,10 +85,6 @@ files:
|
|
81
85
|
- lib/skylight/vendor/active_support/notifications/fanout.rb
|
82
86
|
- lib/skylight/vendor/active_support/notifications/instrumenter.rb
|
83
87
|
- lib/skylight/vendor/active_support/per_thread_registry.rb
|
84
|
-
- lib/skylight/vendor/beefcake.rb
|
85
|
-
- lib/skylight/vendor/beefcake/buffer.rb
|
86
|
-
- lib/skylight/vendor/beefcake/decode.rb
|
87
|
-
- lib/skylight/vendor/beefcake/encode.rb
|
88
88
|
- lib/skylight/vendor/cli/highline.rb
|
89
89
|
- lib/skylight/vendor/cli/highline/color_scheme.rb
|
90
90
|
- lib/skylight/vendor/cli/highline/compatibility.rb
|
@@ -139,9 +139,6 @@ files:
|
|
139
139
|
- lib/sql_lexer.rb
|
140
140
|
- lib/sql_lexer/lexer.rb
|
141
141
|
- lib/sql_lexer/version.rb
|
142
|
-
- CHANGELOG.md
|
143
|
-
- README.md
|
144
|
-
- bin/skylight
|
145
142
|
homepage: http://www.skylight.io
|
146
143
|
licenses: []
|
147
144
|
metadata: {}
|
@@ -151,17 +148,17 @@ require_paths:
|
|
151
148
|
- lib
|
152
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
153
150
|
requirements:
|
154
|
-
- -
|
151
|
+
- - ">="
|
155
152
|
- !ruby/object:Gem::Version
|
156
153
|
version: 1.9.2
|
157
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
155
|
requirements:
|
159
|
-
- -
|
156
|
+
- - ">"
|
160
157
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
158
|
+
version: 1.3.1
|
162
159
|
requirements: []
|
163
160
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.0
|
161
|
+
rubygems_version: 2.2.0
|
165
162
|
signing_key:
|
166
163
|
specification_version: 4
|
167
164
|
summary: Skylight is a ruby application monitoring tool. Currently in closed beta.
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Skylight
|
2
|
-
module Messages
|
3
|
-
class Annotation
|
4
|
-
include Beefcake::Message
|
5
|
-
|
6
|
-
optional :key, :string, 1
|
7
|
-
optional :int, :int64, 2
|
8
|
-
optional :double, :double, 3
|
9
|
-
optional :string, :string, 4
|
10
|
-
repeated :nested, Annotation, 5
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Skylight
|
2
|
-
module Messages
|
3
|
-
class Base
|
4
|
-
module ClassMethods
|
5
|
-
attr_accessor :message_id
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.inherited(klass)
|
9
|
-
klass.class_eval do
|
10
|
-
include Beefcake::Message
|
11
|
-
extend ClassMethods
|
12
|
-
end
|
13
|
-
|
14
|
-
klass.message_id = (@count ||= 0)
|
15
|
-
Messages.set(klass.message_id, klass)
|
16
|
-
@count += 1
|
17
|
-
end
|
18
|
-
|
19
|
-
def message_id
|
20
|
-
self.class.message_id
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,166 +0,0 @@
|
|
1
|
-
module Skylight
|
2
|
-
module Messages
|
3
|
-
class AnnotationBuilder
|
4
|
-
def self.build(object)
|
5
|
-
new(object).build
|
6
|
-
end
|
7
|
-
|
8
|
-
def initialize(object)
|
9
|
-
@object = object
|
10
|
-
end
|
11
|
-
|
12
|
-
def build
|
13
|
-
build_nested(@object)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
def build_nested(object)
|
18
|
-
case object
|
19
|
-
when Hash
|
20
|
-
build_hash(object)
|
21
|
-
when Array
|
22
|
-
build_array(object)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def build_hash(object)
|
27
|
-
object.map do |key, value|
|
28
|
-
build_annotation(value, key)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def build_array(array)
|
33
|
-
array.map do |value|
|
34
|
-
build_annotation(value)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def build_annotation(value, key=nil)
|
39
|
-
Annotation.new.tap do |annotation|
|
40
|
-
annotation.key = key.to_s if key
|
41
|
-
annotation[classify(value)] = build_value(value)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def build_value(value)
|
46
|
-
nested?(value) ? build_nested(value) : value
|
47
|
-
end
|
48
|
-
|
49
|
-
def nested?(value)
|
50
|
-
value.is_a?(Array) || value.is_a?(Hash)
|
51
|
-
end
|
52
|
-
|
53
|
-
def classify(value)
|
54
|
-
case value
|
55
|
-
when String
|
56
|
-
:string
|
57
|
-
when Integer
|
58
|
-
:int
|
59
|
-
when Numeric
|
60
|
-
:double
|
61
|
-
when Hash, Array
|
62
|
-
:nested
|
63
|
-
else
|
64
|
-
raise Skylight::SerializeError.new("Annotation values must be Strings or Numeric. You passed #{value.inspect} in #{@object.inspect}")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class Span
|
70
|
-
include Beefcake::Message
|
71
|
-
|
72
|
-
required :event, Event, 1
|
73
|
-
repeated :annotations, Annotation, 2
|
74
|
-
required :started_at, :uint32, 3
|
75
|
-
optional :duration, :uint32, 4
|
76
|
-
optional :children, :uint32, 5
|
77
|
-
|
78
|
-
# Bit of a hack
|
79
|
-
attr_accessor :absolute_time
|
80
|
-
|
81
|
-
# Optimization
|
82
|
-
def initialize(attrs = nil)
|
83
|
-
super if attrs
|
84
|
-
end
|
85
|
-
|
86
|
-
class Builder
|
87
|
-
|
88
|
-
include Util::Logging
|
89
|
-
|
90
|
-
attr_reader \
|
91
|
-
:time,
|
92
|
-
:category,
|
93
|
-
:title,
|
94
|
-
:started_at,
|
95
|
-
:description,
|
96
|
-
:annotations
|
97
|
-
|
98
|
-
attr_accessor :children
|
99
|
-
|
100
|
-
def initialize(trace, time, started_at, cat, title, desc, annot)
|
101
|
-
@trace = trace
|
102
|
-
@built = false
|
103
|
-
@time = time
|
104
|
-
@started_at = started_at
|
105
|
-
@category = cat.to_s
|
106
|
-
@children = 0
|
107
|
-
@annotations = annot
|
108
|
-
|
109
|
-
self.title = title
|
110
|
-
self.description = desc
|
111
|
-
end
|
112
|
-
|
113
|
-
def config
|
114
|
-
@trace.config
|
115
|
-
end
|
116
|
-
|
117
|
-
def endpoint=(name)
|
118
|
-
@trace.endpoint = name
|
119
|
-
end
|
120
|
-
|
121
|
-
def done
|
122
|
-
@trace.done(self) unless built?
|
123
|
-
rescue Exception => e
|
124
|
-
error e.message
|
125
|
-
t { e.backtrace.join("\n") }
|
126
|
-
end
|
127
|
-
|
128
|
-
def built?
|
129
|
-
@built
|
130
|
-
end
|
131
|
-
|
132
|
-
def build(duration)
|
133
|
-
@built = true
|
134
|
-
Span.new(
|
135
|
-
event: Event.new(
|
136
|
-
category: category,
|
137
|
-
title: title,
|
138
|
-
description: description),
|
139
|
-
annotations: nil,
|
140
|
-
started_at: @started_at,
|
141
|
-
duration: duration && duration > 0 ? duration : nil,
|
142
|
-
children: @children > 0 ? @children : nil)
|
143
|
-
end
|
144
|
-
|
145
|
-
def title=(val)
|
146
|
-
val = nil unless val.respond_to?(:to_str)
|
147
|
-
@title = val && val.to_str
|
148
|
-
end
|
149
|
-
|
150
|
-
def description=(val)
|
151
|
-
val = nil unless val.respond_to?(:to_str)
|
152
|
-
@description = val && val.to_str
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
def to_annotations(val)
|
158
|
-
return nil if !val || val.empty?
|
159
|
-
|
160
|
-
AnnotationBuilder.build(val)
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
@@ -1,292 +0,0 @@
|
|
1
|
-
require 'skylight/vendor/beefcake/encode'
|
2
|
-
require 'skylight/vendor/beefcake/decode'
|
3
|
-
|
4
|
-
module Skylight
|
5
|
-
module Beefcake
|
6
|
-
module Message
|
7
|
-
|
8
|
-
class WrongTypeError < StandardError
|
9
|
-
def initialize(name, exp, got)
|
10
|
-
super("Wrong type `#{got}` given for (#{name}). Expected #{exp}")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
class InvalidValueError < StandardError
|
16
|
-
def initialize(name, val)
|
17
|
-
super("Invalid Value given for `#{name}`: #{val.inspect}")
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
class RequiredFieldNotSetError < StandardError
|
23
|
-
def initialize(name)
|
24
|
-
super("Field #{name} is required but nil")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
class Field < Struct.new(:rule, :name, :type, :fn, :opts)
|
30
|
-
def <=>(o)
|
31
|
-
fn <=> o.fn
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
module Dsl
|
37
|
-
def self.extended(base)
|
38
|
-
initializer = Module.new
|
39
|
-
base.instance_variable_set(:@__initializer, initializer)
|
40
|
-
base.__write_initializer
|
41
|
-
base.send(:include, initializer)
|
42
|
-
end
|
43
|
-
|
44
|
-
def required(name, type, fn, opts={})
|
45
|
-
field(:required, name, type, fn, opts)
|
46
|
-
end
|
47
|
-
|
48
|
-
def repeated(name, type, fn, opts={})
|
49
|
-
field(:repeated, name, type, fn, opts)
|
50
|
-
end
|
51
|
-
|
52
|
-
def optional(name, type, fn, opts={})
|
53
|
-
field(:optional, name, type, fn, opts)
|
54
|
-
end
|
55
|
-
|
56
|
-
def field(rule, name, type, fn, opts)
|
57
|
-
field = Field.new(rule, name, type, fn, opts)
|
58
|
-
indexed_fields[fn] = field
|
59
|
-
fields << field
|
60
|
-
fields.sort!
|
61
|
-
__write_initializer
|
62
|
-
attr_accessor name
|
63
|
-
end
|
64
|
-
|
65
|
-
def fields
|
66
|
-
@fields ||= []
|
67
|
-
end
|
68
|
-
|
69
|
-
def indexed_fields
|
70
|
-
@indexed_fields ||= {}
|
71
|
-
end
|
72
|
-
|
73
|
-
def __write_initializer
|
74
|
-
lines = []
|
75
|
-
|
76
|
-
lines << "def initialize(attrs=nil)"
|
77
|
-
lines << "return unless attrs"
|
78
|
-
fields.each do |fld|
|
79
|
-
lines << "@#{fld.name} = attrs[:#{fld.name}]"
|
80
|
-
end
|
81
|
-
|
82
|
-
lines << "end"
|
83
|
-
|
84
|
-
@__initializer.module_eval(lines.join("\n"), __FILE__, __LINE__+1)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
module Encode
|
89
|
-
|
90
|
-
def encode(buf = Buffer.new)
|
91
|
-
validate!
|
92
|
-
|
93
|
-
if ! buf.respond_to?(:<<)
|
94
|
-
raise ArgumentError, "buf doesn't respond to `<<`"
|
95
|
-
end
|
96
|
-
|
97
|
-
if ! buf.is_a?(Buffer)
|
98
|
-
buf = Buffer.new(buf)
|
99
|
-
end
|
100
|
-
|
101
|
-
# TODO: Error if any required fields at nil
|
102
|
-
|
103
|
-
fields.each do |fld|
|
104
|
-
if fld.opts[:packed]
|
105
|
-
bytes = encode!(Buffer.new, fld, 0)
|
106
|
-
buf.append_info(fld.fn, Buffer.wire_for(fld.type))
|
107
|
-
buf.append_uint64(bytes.length)
|
108
|
-
buf << bytes
|
109
|
-
else
|
110
|
-
encode!(buf, fld, fld.fn)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
buf
|
115
|
-
end
|
116
|
-
|
117
|
-
def encode!(buf, fld, fn)
|
118
|
-
v = self[fld.name]
|
119
|
-
|
120
|
-
if v.is_a?(Array)
|
121
|
-
v.each do |val|
|
122
|
-
encode_field!(buf, fld.type, val, fn)
|
123
|
-
end
|
124
|
-
else
|
125
|
-
encode_field!(buf, fld.type, v, fn)
|
126
|
-
end
|
127
|
-
|
128
|
-
buf
|
129
|
-
end
|
130
|
-
|
131
|
-
def encode_field!(buf, type, val, fn)
|
132
|
-
return if val.nil?
|
133
|
-
|
134
|
-
case type
|
135
|
-
when Class # encodable
|
136
|
-
# TODO: raise error if type != val.class
|
137
|
-
buf.append(:string, val.encode, fn)
|
138
|
-
when Module # enum
|
139
|
-
if ! valid_enum?(type, val)
|
140
|
-
raise InvalidValueError.new(fld.name, val)
|
141
|
-
end
|
142
|
-
|
143
|
-
buf.append(:int32, val, fn)
|
144
|
-
else
|
145
|
-
buf.append(type, val, fn)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def valid_enum?(mod, val)
|
150
|
-
!!name_for(mod, val)
|
151
|
-
end
|
152
|
-
|
153
|
-
def name_for(mod, val)
|
154
|
-
mod.constants.each do |name|
|
155
|
-
if mod.const_get(name) == val
|
156
|
-
return name
|
157
|
-
end
|
158
|
-
end
|
159
|
-
nil
|
160
|
-
end
|
161
|
-
|
162
|
-
def validate!
|
163
|
-
fields.each do |fld|
|
164
|
-
if fld.rule == :required && self[fld.name].nil?
|
165
|
-
raise RequiredFieldNotSetError, fld.name
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
|
172
|
-
module Decode
|
173
|
-
# Use allocate instead of new for performance
|
174
|
-
def decode(buf, o=self.allocate)
|
175
|
-
if ! buf.is_a?(Buffer)
|
176
|
-
buf = Buffer.new(buf)
|
177
|
-
end
|
178
|
-
|
179
|
-
# TODO: test for incomplete buffer
|
180
|
-
while buf.length > 0
|
181
|
-
fn, wire = buf.read_info
|
182
|
-
|
183
|
-
fld = indexed_fields[fn]
|
184
|
-
|
185
|
-
# We don't have a field for with index fn.
|
186
|
-
# Ignore this data and move on.
|
187
|
-
if fld.nil?
|
188
|
-
buf.skip(wire)
|
189
|
-
next
|
190
|
-
end
|
191
|
-
|
192
|
-
exp = Buffer.wire_for(fld.type)
|
193
|
-
if wire != exp
|
194
|
-
raise WrongTypeError.new(fld.name, exp, wire)
|
195
|
-
end
|
196
|
-
|
197
|
-
if fld.rule == :repeated && fld.opts[:packed]
|
198
|
-
len = buf.read_uint64
|
199
|
-
tmp = Buffer.new(buf.read(len))
|
200
|
-
o[fld.name] ||= []
|
201
|
-
while tmp.length > 0
|
202
|
-
o[fld.name] << tmp.read(fld.type)
|
203
|
-
end
|
204
|
-
elsif fld.rule == :repeated
|
205
|
-
val = buf.read(fld.type)
|
206
|
-
(o[fld.name] ||= []) << val
|
207
|
-
else
|
208
|
-
val = buf.read(fld.type)
|
209
|
-
o[fld.name] = val
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# Set defaults
|
214
|
-
fields.each do |f|
|
215
|
-
next if o[f.name] == false
|
216
|
-
o[f.name] ||= f.opts[:default]
|
217
|
-
end
|
218
|
-
|
219
|
-
o.validate!
|
220
|
-
|
221
|
-
o
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
|
226
|
-
def self.included(o)
|
227
|
-
o.extend Dsl
|
228
|
-
o.extend Decode
|
229
|
-
o.send(:include, Encode)
|
230
|
-
end
|
231
|
-
|
232
|
-
def fields
|
233
|
-
self.class.fields
|
234
|
-
end
|
235
|
-
|
236
|
-
def indexed_fields
|
237
|
-
self.class.indexed_fields
|
238
|
-
end
|
239
|
-
|
240
|
-
def [](k)
|
241
|
-
__send__(k)
|
242
|
-
end
|
243
|
-
|
244
|
-
def []=(k, v)
|
245
|
-
__send__("#{k}=", v)
|
246
|
-
end
|
247
|
-
|
248
|
-
def ==(o)
|
249
|
-
return false if (o == nil) || (o == false)
|
250
|
-
return false unless o.respond_to?(:[])
|
251
|
-
fields.all? do |fld|
|
252
|
-
if fld.rule == :repeated
|
253
|
-
Array(self[fld.name]) == Array(o[fld.name])
|
254
|
-
else
|
255
|
-
self[fld.name] == o[fld.name]
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def inspect
|
261
|
-
set = fields.select {|fld| self[fld.name] != nil }
|
262
|
-
|
263
|
-
flds = set.map do |fld|
|
264
|
-
val = self[fld.name]
|
265
|
-
|
266
|
-
case fld.type
|
267
|
-
when Class
|
268
|
-
"#{fld.name}: #{val.inspect}"
|
269
|
-
when Module
|
270
|
-
title = name_for(fld.type, val) || "-NA-"
|
271
|
-
"#{fld.name}: #{title}(#{val.inspect})"
|
272
|
-
else
|
273
|
-
"#{fld.name}: #{val.inspect}"
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
"<#{self.class.name} #{flds.join(", ")}>"
|
278
|
-
end
|
279
|
-
|
280
|
-
def to_hash
|
281
|
-
fields.inject({}) do |h, fld|
|
282
|
-
if v = self[fld.name]
|
283
|
-
h[fld.name] = v
|
284
|
-
end
|
285
|
-
h
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
end
|
290
|
-
|
291
|
-
end
|
292
|
-
end
|