snapbot 0.2.2 → 0.4.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: 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