Skip to content

Commit

Permalink
Add Sqlpkg.path_for method to get file path to installed extension
Browse files Browse the repository at this point in the history
  • Loading branch information
fractaledmind committed Dec 8, 2024
1 parent 278de92 commit 858cc7e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,42 @@ bundle exec sqlpkg help
└────────────────────────────────────────────────┘
```

You can get the path to an installed extension using the `Sqlpkg.path_for` method, e.g.:

```ruby
Sqlpkg.path_for("nalgeon/uuid")
# => "./.sqlpkg/nalgeon/uuid/uuid.dylib"
```

You can also use the shorter `.[]` alias:

```ruby
Sqlpkg["nalgeon/uuid"]
# => "./.sqlpkg/nalgeon/uuid/uuid.dylib"
```

If you try to access an extension that hasn't been installed, a `Sqlpkg::ExtensionNotInstalledError` will be raised:

```ruby
Sqlpkg["nalgeon/ulid"]
# raises Sqlpkg::ExtensionNotInstalledError
```

This feature is particulary useful for the [new Rails feature](https://github.com/rails/rails/pull/53827) and [`sqlite3-ruby` feature](https://github.com/sparklemotion/sqlite3-ruby/pull/586) that allows automatically loading extensions via the `extensions` keyword defined in the Rails `config/database.yml` or the `SQLite3::Database.new` method call. You can now use either:

```yaml
development:
adapter: sqlite3
extensions:
- <%= Sqlpkg.path_for("asg017/ulid") %>
```
or if you are using `SQLite3::Database` directly:

```ruby
db = SQLite3::Database.new(":memory:", extensions: [Sqlpkg.path_for("asg017/ulid")])
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand Down
29 changes: 29 additions & 0 deletions lib/sqlpkg.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
# frozen_string_literal: true

module Sqlpkg
DIR = ".sqlpkg"
FILE_PATTERN = "*.{dylib,so,dll}"

Error = Class.new(StandardError)
ExtensionNotInstalledError = Class.new(Error)

class << self
# File path for identified extension
# => "./.sqlpkg/nalgeon/uuid/uuid.dylib"
def path_for(identifier)
path_glob = File.join(file_dir, identifier, FILE_PATTERN)
path = Dir.glob(path_glob).first

path || raise(ExtensionNotInstalledError, "No extension found for identifier: #{identifier}")
end
alias_method :[], :path_for

# The directory where `sqlpkg` stores installed extensions
# => "./.sqlpkg"
def file_dir
File.join(__dir__, DIR)
end

# List of file paths for all installed extensions
# => ["./.sqlpkg/asg017/ulid/ulid0.dylib", "./.sqlpkg/nalgeon/uuid/uuid.dylib"]
def installed_extension_paths
Dir.glob File.join(file_dir, "**", FILE_PATTERN)
end
end
end

require_relative "sqlpkg/version"
Expand Down
26 changes: 26 additions & 0 deletions test/test_sqlpkg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,30 @@ class TestSqlpkg < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::Sqlpkg::VERSION
end

def test_path_for_when_glob_returns_paths
path = "./.sqlpkg/nalgeon/uuid/uuid.dylib"
Dir.stub :glob, [path] do
assert_equal path, Sqlpkg.path_for("nalgeon/uuid")
end
end

def test_path_for_when_glob_returns_empty_array
assert_raises Sqlpkg::ExtensionNotInstalledError do
Sqlpkg.path_for("nalgeon/uuid")
end
end

def test_accessor_when_glob_returns_paths
path = "./.sqlpkg/nalgeon/uuid/uuid.dylib"
Dir.stub :glob, [path] do
assert_equal path, Sqlpkg["nalgeon/uuid"]
end
end

def test_accessor_when_glob_returns_empty_array
assert_raises Sqlpkg::ExtensionNotInstalledError do
Sqlpkg["nalgeon/uuid"]
end
end
end

0 comments on commit 858cc7e

Please sign in to comment.