PRY-BYETYPO 👋
Autocorrects typos in your Pry console.
This small Pry plugin captures exceptions that may arise from typos and deduces the correct command based on your database information and session history.
Note
Currently, this plugin is not truly agnostic; to fully benefit from it, ActiveRecord with PostgreSQL is required.
Installation
Install the gem and add to the application's Gemfile, under the development
group, by executing:
bundle add pry-byetypo
If bundler is not being used to manage dependencies, install the gem by executing:
gem install pry-byetypo
Usage
- Open a PRY console.
- Start your daily work.
- Let
pry-byetypo
remove frictions. 🚀
Byetypo dictionary
When you open a new Pry console, the gem will generate a byetypo_dictionary.pstore
file containing four pieces of information:
- A list of the ActiveRecord models in your application (e.g.
User
,Account
). - A list of the ActiveRecord associations in your application (e.g.
user
,users
,account
,accounts
). - Unique identifiers for each active Pry instance, populated with the variable history of the current session. (e.g.
result = 1
will storeresult
) - A timestamp representing the last time the
byetypo_dictionary
was updated. (by default updated every week).
This file is generated at the root of your application by default. If you want to update its location, you can configure the path by adding a BYETYPO_STORE_PATH
entry in your .env
file.
Captured exceptions
NameError - undefined local variable or method
This error occurs when you mispelled a variable in your REPL. The gem will catch that exception and will try find the closest matches. If so, it will run the command with the (potential) corrected variable.
Before
[1] pry(main)> result = 1
=> 1
[2] pry(main)> resilt
NameError: undefined local variable or method `resilt' for main:Object
from (pry):2:in `__pry__'
After
[1] pry(main)> result = 1
=> 1
[2] pry(main)> resilt
E, [2024-01-31T17:11:16.344161 #3739] ERROR -- : undefined local variable or method `resilt' for main:Object
I, [2024-01-31T17:11:16.344503 #3739] INFO -- : Running: result
=> 1
NameError - uninitialized constant
This error occurs when you mispelled a model in your REPL. The gem will catch that exception and will try find the closest matches. If so, it will run the command with the (potential) corrected model.
Before
[2] pry(main)> Usert.last
NameError: uninitialized constant Usert
from (pry):2:in `__pry__'
[3] pry(main)>
After
[1] pry(main)> Usert.last
I, [2024-01-13T20:00:16.280710 #694] ERROR -- : uninitialized constant Usert
I, [2024-01-13T20:00:16.281237 #694] INFO -- : Running: User.last
=> #<User id: 1, email: "yo@email.com">
NoMethodError - undefined method
This error occurs when you mispelled a method in your REPL. The gem will catch that exception and will try find the closest matches. If so, it will run the command with the (potential) corrected method.
Before
[1] pry(main)> User.lasst
NoMethodError: undefined method `lasst' for User:Class
from (pry):2:in `__pry__'
After
[1] pry(main)> User.lasst
E, [2024-01-31T17:11:16.344161 #3739] ERROR -- : undefined method `lasst' for User:Class
I, [2024-01-31T17:11:16.344503 #3739] INFO -- : Running: User.last
=> #<User id: 1, email: "yo@email.com">
UndefinedColumn
This error occurs when you mispelled a column in your REPL. The gem will catch that exception and will try find the closest matches. If so, it will run the command with the (potential) corrected column.
Before
[2] pry(main)> User.find_by(emil: "yo@email.com")
E, [2024-03-31T00:14:12.907708 #11761] ERROR -- : PG::UndefinedColumn: ERROR: column users.emil does not exist
LINE 1: ...OM "users" WHERE "users"."deleted_at" IS NULL AND "users"."e...
^
HINT: Perhaps you meant to reference the column "users.email".
After
[1] pry(main)> User.find_by(emil: "yo@email.com")
E, [2024-03-31T00:14:12.907708 #11761] ERROR -- : PG::UndefinedColumn: ERROR: column users.emil does not exist
LINE 1: ...OM "users" WHERE "users"."deleted_at" IS NULL AND "users"."e...
^
HINT: Perhaps you meant to reference the column "users.email".
I, [2024-03-31T00:14:12.908257 #11761] INFO -- : Running: User.find_by(email: "yo@email.com")
2024-03-31 00:14:12.915906 D [11761:9180 log_subscriber.rb:130] ActiveRecord::Base -- User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."email" = $1 LIMIT $2 [["email", "yo@email.com"], ["LIMIT", 1]]
=> #<User id: 1, email: "yo@email.com", ...>
ActiveRecord::ConfigurationError
Raised when association is being configured improperly or user tries to use offset and limit together with ActiveRecord::Base.has_many
or ActiveRecord::Base.has_and_belongs_to_many
associations.
This plugin will look into the byetypo_dictionary
file to find the closest match and run the correct query.
Before
[6] pry(main)> User.joins(:group).where(groups: { name: "Landlord" }).last
ActiveRecord::ConfigurationError: Can't join 'User' to association named 'group'; perhaps you misspelled it?
After
[1] pry(main)> User.joins(:group).where(groups: { name: "Landlord" })
I, [2024-01-13T22:45:16.297811 #1079] ERROR -- : ActiveRecord::ConfigurationError: Can't join 'User' to association named 'group'; perhaps you misspelled it?
I, [2024-01-13T22:45:16.297972 #1079] INFO -- : Running: User.joins(:groups).where(groups: { name: "Landlord" })
2024-01-13 22:45:16.319544 D [1079:9200 log_subscriber.rb:130] ActiveRecord::Base -- User Load (1.6ms) SELECT "users".* FROM "users" INNER JOIN "user_groups" ON "user_groups"."user_id" = "users"."id" INNER JOIN "groups" ON "groups"."id" = "user_groups"."group_id" WHERE "users"."deleted_at" IS NULL AND "groups"."name" = $1 [["name", "Landlord"]]
=> []
ActiveRecord::StatementInvalid
The query attempts to reference columns or conditions related to a table, but the table is not properly included in the FROM clause.
This plugin will look into the byetypo_dictionary
file to find the closest match and run the correct query.
Before
[1] pry(main)> User.joins(:groups).where(grous: { name: "Landlord" }).last
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "grous"
LINE 1: ..."group_id" WHERE "users"."deleted_at" IS NULL AND "grous"."n...
After
1] pry(main)> User.joins(:groups).where(grous: { name: "Landlord" }).last
I, [2024-01-14T23:50:49.273043 #1248] ERROR -- : ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "grous"
I, [2024-01-14T23:50:49.273177 #1248] INFO -- : Running: User.joins(:groups).where(groups: { name: "Landlord" }).last
2024-01-14 23:50:49.281956 D [1248:9200 log_subscriber.rb:130] ActiveRecord::Base -- User Load (2.1ms) SELECT "users".* FROM "users" INNER JOIN "user_groups" ON "user_groups"."user_id" = "users"."id" INNER JOIN "groups" ON "groups"."id" = "user_groups"."group_id" WHERE "users"."deleted_at" IS NULL AND "groups"."name" = $1 ORDER BY "users"."id" DESC LIMIT $2 [["name", "Landlord"], ["LIMIT", 1]]
Troubleshooting
Pry-byetypo is linked to your development database. During initialization, it will attempt to establish a connection to retrieve the tables available in your project. It will fetch the information for the development environment from the database.yml
file.
Unreadable database URL (URI::InvalidURIError)
If the database connection string is not readable, the gem will be unable to establish a connection. If you encounter such an issue, make sure to add a DATABASE_URL
variable to your .env
file with the easily readable URL of your database.
Unreadable connection pool (ActiveRecord::ConnectionTimeoutError)
If the number of connections in your pool is not readable, you may encounter an ActiveRecord::ConnectionTimeoutError
. If you experience this issue, make sure to add a DATABASE_POOL
variable to your .env
file.
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/morissetcl/pry-byetypo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the Pry::Byetypo project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.