snapbot 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +2 -0
- data/Rakefile +3 -1
- data/Steepfile +43 -0
- data/lib/snapbot/diagram/dot_generator.rb +0 -1
- data/lib/snapbot/{diagram/dot_generator → reflector}/relationship.rb +0 -0
- data/lib/snapbot/reflector.rb +2 -1
- data/lib/snapbot/version.rb +1 -1
- data/lib/tasks/steep.rake +8 -0
- data/sig/lib/snapbot/diagram/dot_generator.rbs +25 -0
- data/sig/lib/snapbot/diagram/renderer.rbs +19 -0
- data/sig/lib/snapbot/diagram.rbs +9 -0
- data/sig/lib/snapbot/reflector/relationship.rbs +14 -0
- data/sig/lib/snapbot/reflector.rbs +38 -0
- data/sig/lib/snapbot/rspec/lets.rbs +25 -0
- data/snapbot.gemspec +2 -0
- metadata +38 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f8b1c94c13ad202a7a33eb020d8aa4c6fc66b3123a08f0f210c13a2b91598c3
|
4
|
+
data.tar.gz: 54ade2525a1d3f0497c4148610488b350bacc2c2860ed7e6969d5fb237cce0f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b4b99a9dd2bf1dea4174ff924eed781818f29707a89b94d3952830ecd59368fbb2632d90c3633414aa175ac03741dcfaa322698160f8e2484d1b1884cdbad5d
|
7
|
+
data.tar.gz: cd76dec5c1fd06383679a1d35b06cd8cd59d17e8c9a676395efbe30065c79b1baa99cad653f6589557243a1ace625050b470b7133843d41663fdc210dfd02fc0
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Snapbot
|
2
2
|
|
3
|
+
![example workflow](https://github.com/rgarner/snapbot/actions/workflows/main.yml/badge.svg)
|
4
|
+
|
3
5
|
Snapbot generates little diagrams via `save_and_open_diagram` for you to visualise the small constellations of
|
4
6
|
ActiveRecord objects that you find in feature and integration tests. These are most often made by
|
5
7
|
[FactoryBot](https://github.com/thoughtbot/factory_bot) or some other fixture-handling method, but this gem has no
|
data/Rakefile
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
|
6
|
+
Dir["lib/tasks/*.rake"].each { |file| import file }
|
7
|
+
|
6
8
|
RSpec::Core::RakeTask.new(:spec)
|
7
9
|
|
8
10
|
require "rubocop/rake_task"
|
9
11
|
|
10
12
|
RuboCop::RakeTask.new
|
11
13
|
|
12
|
-
task default: %i[spec rubocop]
|
14
|
+
task default: %i[spec rubocop steep:check]
|
data/Steepfile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
D = Steep::Diagnostic
|
2
|
+
|
3
|
+
target :lib do
|
4
|
+
signature "sig"
|
5
|
+
|
6
|
+
check "lib" # Directory name
|
7
|
+
# check "Gemfile" # File name
|
8
|
+
# check "app/models/**/*.rb" # Glob
|
9
|
+
# ignore "lib/templates/*.rb"
|
10
|
+
|
11
|
+
library "set"
|
12
|
+
# library "rspec"
|
13
|
+
# library "strong_json" # Gems
|
14
|
+
|
15
|
+
# configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
16
|
+
configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
17
|
+
configure_code_diagnostics do |hash| # You can setup everything yourself
|
18
|
+
# lib/snapbot/reflector.rb:73:35: [error] Unsupported block params pattern, probably masgn?
|
19
|
+
# │ Diagnostic ID: Ruby::UnsupportedSyntax
|
20
|
+
# │
|
21
|
+
# └ hash.each_with_object([]) do |(key, value), array|
|
22
|
+
# ~~~~~~~~~~~~~~~~~~~~~
|
23
|
+
# This disables that ^^
|
24
|
+
hash[D::Ruby::UnsupportedSyntax] = :information
|
25
|
+
|
26
|
+
# lib/snapbot/diagram/renderer.rb:21:58: [error] The method cannot be called with a block
|
27
|
+
# │ Diagnostic ID: Ruby::UnexpectedBlockGiven
|
28
|
+
# │
|
29
|
+
# └ IO.popen("dot -Tsvg -o #{OUTPUT_FILENAME}", "w+") do |pipe|
|
30
|
+
# ~~~~~~~~~
|
31
|
+
#
|
32
|
+
# This disables that ^^ but probably a bit too much. Can we restrict to renderer.rb?
|
33
|
+
hash[D::Ruby::UnexpectedBlockGiven] = :information
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# target :test do
|
38
|
+
# signature "sig", "sig-private"
|
39
|
+
#
|
40
|
+
# check "test"
|
41
|
+
#
|
42
|
+
# # library "pathname", "set" # Standard libraries
|
43
|
+
# end
|
File without changes
|
data/lib/snapbot/reflector.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_record"
|
4
|
+
require "snapbot/reflector/relationship"
|
4
5
|
|
5
6
|
module Snapbot
|
6
7
|
# Reflect models and instances in a way that's useful for generating a diagram
|
@@ -25,7 +26,7 @@ module Snapbot
|
|
25
26
|
/^ActiveRecord::SchemaMigration$/
|
26
27
|
].freeze
|
27
28
|
def activerecord_ignore?(klass)
|
28
|
-
ACTIVERECORD_IGNORE.any? { |r| klass.name =~ r }
|
29
|
+
ACTIVERECORD_IGNORE.any? { |r| klass.name =~ r } || klass.abstract_class
|
29
30
|
end
|
30
31
|
|
31
32
|
def instances
|
data/lib/snapbot/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Snapbot
|
2
|
+
module Diagram
|
3
|
+
# Get a visual handle on what small constellations of objects we're creating
|
4
|
+
# in specs
|
5
|
+
class DotGenerator
|
6
|
+
def initialize: (?label: ::String, ?attrs: bool, ?ignore_lets: Array[Symbol]) -> void
|
7
|
+
def dot: () -> ::String
|
8
|
+
|
9
|
+
@label: String
|
10
|
+
@attrs: bool
|
11
|
+
@ignore_lets: Array[Symbol]
|
12
|
+
|
13
|
+
@options: Hash[Object, Object]
|
14
|
+
@lets_by_value: Hash[Object, Symbol]
|
15
|
+
@reflector: Reflector
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def reflector: () -> Reflector
|
20
|
+
def collect_lets: (::RSpec::Core::ExampleGroup example) -> untyped
|
21
|
+
def instance_name: (ActiveRecord::Base `instance`) -> ::String
|
22
|
+
def template: () -> ::String
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Snapbot
|
2
|
+
module Diagram
|
3
|
+
# Render some DOT via Graphviz dot command line
|
4
|
+
class Renderer
|
5
|
+
INSTALL_GRAPHVIZ_URL: "https://graphviz.org/download/#executable-packages"
|
6
|
+
OUTPUT_FILENAME: "tmp/models.svg"
|
7
|
+
|
8
|
+
@dot: String
|
9
|
+
|
10
|
+
def initialize: (String dot) -> void
|
11
|
+
def save: () -> String
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def graphviz_executable: () -> ::String
|
16
|
+
def ensure_graphviz: () -> void
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Snapbot
|
2
|
+
# Print the small constellation of objects in your integration test and how they relate.
|
3
|
+
# Requires Graphviz. Optimised for Mac. YMMV.
|
4
|
+
module Diagram
|
5
|
+
def save_and_open_diagram: (**untyped args) -> (nil | untyped)
|
6
|
+
|
7
|
+
def open_command: () -> untyped
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Snapbot
|
2
|
+
class Reflector
|
3
|
+
# A source/destination-based relationship
|
4
|
+
class Relationship
|
5
|
+
attr_accessor source: ::String
|
6
|
+
|
7
|
+
attr_accessor destination: ::String
|
8
|
+
|
9
|
+
def initialize: (::String source, ::String destination) -> void
|
10
|
+
|
11
|
+
def ==: (Relationship other) -> bool
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
end
|
4
|
+
|
5
|
+
module Reflection
|
6
|
+
class AssociationReflection
|
7
|
+
def name: () -> Symbol
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Snapbot
|
13
|
+
# Reflect models and instances in a way that's useful for generating a diagram
|
14
|
+
class Reflector
|
15
|
+
ACTIVERECORD_IGNORE: ::Array[::Regexp]
|
16
|
+
|
17
|
+
@models: Array[Class]
|
18
|
+
@instances: Array[ActiveRecord::Base]
|
19
|
+
@relationships: Set[Relationship]
|
20
|
+
|
21
|
+
def base_activerecord_class: () -> Class
|
22
|
+
def models: (?only_with_records: bool) -> Array[Class]
|
23
|
+
def activerecord_ignore?: (Class klass) -> bool
|
24
|
+
def instances: () -> Array[ActiveRecord::Base]
|
25
|
+
|
26
|
+
# A Set of relationships to other identified entities
|
27
|
+
def relationships: () -> Set[Relationship]
|
28
|
+
def add_relationships: (ActiveRecord::Base `instance`, Set[Relationship] set) -> untyped
|
29
|
+
def reflect_associations: (ActiveRecord::Base `instance`) -> Array[ActiveRecord::Reflection::AssociationReflection]
|
30
|
+
def attributes: (ActiveRecord::Base `instance`) -> Hash[Symbol, Object]
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def instance_name: (ActiveRecord::Base `instance`) -> ::String
|
35
|
+
# Remains commented out, as is private, and https://github.com/ruby/rbs/issues/734#issuecomment-1192607498
|
36
|
+
# def escape_hash: (Hash[Symbol, Object] hash) -> untyped
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
class ExampleGroup
|
4
|
+
end
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module Snapbot
|
9
|
+
module RSpec
|
10
|
+
# Collect RSpec `let`s for a given example and all her parents
|
11
|
+
class Lets
|
12
|
+
@lets: Array[Symbol]
|
13
|
+
@lets_by_value: Hash[Object, Symbol]
|
14
|
+
@example: ::RSpec::Core::ExampleGroup
|
15
|
+
|
16
|
+
def initialize: (::RSpec::Core::ExampleGroup example) -> void
|
17
|
+
|
18
|
+
def collect: () -> Array[Symbol]
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _collect: (::RSpec::Core::ExampleGroup klass, Array[Symbol] lets) -> Array[Symbol]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/snapbot.gemspec
CHANGED
@@ -35,7 +35,9 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_runtime_dependency "activerecord", version_string
|
36
36
|
spec.add_runtime_dependency "activesupport", version_string
|
37
37
|
|
38
|
+
spec.add_development_dependency "rbs"
|
38
39
|
spec.add_development_dependency "sqlite3"
|
40
|
+
spec.add_development_dependency "steep"
|
39
41
|
|
40
42
|
# For more information and examples about making a new gem, check out our
|
41
43
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snapbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Russell Garner
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '6.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rbs
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: sqlite3
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: steep
|
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'
|
83
111
|
description:
|
84
112
|
email:
|
85
113
|
- rgarner@zephyros-systems.co.uk
|
@@ -95,14 +123,22 @@ files:
|
|
95
123
|
- LICENSE.txt
|
96
124
|
- README.md
|
97
125
|
- Rakefile
|
126
|
+
- Steepfile
|
98
127
|
- lib/snapbot.rb
|
99
128
|
- lib/snapbot/diagram.rb
|
100
129
|
- lib/snapbot/diagram/dot_generator.rb
|
101
|
-
- lib/snapbot/diagram/dot_generator/relationship.rb
|
102
130
|
- lib/snapbot/diagram/renderer.rb
|
103
131
|
- lib/snapbot/reflector.rb
|
132
|
+
- lib/snapbot/reflector/relationship.rb
|
104
133
|
- lib/snapbot/rspec/lets.rb
|
105
134
|
- lib/snapbot/version.rb
|
135
|
+
- lib/tasks/steep.rake
|
136
|
+
- sig/lib/snapbot/diagram.rbs
|
137
|
+
- sig/lib/snapbot/diagram/dot_generator.rbs
|
138
|
+
- sig/lib/snapbot/diagram/renderer.rbs
|
139
|
+
- sig/lib/snapbot/reflector.rbs
|
140
|
+
- sig/lib/snapbot/reflector/relationship.rbs
|
141
|
+
- sig/lib/snapbot/rspec/lets.rbs
|
106
142
|
- sig/snapbot.rbs
|
107
143
|
- snapbot.gemspec
|
108
144
|
homepage: https://github.com/rgarner/snapbot
|