diff --git a/README.md b/README.md index 2cb529e..79af782 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/lib/sqlpkg.rb b/lib/sqlpkg.rb index 6c574c0..a24ec14 100644 --- a/lib/sqlpkg.rb +++ b/lib/sqlpkg.rb @@ -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" diff --git a/test/test_sqlpkg.rb b/test/test_sqlpkg.rb index bccc189..224cdaf 100644 --- a/test/test_sqlpkg.rb +++ b/test/test_sqlpkg.rb @@ -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