pry-byetypo 1.1.0 → 1.3.0

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: ffd46e3838ed0c8d43e5aa5c3fc5a38c518d90a4dbefcbba09f1629fffe72260
4
- data.tar.gz: cef94f7e070bc541cedc9f2a547a9dc2901b8bf2ca96b4cfda09f5ffef890381
3
+ metadata.gz: da8cec30c93c393374f141f18ce63052a9019f7cdeb07ef812b82a66cb050a34
4
+ data.tar.gz: 7310aa51a6dbfb284b970049317e11036fd2dcc2449f33565e879c8604e4ca5d
5
5
  SHA512:
6
- metadata.gz: 61e7d2eb327d7a3905eb882288260484d42497bfe895a98a72bbccf562d9905ede28becb9b9c2da9e71c537967f8621299d364b97f442869d98f551a4b5073a4
7
- data.tar.gz: 86252b1586e787a3f3e3ac6a66c13034640eba983a2d0d8a8be95f239906fef4611f9c00fcf17c675030b03ab512605dc1e87436ef9eaea7d261675a2cc03845
6
+ metadata.gz: d7c23c25abd958cd72a5298c9b4c1c02a4cae85e2147a7d0051ee4e58392c298a7a5a852fa89ba43fcb260d7843210529cbb7dcee3e82290afd425faec4deabb
7
+ data.tar.gz: cb4b3db82a3f9414eebd451d88c3383044207799e4cedeaaf47b621d62f3f72569b3e1a39e9afc26694ba1e01fab50dd4680f2768d4d4a2831612de60de7733b
data/Gemfile.lock CHANGED
@@ -1,10 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pry-byetypo (1.1.0)
4
+ pry-byetypo (1.3.0)
5
5
  colorize (~> 1.1.0)
6
6
  pry (>= 0.13, < 0.15)
7
- rails (~> 7.0)
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
@@ -146,7 +145,7 @@ GEM
146
145
  psych (5.1.2)
147
146
  stringio
148
147
  racc (1.7.3)
149
- rack (3.0.8)
148
+ rack (3.0.9)
150
149
  rack-session (2.0.0)
151
150
  rack (>= 3.0.0)
152
151
  rack-test (2.1.0)
@@ -248,11 +247,13 @@ GEM
248
247
 
249
248
  PLATFORMS
250
249
  arm64-darwin-22
250
+ arm64-darwin-23
251
251
  x86_64-linux
252
252
 
253
253
  DEPENDENCIES
254
254
  byebug
255
255
  pry-byetypo!
256
+ rails (~> 7.0)
256
257
  rake (~> 13.0)
257
258
  rspec (~> 3.0)
258
259
  standard (~> 1.3)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PRY-BYETYPO
1
+ # PRY-BYETYPO 👋
2
2
 
3
3
  Autocorrects typos in your Pry console.
4
4
 
@@ -26,7 +26,7 @@ I, [2024-01-31T17:11:16.344503 #3739] INFO -- : Running: result
26
26
  ```
27
27
 
28
28
  > [!NOTE]
29
- > So far, this plugin is not framework agnostic, and it requires Rails 7 or later.
29
+ > Currently, this plugin is not truly ORM-agnostic; to fully benefit from it, ActiveRecord is required.
30
30
 
31
31
  ## Installation
32
32
 
@@ -7,10 +7,6 @@ module Exceptions
7
7
  class Base < ExceptionsBase
8
8
  private
9
9
 
10
- def corrected_word
11
- @corrected_word ||= spell_checker(associations_dictionary).correct(unknown_from_exception).first
12
- end
13
-
14
10
  def corrected_cmd
15
11
  @corrected_cmd ||= last_cmd.gsub(/\b#{unknown_from_exception}\b/, corrected_word)
16
12
  end
@@ -19,8 +15,8 @@ module Exceptions
19
15
  exception.to_s.match(exception_regexp)[1]
20
16
  end
21
17
 
22
- def associations_dictionary
23
- @associations_dictionary ||= store.transaction { |s| s["associations"] }
18
+ def dictionary
19
+ store.transaction { |s| s["associations"] }
24
20
  end
25
21
  end
26
22
  end
@@ -1,25 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../exceptions_base"
3
+ require_relative "base"
4
4
 
5
5
  module Exceptions
6
- module NameError
7
- class UninitializedConstant < ExceptionsBase
6
+ module ActiveRecord
7
+ class UninitializedConstant < Base
8
8
  private
9
9
 
10
10
  def unknown_from_exception
11
11
  exception.to_s.split.last
12
12
  end
13
13
 
14
- def corrected_word
15
- @corrected_word ||= spell_checker(ar_models_dictionary).correct(unknown_from_exception).first
16
- end
17
-
18
14
  def corrected_cmd
19
15
  @corrected_cmd ||= last_cmd.gsub(unknown_from_exception, corrected_word)
20
16
  end
21
17
 
22
- def ar_models_dictionary
18
+ def dictionary
23
19
  @ar_models_dictionary ||= store.transaction { |s| s["active_record_models"] }
24
20
  end
25
21
  end
@@ -29,7 +29,11 @@ class ExceptionsBase < Base
29
29
  @pry = pry
30
30
  end
31
31
 
32
- def spell_checker(dictionary)
32
+ def corrected_word
33
+ @corrected_word ||= spell_checker.correct(unknown_from_exception).first
34
+ end
35
+
36
+ def spell_checker
33
37
  DidYouMean::SpellChecker.new(dictionary: dictionary)
34
38
  end
35
39
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "../exceptions_base"
4
4
  require_relative "../../constants/errors"
5
- require_relative "uninitialized_constant"
5
+ require_relative "../active_record/uninitialized_constant"
6
6
  require_relative "undefined_variable"
7
7
 
8
8
  module Exceptions
@@ -21,7 +21,7 @@ module Exceptions
21
21
  def call
22
22
  case exception.message
23
23
  in /#{Constants::Errors::UNINITIALIZED_CONSTANT}/
24
- UninitializedConstant.call(output, exception, pry)
24
+ ActiveRecord::UninitializedConstant.call(output, exception, pry)
25
25
  in /#{Constants::Errors::UNDEFINED_VARIABLE}/
26
26
  UndefinedVariable.call(output, exception, pry)
27
27
  else
@@ -7,10 +7,6 @@ module Exceptions
7
7
  class UndefinedVariable < ExceptionsBase
8
8
  private
9
9
 
10
- def corrected_word
11
- @corrected_word ||= spell_checker(session_dictionary).correct(unknown_from_exception).first
12
- end
13
-
14
10
  def corrected_cmd
15
11
  @corrected_cmd ||= last_cmd.gsub(/\b#{unknown_from_exception}\b/, corrected_word)
16
12
  end
@@ -19,8 +15,8 @@ module Exceptions
19
15
  exception.to_s.match(exception_regexp)[1]
20
16
  end
21
17
 
22
- def session_dictionary
23
- @session_dictionary ||= store.transaction { |s| s[pry_instance_uid] }
18
+ def dictionary
19
+ store.transaction { |s| s[pry_instance_uid] }
24
20
  end
25
21
 
26
22
  def exception_regexp
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "exceptions_base"
4
+
5
+ module Exceptions
6
+ class NoMethodError < ExceptionsBase
7
+ private
8
+
9
+ def corrected_cmd
10
+ @corrected_cmd ||= last_cmd.gsub(/\b#{unknown_from_exception}\b/, corrected_word)
11
+ end
12
+
13
+ def unknown_from_exception
14
+ exception.to_s.match(exception_regexp)[1]
15
+ end
16
+
17
+ def dictionary
18
+ eval(klass).methods.map(&:to_s) # rubocop:disable Security/Eval
19
+ end
20
+
21
+ def exception_regexp
22
+ /`([^']+)' for/
23
+ end
24
+
25
+ def klass
26
+ exception.to_s.match(/for\s+(.*?):\w*$/)[1]
27
+ end
28
+ end
29
+ end
@@ -4,6 +4,7 @@ require_relative "base"
4
4
  require_relative "exceptions/active_record/statement_invalid"
5
5
  require_relative "exceptions/active_record/configuration_error"
6
6
  require_relative "exceptions/name_error/handler"
7
+ require_relative "exceptions/no_method_error"
7
8
  require_relative "constants/errors"
8
9
 
9
10
  class ExceptionsHandler < Base
@@ -17,6 +18,8 @@ class ExceptionsHandler < Base
17
18
 
18
19
  def call
19
20
  case exception
21
+ in NoMethodError
22
+ Exceptions::NoMethodError.call(output, exception, pry)
20
23
  in NameError
21
24
  # NameError is a Superclass for all undefined statement.
22
25
  Exceptions::NameError::Handler.call(output, exception, pry)
@@ -14,10 +14,12 @@ module Session
14
14
  end
15
15
 
16
16
  def call
17
+ return unless is_assignement_variables?
18
+
17
19
  store.transaction do
18
- store.abort unless extract_variable_to_store
20
+ store.abort unless variables_to_store
19
21
 
20
- store[pry_instance_uid].push(variable_to_store)
22
+ store[pry_instance_uid].push(*variables_to_store)
21
23
  end
22
24
  end
23
25
 
@@ -28,16 +30,28 @@ module Session
28
30
  binding.binding_stack.join
29
31
  end
30
32
 
31
- def extract_variable_to_store
32
- @extract_variable_to_store ||= last_cmd.match(/^(\w+)\s*=/)
33
+ def variables_to_store
34
+ @variables_to_store ||= last_cmd.split("=").first.strip.split(",")
33
35
  end
34
36
 
35
37
  def last_cmd
36
38
  binding.eval_string.strip
37
39
  end
38
40
 
39
- def variable_to_store
40
- extract_variable_to_store[1]
41
+ # Returns true if the last command seems to be an assignment of variables, false otherwise.
42
+ #
43
+ # Examples
44
+ #
45
+ # is_assignment_variables?("user_last, user_first = User.last, User.first")
46
+ # # => true
47
+ #
48
+ # is_assignment_variables?("user_last = User.last")
49
+ # # => true
50
+ #
51
+ # is_assignment_variables?("user_last")
52
+ # # => false
53
+ def is_assignement_variables?
54
+ last_cmd.include?("=")
41
55
  end
42
56
  end
43
57
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "checks/database_url"
4
- require_relative "checks/database_pool"
5
- require_relative "store"
6
3
  require_relative "../base"
7
-
4
+ require_relative "store"
5
+ require_relative "dictionary/active_record"
8
6
  require "pstore"
9
7
 
10
8
  module Setup
@@ -16,7 +14,7 @@ module Setup
16
14
  end
17
15
 
18
16
  def call
19
- establish_db_connection
17
+ Setup::Dictionary::ActiveRecord.initialize! if defined?(ActiveRecord)
20
18
  populate_store
21
19
  end
22
20
 
@@ -24,64 +22,14 @@ module Setup
24
22
 
25
23
  attr_reader :binding
26
24
 
27
- SEVEN_DAYS = 604800
28
-
29
25
  def populate_store
30
- store.transaction do
31
- # Create a table with unique instance identifier information to store variables history.
32
- store[pry_instance_uid] = []
33
- store.commit unless staled_store?
34
-
35
- store["active_record_models"] = populate_active_record_models_dictionary
36
- store["associations"] = populate_associations
37
- store["synced_at"] = Time.now
38
- end
39
- end
40
-
41
- def establish_db_connection
42
- configuration_checks
43
- ActiveRecord::Base.establish_connection(development_database_config)
44
- end
45
-
46
- def populate_active_record_models_dictionary
47
- Zeitwerk::Loader.eager_load_all
48
- ActiveRecord::Base.descendants.map { |model| model.name }
49
- end
50
-
51
- def populate_associations
52
- table_names = ActiveRecord::Base.connection.tables
53
- singularize_table_names = table_names.map { |a| a.chop }
54
- table_names.zip(singularize_table_names).flatten
55
- end
56
-
57
- def configuration_checks
58
- Setup::Checks::DatabaseUrl.check(development_database_config, logger)
59
- Setup::Checks::DatabasePool.check(development_database_config, logger)
60
- end
61
-
62
- def database_config
63
- YAML.safe_load(File.read("./config/database.yml"), aliases: true)
64
- end
65
-
66
- def development_database_config
67
- @development_database_config ||= database_config["development"]
68
- end
69
-
70
- # By default we update the store every week.
71
- # TODO: Make it configurable
72
- def staled_store?
73
- return true if store["synced_at"].nil?
74
-
75
- (store["synced_at"] + SEVEN_DAYS) <= Time.now
26
+ # Create a table with unique instance identifier information to store variables history.
27
+ store.transaction { store[pry_instance_uid] = [] }
76
28
  end
77
29
 
78
30
  # Use the binding identifier as pry instance uid.
79
31
  def pry_instance_uid
80
32
  binding.to_s
81
33
  end
82
-
83
- def logger
84
- @logger = Logger.new($stdout)
85
- end
86
34
  end
87
35
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../checks/database_url"
4
+ require_relative "../checks/database_pool"
5
+ require_relative "../store"
6
+
7
+ require "pstore"
8
+
9
+ module Setup
10
+ module Dictionary
11
+ class ActiveRecord
12
+ class << self
13
+ include Store
14
+
15
+ def initialize!
16
+ establish_db_connection
17
+ populate_store
18
+ end
19
+
20
+ private
21
+
22
+ def populate_store
23
+ store.transaction do
24
+ store.commit unless staled_store?
25
+
26
+ store["active_record_models"] = populate_active_record_models_dictionary
27
+ store["associations"] = populate_associations
28
+ store["synced_at"] = Time.now
29
+ end
30
+ end
31
+
32
+ def establish_db_connection
33
+ configuration_checks
34
+ ::ActiveRecord::Base.establish_connection(development_database_config)
35
+ end
36
+
37
+ def populate_active_record_models_dictionary
38
+ Zeitwerk::Loader.eager_load_all
39
+ ::ActiveRecord::Base.descendants.map { |model| format_active_record_model(model) }.flatten
40
+ end
41
+
42
+ def populate_associations
43
+ table_names = ::ActiveRecord::Base.connection.tables
44
+ singularize_table_names = table_names.map { |a| a.chop }
45
+ table_names.zip(singularize_table_names).flatten
46
+ end
47
+
48
+ # This method takes an ActiveRecord model as an argument and formats its name and module information.
49
+ # If the model is within a module namespace, it returns an array containing the model's name and an array of its modules.
50
+ # If the model is not within a module, it returns just the model's name as a string.
51
+ def format_active_record_model(model)
52
+ modules = model.name.split("::")
53
+ return model.name, modules if modules.count > 1
54
+
55
+ model.name
56
+ end
57
+
58
+ def development_database_config
59
+ @development_database_config ||= database_config["development"]
60
+ end
61
+
62
+ def configuration_checks
63
+ Setup::Checks::DatabaseUrl.check(development_database_config, logger)
64
+ Setup::Checks::DatabasePool.check(development_database_config, logger)
65
+ end
66
+
67
+ def database_config
68
+ YAML.safe_load(File.read(database_config_path), aliases: true)
69
+ end
70
+
71
+ def logger
72
+ @logger = Logger.new($stdout)
73
+ end
74
+
75
+ def database_config_path
76
+ ENV["DB_CONFIG_PATH"] || "./config/database.yml"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,6 +1,7 @@
1
1
  module Setup
2
2
  module Store
3
3
  DEFAULT_STORE_PATH = "byetypo_dictionary.pstore"
4
+ SEVEN_DAYS = 604800
4
5
 
5
6
  def store
6
7
  @store ||= PStore.new(store_path)
@@ -9,5 +10,13 @@ module Setup
9
10
  def store_path
10
11
  ENV["BYETYPO_STORE_PATH"] || DEFAULT_STORE_PATH
11
12
  end
13
+
14
+ # By default we update the store every week.
15
+ # TODO: Make it configurable
16
+ def staled_store?
17
+ return true if store["synced_at"].nil?
18
+
19
+ (store["synced_at"] + SEVEN_DAYS) <= Time.now
20
+ end
12
21
  end
13
22
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  class Pry
4
4
  module Byetypo
5
- VERSION = "1.1.0"
5
+ VERSION = "1.3.0"
6
6
  end
7
7
  end
data/pry-byetypo.gemspec CHANGED
@@ -5,14 +5,14 @@ require_relative "lib/pry-byetypo/version"
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "pry-byetypo"
7
7
  gem.version = Pry::Byetypo::VERSION
8
- gem.authors = ["morissetcl"]
8
+ gem.authors = ["Clément Morisset"]
9
9
  gem.email = ["morissetcl87@gmail.com"]
10
10
 
11
11
  gem.summary = "Autocorrects typos in your Pry console"
12
- gem.description = "This small Pry plugin captures exceptions that could be due to typos and deduces the correct command based on your database information."
12
+ gem.description = "This Pry plugin captures exceptions that could be due to typos and deduces the correct command based on your database information."
13
13
  gem.homepage = "https://github.com/morissetcl/pry-byetypo"
14
14
  gem.license = "MIT"
15
- gem.required_ruby_version = ">= 2.6.0"
15
+ gem.required_ruby_version = ">= 2.7.0"
16
16
 
17
17
  gem.metadata["homepage_uri"] = gem.homepage
18
18
  gem.metadata["source_code_uri"] = "https://github.com/morissetcl/pry-byetypo"
@@ -28,7 +28,7 @@ Gem::Specification.new do |gem|
28
28
  gem.bindir = "exe"
29
29
  gem.executables = gem.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
30
  gem.require_paths = ["lib"]
31
+ gem.add_development_dependency "rails", "~> 7.0"
31
32
  gem.add_runtime_dependency "colorize", "~> 1.1.0"
32
33
  gem.add_runtime_dependency "pry", ">= 0.13", "< 0.15"
33
- gem.add_runtime_dependency "rails", "~> 7.0"
34
34
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-byetypo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - morissetcl
7
+ - Clément Morisset
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-31 00:00:00.000000000 Z
11
+ date: 2024-02-29 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: colorize
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,22 +58,8 @@ dependencies:
44
58
  - - "<"
45
59
  - !ruby/object:Gem::Version
46
60
  version: '0.15'
47
- - !ruby/object:Gem::Dependency
48
- name: rails
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '7.0'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '7.0'
61
- description: This small Pry plugin captures exceptions that could be due to typos
62
- and deduces the correct command based on your database information.
61
+ description: This Pry plugin captures exceptions that could be due to typos and deduces
62
+ the correct command based on your database information.
63
63
  email:
64
64
  - morissetcl87@gmail.com
65
65
  executables: []
@@ -81,10 +81,11 @@ files:
81
81
  - lib/pry-byetypo/exceptions/active_record/base.rb
82
82
  - lib/pry-byetypo/exceptions/active_record/configuration_error.rb
83
83
  - lib/pry-byetypo/exceptions/active_record/statement_invalid.rb
84
+ - lib/pry-byetypo/exceptions/active_record/uninitialized_constant.rb
84
85
  - lib/pry-byetypo/exceptions/exceptions_base.rb
85
86
  - lib/pry-byetypo/exceptions/name_error/handler.rb
86
87
  - lib/pry-byetypo/exceptions/name_error/undefined_variable.rb
87
- - lib/pry-byetypo/exceptions/name_error/uninitialized_constant.rb
88
+ - lib/pry-byetypo/exceptions/no_method_error.rb
88
89
  - lib/pry-byetypo/exceptions_handler.rb
89
90
  - lib/pry-byetypo/session/clear_history.rb
90
91
  - lib/pry-byetypo/session/populate_history.rb
@@ -92,6 +93,7 @@ files:
92
93
  - lib/pry-byetypo/setup/checks/base.rb
93
94
  - lib/pry-byetypo/setup/checks/database_pool.rb
94
95
  - lib/pry-byetypo/setup/checks/database_url.rb
96
+ - lib/pry-byetypo/setup/dictionary/active_record.rb
95
97
  - lib/pry-byetypo/setup/store.rb
96
98
  - lib/pry-byetypo/version.rb
97
99
  - pry-byetypo.gemspec
@@ -111,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
113
  requirements:
112
114
  - - ">="
113
115
  - !ruby/object:Gem::Version
114
- version: 2.6.0
116
+ version: 2.7.0
115
117
  required_rubygems_version: !ruby/object:Gem::Requirement
116
118
  requirements:
117
119
  - - ">="