snapbot 0.2.2 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bd122996f917b0e18388a91aaeba183028d54a6b5e2fc58c05559f3a5103b6a
4
- data.tar.gz: 15ce511a21b7d1dd96553a45959dce0e9ebfb9ad9ba2624d369af615742ec80b
3
+ metadata.gz: 3ccc2f9565d40b7b3dd10ffd1f92054e7b718eb28613cdc9336531f35a916204
4
+ data.tar.gz: 661b49c7b72f6a55736a88fcdafc74e249d6d59c8fcbd115b0fcf6c89442ee51
5
5
  SHA512:
6
- metadata.gz: 34c2e342537c4085fcef8e9ae08e2cde45d8b200e8f7d4e3f369f745ce41ddae3ac5b36a8735c7d568c37427038107e061b9525372f8cc6c9be21ab2d4ad6f20
7
- data.tar.gz: 4fbe87ef32e963c62eb44fe5f54e26901f7dd33e0c1ca048d962a066a0bb9de2abb5516ccc24b20c84fe8e1f86c435b27c04d2bb85b2ddf30b06efd367d30dba
6
+ metadata.gz: d19d016d55b593f14106933bb66926d5d9b18b1b986deabfd644ab7f5c27dddb33cfe1ed6ef50952aea72d833eda570937ae6dac1be41d7519c06f403cba64d2
7
+ data.tar.gz: 22416a76acec3531aa6487de788068c919e69023d9569237daa7990f3db088fe853a3c0a2594632b0edab29a9ea6013921a5379c24878bc6fd8f3d3e89cf04c1
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in snapbot.gemspec
6
6
  gemspec
7
7
 
8
+ gem "launchy", "~> 2.5.0"
9
+
8
10
  gem "rake", "~> 13.0"
9
11
 
10
12
  gem "rspec", "~> 3.0"
data/README.md CHANGED
@@ -20,13 +20,19 @@ Install this first, then add the gem to your project's `:test` group in the gemf
20
20
  end
21
21
  ```
22
22
 
23
- Add to your tests:
23
+ `include Snapbot::Diagram` in your tests.
24
24
 
25
+ For RSpec, you may prefer to put something like
26
+
27
+ ```ruby
28
+ RSpec.config do |config|
29
+ config.include Snapbot::Diagram, type: :feature
30
+ end
25
31
  ```
26
- include Snapbot::Diagram
27
- ```
28
32
 
29
- Use:
33
+ in your `spec/rails_helper` to have it mixed in automatically (to features, in this case).
34
+
35
+ ## Usage example
30
36
 
31
37
  ```
32
38
  blog = Blog.create(title: 'My blog')
data/Steepfile CHANGED
@@ -26,7 +26,7 @@ target :lib do
26
26
  # lib/snapbot/diagram/renderer.rb:21:58: [error] The method cannot be called with a block
27
27
  # │ Diagnostic ID: Ruby::UnexpectedBlockGiven
28
28
  # │
29
- # └ IO.popen("dot -Tsvg -o #{OUTPUT_FILENAME}", "w+") do |pipe|
29
+ # └ IO.popen("dot -Tsvg -o #{DEFAULT_OUTPUT_FILENAME}", "w+") do |pipe|
30
30
  # ~~~~~~~~~
31
31
  #
32
32
  # This disables that ^^ but probably a bit too much. Can we restrict to renderer.rb?
@@ -1,29 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
4
-
5
3
  module Snapbot
6
4
  module Diagram
7
5
  # Render some DOT via Graphviz dot command line
8
6
  class Renderer
9
7
  INSTALL_GRAPHVIZ_URL = "https://graphviz.org/download/#executable-packages"
10
- OUTPUT_FILENAME = "tmp/models.svg"
8
+ DEFAULT_OUTPUT_FILENAME = "tmp/models.svg"
11
9
 
12
10
  def initialize(dot)
13
11
  @dot = dot
14
12
  end
15
13
 
16
- def save
14
+ def save(path = DEFAULT_OUTPUT_FILENAME)
17
15
  ensure_graphviz
18
- FileUtils.rm(OUTPUT_FILENAME, force: true)
19
- FileUtils.mkdir_p(File.dirname(OUTPUT_FILENAME))
16
+ FileUtils.rm(path, force: true)
17
+ FileUtils.mkdir_p(File.dirname(path))
20
18
 
21
- IO.popen("dot -Tsvg -o #{OUTPUT_FILENAME}", "w") do |pipe|
19
+ IO.popen("dot -Tsvg -o #{path}", "w") do |pipe|
22
20
  pipe.puts(@dot)
23
21
  end
24
22
 
25
- warn "Written to #{OUTPUT_FILENAME}"
26
- OUTPUT_FILENAME
23
+ warn "Written to #{path}"
24
+ path
27
25
  end
28
26
 
29
27
  private
@@ -2,28 +2,33 @@
2
2
 
3
3
  require "snapbot/diagram/dot_generator"
4
4
  require "snapbot/diagram/renderer"
5
- require "open3"
6
5
 
7
6
  module Snapbot
8
7
  # Print the small constellation of objects in your integration test and how they relate.
9
8
  # Requires Graphviz. Optimised for Mac. YMMV.
10
9
  module Diagram
11
- def save_and_open_diagram(**args)
12
- args.reverse_merge!(rspec: !!defined?(RSpec))
13
- dot = DotGenerator.new(**args).dot
14
- filename = Renderer.new(dot).save
10
+ def save_and_open_diagram(path = Renderer::DEFAULT_OUTPUT_FILENAME, **args)
11
+ filename = save_diagram(path, **args)
15
12
 
16
- unless open_command.present?
17
- warn "No `open` command available. File saved to #{filename}"
13
+ unless launchy_present?
14
+ warn "Cannot open diagram install `launchy`."
18
15
  return
19
16
  end
20
17
 
21
- _stdout, stderr, status = Open3.capture3("#{open_command} #{filename}")
22
- raise stderr unless status.exitstatus.zero?
18
+ Launchy.open(filename)
19
+ end
20
+
21
+ def save_diagram(path = Renderer::DEFAULT_OUTPUT_FILENAME, **args)
22
+ args.reverse_merge!(rspec: !!defined?(RSpec))
23
+ dot = DotGenerator.new(**args).dot
24
+ Renderer.new(dot).save(path)
23
25
  end
24
26
 
25
- def open_command
26
- `which open`.chomp
27
+ def launchy_present?
28
+ require "launchy"
29
+ true
30
+ rescue LoadError
31
+ false
27
32
  end
28
33
  end
29
34
  end
@@ -44,6 +44,8 @@ module Snapbot
44
44
 
45
45
  def add_relationships(instance, set)
46
46
  reflect_associations(instance).each do |association|
47
+ next unless valid_association?(association) # Skip POROs
48
+
47
49
  records = Array(instance.send(association.name)).compact
48
50
  records.each do |record|
49
51
  set.add(Relationship.new(instance_name(instance), instance_name(record)))
@@ -65,6 +67,18 @@ module Snapbot
65
67
 
66
68
  private
67
69
 
70
+ # rubocop:disable Style/RescueModifier
71
+ def valid_association?(association)
72
+ # AR7.x raises an ArgumentError when the class is a PORO. AR6.x would fall over
73
+ # later with NoMethodError on `relation_delegate_class`. Either way, we're not
74
+ # valid if the association.klass is not descended from our `base_activerecord_class`
75
+ return true if (association.klass rescue ArgumentError) < base_activerecord_class
76
+
77
+ warn "#{association.active_record} -> :#{association.name} is not a valid association. " \
78
+ "Make sure it inherits from #{base_activerecord_class}"
79
+ end
80
+ # rubocop:enable Style/RescueModifier
81
+
68
82
  def instance_name(instance)
69
83
  "#{instance.model_name}##{instance.id}"
70
84
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snapbot
4
- VERSION = "0.2.2"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -2,18 +2,19 @@ module Snapbot
2
2
  module Diagram
3
3
  # Render some DOT via Graphviz dot command line
4
4
  class Renderer
5
- INSTALL_GRAPHVIZ_URL: "https://graphviz.org/download/#executable-packages"
6
- OUTPUT_FILENAME: "tmp/models.svg"
5
+ INSTALL_GRAPHVIZ_URL: String
6
+ DEFAULT_OUTPUT_FILENAME: String
7
7
 
8
8
  @dot: String
9
9
 
10
10
  def initialize: (String dot) -> void
11
- def save: () -> String
11
+ def save: (?String path) -> String
12
12
 
13
13
  private
14
14
 
15
15
  def graphviz_executable: () -> ::String
16
16
  def ensure_graphviz: () -> void
17
+ def launchy_present?: () -> bool
17
18
  end
18
19
  end
19
20
  end
@@ -2,7 +2,8 @@ module Snapbot
2
2
  # Print the small constellation of objects in your integration test and how they relate.
3
3
  # Requires Graphviz. Optimised for Mac. YMMV.
4
4
  module Diagram
5
- def save_and_open_diagram: (**untyped args) -> (nil | untyped)
5
+ def save_diagram: (?String path, **untyped args) -> (nil | untyped)
6
+ def save_and_open_diagram: (?String path, **untyped args) -> (nil | untyped)
6
7
 
7
8
  def open_command: () -> untyped
8
9
  end
data/snapbot.gemspec CHANGED
@@ -35,6 +35,7 @@ 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 "launchy"
38
39
  spec.add_development_dependency "rbs"
39
40
  spec.add_development_dependency "sqlite3"
40
41
  spec.add_development_dependency "steep"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Russell Garner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-10 00:00:00.000000000 Z
11
+ date: 2022-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -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: launchy
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: rbs
71
85
  requirement: !ruby/object:Gem::Requirement