active_explorer 0.0.7
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.standalone_migrations +6 -0
- data/.travis.yml +4 -0
- data/Appraisals +27 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Guardfile +27 -0
- data/LICENSE.txt +21 -0
- data/README.md +230 -0
- data/Rakefile +7 -0
- data/active_explorer.gemspec +38 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/gemfiles/activerecord_3_0.gemfile +7 -0
- data/gemfiles/activerecord_3_0.gemfile.lock +111 -0
- data/gemfiles/activerecord_3_1.gemfile +7 -0
- data/gemfiles/activerecord_3_1.gemfile.lock +113 -0
- data/gemfiles/activerecord_3_2.gemfile +7 -0
- data/gemfiles/activerecord_3_2.gemfile.lock +113 -0
- data/gemfiles/activerecord_4_0.gemfile +7 -0
- data/gemfiles/activerecord_4_0.gemfile.lock +119 -0
- data/gemfiles/activerecord_4_1.gemfile +7 -0
- data/gemfiles/activerecord_4_1.gemfile.lock +118 -0
- data/gemfiles/activerecord_4_2.gemfile +7 -0
- data/gemfiles/activerecord_4_2.gemfile.lock +118 -0
- data/gemfiles/activerecord_5_0.gemfile +7 -0
- data/gemfiles/activerecord_5_0.gemfile.lock +115 -0
- data/lib/active_explorer/version.rb +3 -0
- data/lib/active_explorer.rb +58 -0
- data/lib/config.rb +8 -0
- data/lib/exploration.rb +233 -0
- data/lib/painter.rb +101 -0
- data/lib/writer.rb +48 -0
- metadata +284 -0
data/lib/exploration.rb
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'writer'
|
2
|
+
require 'painter'
|
3
|
+
require 'config'
|
4
|
+
|
5
|
+
module ActiveExplorer
|
6
|
+
class Exploration
|
7
|
+
ASSOCIATION_FILTER_VALUES = [:has_many, :has_one, :belongs_to, :all]
|
8
|
+
|
9
|
+
# Creates new exploration and generates exploration hash.
|
10
|
+
#
|
11
|
+
# @param association_filter [Array]
|
12
|
+
# Values of array: `:has_many`, `:has_one`, `:belongs_to`, `:all`.
|
13
|
+
# When empty then it "follows previous association" (i.e. uses `:belongs_to` when previous assoc. was `:belongs_to` and
|
14
|
+
# uses `:has_xxx` when previous assoc. was `:has_xxx`). To always follow all associations you must specify
|
15
|
+
# all associations (e.g. uses `ActiveExplorer::Exploration::ASSOCIATION_FILTER_VALUES` as a value).
|
16
|
+
#
|
17
|
+
# @param class_filter [Array or Hash]
|
18
|
+
# If Array is used then it means to show only those classes in Array.
|
19
|
+
# When Hash is used then it can have these keys:
|
20
|
+
# - `:show` - Shows these classes, ignores at all other classes.
|
21
|
+
# - `:ignore` - Stops processing at these, does not show it and does not go to children. Processing goes back to parent.
|
22
|
+
# Use plural form (e.g. `books`).
|
23
|
+
#
|
24
|
+
# @param depth [Integer]
|
25
|
+
# How deep into the subobjects should the explorere go. Depth 1 is only direct children. Depth 0 returns no children.
|
26
|
+
#
|
27
|
+
def initialize(object, depth: 5, class_filter: nil, attribute_filter: nil, attribute_limit: nil, association_filter: nil, parent_object: nil)
|
28
|
+
raise TypeError, "Parameter 'class_filter' must be Array or Hash but is #{class_filter.class}." unless class_filter.nil? || class_filter.is_a?(Array) || class_filter.is_a?(Hash)
|
29
|
+
raise TypeError, "Parameter 'association_filter' must be Array but is #{association_filter.class}." unless association_filter.nil? || association_filter.is_a?(Array)
|
30
|
+
raise TypeError, "Parameter 'association_filter' must only contain values #{ASSOCIATION_FILTER_VALUES.to_s[1..-2]}." unless association_filter.nil? || association_filter.empty? || (association_filter & ASSOCIATION_FILTER_VALUES).any?
|
31
|
+
|
32
|
+
@object = object
|
33
|
+
@depth = depth
|
34
|
+
@parent_object = parent_object
|
35
|
+
|
36
|
+
@attribute_limit = attribute_limit || ActiveExplorer::Config.attribute_limit
|
37
|
+
@attribute_filter = attribute_filter || ActiveExplorer::Config.attribute_filter
|
38
|
+
|
39
|
+
@hash = { class_name: make_safe(@object.class.name),
|
40
|
+
attributes: attributes }
|
41
|
+
|
42
|
+
unless @depth.zero?
|
43
|
+
@class_filter = class_filter || ActiveExplorer::Config.class_filter
|
44
|
+
@class_filter = { show: @class_filter } if @class_filter.is_a?(Array)
|
45
|
+
|
46
|
+
[:show, :ignore].each do |group|
|
47
|
+
@class_filter[group] = @class_filter[group].present? ? each_val_to_s(@class_filter[group]) : []
|
48
|
+
end
|
49
|
+
|
50
|
+
@association_filter = association_filter || ActiveExplorer::Config.association_filter
|
51
|
+
@association_filter = ASSOCIATION_FILTER_VALUES if @association_filter.present? && @association_filter.include?(:all)
|
52
|
+
|
53
|
+
@associations = associtations(@object, @class_filter, @association_filter)
|
54
|
+
|
55
|
+
subobject_hash = subobjects_hash(@object, @associations)
|
56
|
+
@hash[:subobjects] = subobject_hash unless subobject_hash.empty?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def attributes
|
61
|
+
attrs = @object.attributes.symbolize_keys
|
62
|
+
attrs = attrs.first(@attribute_limit).to_h if @attribute_limit
|
63
|
+
|
64
|
+
return attrs if @attribute_filter.nil?
|
65
|
+
|
66
|
+
filter = @attribute_filter[@object.class.name.downcase.pluralize.to_sym]
|
67
|
+
|
68
|
+
if filter
|
69
|
+
attrs.select { |key| filter.include?(key) }
|
70
|
+
else
|
71
|
+
attrs
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_hash
|
76
|
+
@hash.deep_dup
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_console
|
80
|
+
Writer.new(self).write
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_image(file, origin_as_root: false)
|
84
|
+
Painter.new(self, file).paint(origin_as_root: origin_as_root)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def subobjects_hash(object, associations)
|
90
|
+
associations.each_with_object([]) do |association, results|
|
91
|
+
case association_type(association)
|
92
|
+
when :belongs_to
|
93
|
+
subobject = subobjects_from_association(object, association)
|
94
|
+
|
95
|
+
if subobject.present?
|
96
|
+
results.push subobject_hash(association, object, subobject) unless is_parent?(subobject)
|
97
|
+
end
|
98
|
+
|
99
|
+
when :has_many, :has_one
|
100
|
+
subobjects = subobjects_from_association(object, association)
|
101
|
+
|
102
|
+
if subobjects.present?
|
103
|
+
subobjects.each do |subobject|
|
104
|
+
results.push subobject_hash(association, object, subobject) unless is_parent?(subobject)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def subobject_hash(association, object, subobject)
|
112
|
+
association_type = association_type(association)
|
113
|
+
|
114
|
+
exploration = explore(subobject, parent_object: object, association_type: association_type)
|
115
|
+
|
116
|
+
hash = exploration.get_hash
|
117
|
+
hash[:association] = association_type
|
118
|
+
hash
|
119
|
+
end
|
120
|
+
|
121
|
+
def subobjects_from_association(object, association)
|
122
|
+
subobjects = object.send(association.name)
|
123
|
+
subobjects.present? ? subobjects : nil
|
124
|
+
|
125
|
+
rescue NameError, ActiveRecord::StatementInvalid, ActiveRecord::RecordNotFound => e
|
126
|
+
association_type = is_has_many_association?(association) ? 'has_many' : 'belongs_to'
|
127
|
+
add_error_hash("#{e.message} in #{association_type} :#{association.name}")
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def explore(object, parent_object:, association_type:)
|
132
|
+
association_filter = if !@association_filter.nil? && @association_filter.any?
|
133
|
+
@association_filter
|
134
|
+
elsif association_type == :belongs_to
|
135
|
+
[:belongs_to]
|
136
|
+
else
|
137
|
+
[:has_many, :has_one]
|
138
|
+
end
|
139
|
+
|
140
|
+
Exploration.new object,
|
141
|
+
depth: @depth - 1,
|
142
|
+
class_filter: @class_filter,
|
143
|
+
attribute_filter: @attribute_filter,
|
144
|
+
attribute_limit: @attribute_limit,
|
145
|
+
association_filter: association_filter,
|
146
|
+
parent_object: parent_object
|
147
|
+
end
|
148
|
+
|
149
|
+
def associtations(object, class_filter, association_filter)
|
150
|
+
associations = object.class.reflections.collect do |reflection|
|
151
|
+
reflection.second
|
152
|
+
end
|
153
|
+
|
154
|
+
if !association_filter.nil? && association_filter.any? && !association_filter.include?(:all)
|
155
|
+
associations.select! do |association|
|
156
|
+
association_filter.include? association_type(association)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
if class_filter
|
161
|
+
if class_filter[:show].any?
|
162
|
+
associations.select! do |association|
|
163
|
+
should_show?(association)
|
164
|
+
end
|
165
|
+
elsif class_filter[:ignore].any?
|
166
|
+
associations.reject! do |association|
|
167
|
+
should_ignore?(association)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
associations
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_error_hash(message)
|
176
|
+
@hash[:class_name] = make_safe(@object.class.name)
|
177
|
+
@hash[:attributes] = attributes
|
178
|
+
|
179
|
+
@hash[:error_message] = "Error in #{@object.class.name}(#{@object.id}): #{message}"
|
180
|
+
end
|
181
|
+
|
182
|
+
def association_type(association)
|
183
|
+
if association.is_a?(ActiveRecord::Reflection::HasManyReflection) ||
|
184
|
+
association.is_a?(ActiveRecord::Reflection::ThroughReflection) ||
|
185
|
+
association.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection)
|
186
|
+
:has_many
|
187
|
+
elsif association.is_a?(ActiveRecord::Reflection::HasOneReflection)
|
188
|
+
:has_one
|
189
|
+
elsif association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
190
|
+
:belongs_to
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def make_short(text)
|
195
|
+
text.length < 70 ? text : text[0..70] + " (...)"
|
196
|
+
end
|
197
|
+
|
198
|
+
# Replace characters that conflict with DOT language (used in GraphViz).
|
199
|
+
# These: `{`, `}`, `<`, `>`, `|`, `\`
|
200
|
+
#
|
201
|
+
def make_safe(text)
|
202
|
+
text.tr('{}<>|\\', '')
|
203
|
+
end
|
204
|
+
|
205
|
+
def each_val_to_s(array)
|
206
|
+
array.collect { |a| a.to_s }
|
207
|
+
end
|
208
|
+
|
209
|
+
def is_belongs_to_association?(association)
|
210
|
+
association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
211
|
+
end
|
212
|
+
|
213
|
+
def is_has_many_association?(association)
|
214
|
+
association.is_a?(ActiveRecord::Reflection::HasManyReflection)
|
215
|
+
end
|
216
|
+
|
217
|
+
def is_has_one_association?(association)
|
218
|
+
association.is_a?(ActiveRecord::Reflection::HasOneReflection)
|
219
|
+
end
|
220
|
+
|
221
|
+
def is_parent?(object)
|
222
|
+
object === @parent_object
|
223
|
+
end
|
224
|
+
|
225
|
+
def should_show?(association)
|
226
|
+
@class_filter[:show].include? association.plural_name.to_s
|
227
|
+
end
|
228
|
+
|
229
|
+
def should_ignore?(association)
|
230
|
+
@class_filter[:ignore].include? association.plural_name.to_s
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
data/lib/painter.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
module ActiveExplorer
|
2
|
+
class Painter
|
3
|
+
def initialize(exploration, file_path)
|
4
|
+
@exploration = exploration
|
5
|
+
@file_path = file_path
|
6
|
+
@graph = GraphViz.new(:G, :type => :digraph)
|
7
|
+
end
|
8
|
+
|
9
|
+
def paint(origin_as_root: false)
|
10
|
+
@centralized = origin_as_root
|
11
|
+
paint_object @exploration.get_hash, @graph, nil
|
12
|
+
save_to_file
|
13
|
+
@graph
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def paint_object(hash, graph, parent_node)
|
19
|
+
style = parent_node.nil? ? :origin : nil
|
20
|
+
|
21
|
+
node = add_node(hash, graph, style: style)
|
22
|
+
add_edge(graph, parent_node, node, hash[:association]) unless parent_node.nil?
|
23
|
+
|
24
|
+
paint_subobjects graph, node, hash[:subobjects] unless hash[:subobjects].nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def paint_subobjects(graph, parent_node, subhashes)
|
28
|
+
subhashes.each do |hash|
|
29
|
+
paint_object hash, graph, parent_node
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_node(hash, graph, style: nil)
|
34
|
+
id = hash[:attributes][:id]
|
35
|
+
class_name = make_safe(hash[:class_name])
|
36
|
+
attributes = make_safe(hash[:attributes].keys.join("\n"))
|
37
|
+
values = hash[:attributes].values.collect do |val|
|
38
|
+
if val.nil?
|
39
|
+
'nil'
|
40
|
+
elsif val.is_a? String
|
41
|
+
"\"#{make_short(val)}\""
|
42
|
+
else
|
43
|
+
make_short(val.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
values = make_safe(values.join("\n"))
|
47
|
+
|
48
|
+
if style == :origin
|
49
|
+
graph.add_node("#{class_name}_#{id}", shape: "record", label: "{#{class_name}|{#{attributes}|#{values}}}", labelloc: 't', style: 'filled', fillcolor: 'yellow')
|
50
|
+
else
|
51
|
+
graph.add_node("#{class_name}_#{id}", shape: "record", label: "{#{class_name}|{#{attributes}|#{values}}}", labelloc: 't')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_edge(graph, parent_node, node, association)
|
56
|
+
if @centralized
|
57
|
+
graph.add_edge(parent_node, node, label: association == :belongs_to ? ' belongs to' : ' has') unless edge_exists?(graph, parent_node, node)
|
58
|
+
else
|
59
|
+
if association == :belongs_to
|
60
|
+
graph.add_edge(node, parent_node) unless edge_exists?(graph, node, parent_node)
|
61
|
+
else
|
62
|
+
graph.add_edge(parent_node, node) unless edge_exists?(graph, parent_node, node)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def edge_exists?(graph, node_one, node_two)
|
68
|
+
graph.each_edge do |edge|
|
69
|
+
return true if edge.node_one == node_one.id && edge.node_two == node_two.id
|
70
|
+
end
|
71
|
+
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
def save_to_file
|
76
|
+
filename = @file_path.split(File::SEPARATOR).last
|
77
|
+
directory = @file_path.chomp filename
|
78
|
+
|
79
|
+
create_directory directory unless directory.empty?
|
80
|
+
|
81
|
+
@graph.output(:png => @file_path)
|
82
|
+
end
|
83
|
+
|
84
|
+
def create_directory(directory)
|
85
|
+
unless directory.empty? || File.directory?(directory)
|
86
|
+
FileUtils.mkdir_p directory
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def make_short(text)
|
91
|
+
text.length < 70 ? text : text[0..70] + " (...)"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Replace characters that conflict with DOT language (used in GraphViz).
|
95
|
+
# These: `{`, `}`, `<`, `>`, `|`, `\`
|
96
|
+
#
|
97
|
+
def make_safe(text)
|
98
|
+
text.tr('{}<>|\\', '')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/writer.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module ActiveExplorer
|
2
|
+
class Writer
|
3
|
+
def initialize(exploration)
|
4
|
+
@exploration = exploration
|
5
|
+
end
|
6
|
+
|
7
|
+
def write
|
8
|
+
exploration_hash = @exploration.get_hash
|
9
|
+
|
10
|
+
puts "\nExplored #{exploration_hash[:class_name]}(#{exploration_hash[:attributes][:id]}):\n\n"
|
11
|
+
write_object(exploration_hash)
|
12
|
+
puts "\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def write_object(object, level = 0)
|
18
|
+
class_name = object[:class_name]
|
19
|
+
id = object[:attributes][:id]
|
20
|
+
attributes = object[:attributes]
|
21
|
+
error_message = object[:error_message]
|
22
|
+
|
23
|
+
attributes.delete :id
|
24
|
+
|
25
|
+
margin = ' ' * level
|
26
|
+
|
27
|
+
if level > 0
|
28
|
+
margin[-2] = '->'
|
29
|
+
margin += object[:association] == :belongs_to ? 'belongs to ' : 'has '
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "#{margin}#{class_name}(#{id}) #{attributes}"
|
33
|
+
|
34
|
+
if error_message.present?
|
35
|
+
margin = ' ' * level
|
36
|
+
puts "#{margin}(#{error_message})" if error_message.present?
|
37
|
+
end
|
38
|
+
|
39
|
+
write_objects object[:subobjects], level + 1 unless object[:subobjects].nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_objects(objects, level)
|
43
|
+
objects.each do |object|
|
44
|
+
write_object object, level
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_explorer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marek Ulicny
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-graphviz
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-nc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: ruby-graphviz
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.2'
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: 1.2.2
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - "~>"
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '1.2'
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 1.2.2
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: mysql
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: standalone_migrations
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: awesome_print
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
type: :development
|
181
|
+
prerelease: false
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: factory_girl
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '0'
|
194
|
+
type: :development
|
195
|
+
prerelease: false
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
- !ruby/object:Gem::Dependency
|
202
|
+
name: appraisal
|
203
|
+
requirement: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - ">="
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '0'
|
208
|
+
type: :development
|
209
|
+
prerelease: false
|
210
|
+
version_requirements: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
description: Visualization of data and associations represented by Active Record.
|
216
|
+
email:
|
217
|
+
- xulicny@gmail.com
|
218
|
+
executables:
|
219
|
+
- console
|
220
|
+
- setup
|
221
|
+
extensions: []
|
222
|
+
extra_rdoc_files: []
|
223
|
+
files:
|
224
|
+
- ".gitignore"
|
225
|
+
- ".rspec"
|
226
|
+
- ".ruby-gemset"
|
227
|
+
- ".ruby-version"
|
228
|
+
- ".standalone_migrations"
|
229
|
+
- ".travis.yml"
|
230
|
+
- Appraisals
|
231
|
+
- CODE_OF_CONDUCT.md
|
232
|
+
- Gemfile
|
233
|
+
- Guardfile
|
234
|
+
- LICENSE.txt
|
235
|
+
- README.md
|
236
|
+
- Rakefile
|
237
|
+
- active_explorer.gemspec
|
238
|
+
- bin/console
|
239
|
+
- bin/setup
|
240
|
+
- gemfiles/activerecord_3_0.gemfile
|
241
|
+
- gemfiles/activerecord_3_0.gemfile.lock
|
242
|
+
- gemfiles/activerecord_3_1.gemfile
|
243
|
+
- gemfiles/activerecord_3_1.gemfile.lock
|
244
|
+
- gemfiles/activerecord_3_2.gemfile
|
245
|
+
- gemfiles/activerecord_3_2.gemfile.lock
|
246
|
+
- gemfiles/activerecord_4_0.gemfile
|
247
|
+
- gemfiles/activerecord_4_0.gemfile.lock
|
248
|
+
- gemfiles/activerecord_4_1.gemfile
|
249
|
+
- gemfiles/activerecord_4_1.gemfile.lock
|
250
|
+
- gemfiles/activerecord_4_2.gemfile
|
251
|
+
- gemfiles/activerecord_4_2.gemfile.lock
|
252
|
+
- gemfiles/activerecord_5_0.gemfile
|
253
|
+
- gemfiles/activerecord_5_0.gemfile.lock
|
254
|
+
- lib/active_explorer.rb
|
255
|
+
- lib/active_explorer/version.rb
|
256
|
+
- lib/config.rb
|
257
|
+
- lib/exploration.rb
|
258
|
+
- lib/painter.rb
|
259
|
+
- lib/writer.rb
|
260
|
+
homepage: https://github.com/rascasone/active_explorer
|
261
|
+
licenses:
|
262
|
+
- MIT
|
263
|
+
metadata: {}
|
264
|
+
post_install_message:
|
265
|
+
rdoc_options: []
|
266
|
+
require_paths:
|
267
|
+
- lib
|
268
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - ">="
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: '0'
|
273
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
274
|
+
requirements:
|
275
|
+
- - ">="
|
276
|
+
- !ruby/object:Gem::Version
|
277
|
+
version: '0'
|
278
|
+
requirements: []
|
279
|
+
rubyforge_project:
|
280
|
+
rubygems_version: 2.5.1
|
281
|
+
signing_key:
|
282
|
+
specification_version: 4
|
283
|
+
summary: Visualization of data and associations represented by Active Record.
|
284
|
+
test_files: []
|