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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb7768e6e3ac46cacf84d569a0d8026062418160d39c5ae1e214875ac0f4b26d
4
- data.tar.gz: 50467bc231c453c7c81129181f90c21759f5acb2f121fbaf07bfd5313dcaea80
3
+ metadata.gz: 7f8b1c94c13ad202a7a33eb020d8aa4c6fc66b3123a08f0f210c13a2b91598c3
4
+ data.tar.gz: 54ade2525a1d3f0497c4148610488b350bacc2c2860ed7e6969d5fb237cce0f9
5
5
  SHA512:
6
- metadata.gz: 0331b6031f3fe4e3ee09aef66a1030bfec968f5df8c7308c2dd09933e0c63cfad55e54dab10e7bf0e9dc568216d34bbd3f8ac32c5bd6e524750ad676fbb49988
7
- data.tar.gz: 06757de1f42e455f6b8565661426bba4a94e609d567a5d2a2c6d8cdb8be8e5aed4b16e97334a009d34bda3b400707b2796a9a4b88b507a407b58e1ca8df2a798
6
+ metadata.gz: 7b4b99a9dd2bf1dea4174ff924eed781818f29707a89b94d3952830ecd59368fbb2632d90c3633414aa175ac03741dcfaa322698160f8e2484d1b1884cdbad5d
7
+ data.tar.gz: cd76dec5c1fd06383679a1d35b06cd8cd59d17e8c9a676395efbe30065c79b1baa99cad653f6589557243a1ace625050b470b7133843d41663fdc210dfd02fc0
data/.rubocop.yml CHANGED
@@ -1,6 +1,9 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.6
3
3
  SuggestExtensions: false
4
+ Exclude:
5
+ - Steepfile
6
+
4
7
 
5
8
  Metrics/AbcSize:
6
9
  Exclude:
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
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "snapbot/reflector"
4
- require "snapbot/diagram/dot_generator/relationship"
5
4
 
6
5
  if defined?(::RSpec)
7
6
  require "snapbot/rspec/lets"
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snapbot
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :steep do
4
+ desc "Run `steep check`"
5
+ task :check do
6
+ system("steep check", exception: true)
7
+ end
8
+ end
@@ -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.0
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