hanami-db 2.2.0.beta1
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 +7 -0
- data/LICENSE.md +22 -0
- data/README.md +52 -0
- data/hanami-db.gemspec +30 -0
- data/lib/hanami/db/gem_inflector.rb +14 -0
- data/lib/hanami/db/relation.rb +10 -0
- data/lib/hanami/db/repo.rb +53 -0
- data/lib/hanami/db/struct.rb +10 -0
- data/lib/hanami/db/testing.rb +145 -0
- data/lib/hanami/db/version.rb +7 -0
- data/lib/hanami/db.rb +28 -0
- data/lib/hanami-db.rb +3 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3b8f0855774dd7a9d0edc7609c7a07b95080edb38a6d30cab7454c5eb61a3e67
|
4
|
+
data.tar.gz: 1398ac362dcab2ac3f74cc59e328b5264c7326ddd6bec6502e3cd747bdceeedc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf77b5817253e28718b84495d45cc6fe1665718c1c008f70577615e1f4c259e39adbfac342112761b30cd699e1b249b88f05b0d839d8955a2201fa645cd84ac0
|
7
|
+
data.tar.gz: b212e3a4b636b0d7bda6a31fad889105a47b9c26a4c094d0a16e1369c41ff01c0fa79a2eefebfa64bce84e3abf5cf6d926d29ec323d5955cc4d0702fcf7a3c5c
|
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright © 2024 Tim Riley
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Hanami::DB
|
2
|
+
|
3
|
+
The database layer for [full-stack Hanami 2.2 applications](hanami/hanami).
|
4
|
+
It's a thin layer on top of [ROM](https://rom-rb.org/) 5.
|
5
|
+
|
6
|
+
## Status
|
7
|
+
|
8
|
+
[](https://badge.fury.io/rb/db)
|
9
|
+
[](https://github.com/hanami/db/actions?query=workflow%3Aci+branch%3Amain)
|
10
|
+
[](https://depfu.com/github/hanami/controller?project=Bundler)
|
11
|
+
|
12
|
+
## Contact
|
13
|
+
|
14
|
+
* Home page: http://hanamirb.org
|
15
|
+
* Community: http://hanamirb.org/community
|
16
|
+
* Guides: https://guides.hanamirb.org
|
17
|
+
* Mailing List: http://hanamirb.org/mailing-list
|
18
|
+
* API Doc: http://rubydoc.info/gems/hanami-db
|
19
|
+
* Chat: http://chat.hanamirb.org
|
20
|
+
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
__Hanami::DB__ supports Ruby (MRI) 3.1+
|
25
|
+
|
26
|
+
Add this line to your Hanami application's Gemfile:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem "hanami-db"
|
30
|
+
```
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
```shell
|
35
|
+
$ bundle
|
36
|
+
```
|
37
|
+
|
38
|
+
## Versioning
|
39
|
+
|
40
|
+
__Hanami::DB__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
49
|
+
|
50
|
+
## Copyright
|
51
|
+
|
52
|
+
Copyright © 2024 Hanami Team – Released under MIT License
|
data/hanami-db.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/hanami/db/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "hanami-db"
|
7
|
+
spec.version = Hanami::DB::VERSION
|
8
|
+
spec.authors = ["Hanami team"]
|
9
|
+
spec.email = ["admin@hanamirb.org"]
|
10
|
+
spec.summary = "The database layer for Hanami apps"
|
11
|
+
spec.homepage = "https://hanamirb.org"
|
12
|
+
spec.license = "MIT"
|
13
|
+
|
14
|
+
spec.metadata = {
|
15
|
+
"bug_tracker_uri" => "https://github.com/hanami/db/issues",
|
16
|
+
"changelog_uri" => "https://github.com/hanami/db/blob/main/CHANGELOG.md",
|
17
|
+
"documentation_uri" => "https://guides.hanamirb.org",
|
18
|
+
"funding_uri" => "https://github.com/sponsors/hanami",
|
19
|
+
"source_code_uri" => "https://github.com/hanami/db",
|
20
|
+
"rubygems_mfa_required" => "true"
|
21
|
+
}
|
22
|
+
|
23
|
+
spec.required_ruby_version = ">= 3.1"
|
24
|
+
spec.add_dependency "rom", "~> 5.3"
|
25
|
+
spec.add_dependency "rom-sql", "~> 3.6", ">= 3.6.4"
|
26
|
+
spec.add_dependency "zeitwerk", "~> 2.6"
|
27
|
+
|
28
|
+
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
29
|
+
spec.files = Dir["*.gemspec", "lib/**/*"]
|
30
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module DB
|
5
|
+
# @api public
|
6
|
+
# @since 2.2.0
|
7
|
+
class Repo < ROM::Repository
|
8
|
+
# @api public
|
9
|
+
# @since 2.2.0
|
10
|
+
def self.[](root)
|
11
|
+
fetch_or_store(root) do
|
12
|
+
# Override ROM::Repository.[] logic to ensure repos with explicit roots inherit from
|
13
|
+
# Hanami::DB::Repo itself, instead of the plain old ROM::Repository::Root.
|
14
|
+
Class.new(self).tap { |klass|
|
15
|
+
klass.root(root)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api public
|
21
|
+
# @since 2.2.0
|
22
|
+
defines :root
|
23
|
+
|
24
|
+
# @api public
|
25
|
+
# @since 2.2.0
|
26
|
+
attr_reader :root
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def self.inherited(klass)
|
30
|
+
super
|
31
|
+
klass.root(root)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api public
|
35
|
+
# @since 2.2.0
|
36
|
+
def initialize(*, **)
|
37
|
+
super
|
38
|
+
|
39
|
+
# Repos in Hanami apps infer a root from their class name (e.g. :posts for PostRepo). This
|
40
|
+
# means _every_ repo ends up with an inferred root, many of which will not exist as
|
41
|
+
# relations. To avoid errors from fetching these non-existent relations, check first before
|
42
|
+
# setting the root.
|
43
|
+
@root = set_relation(self.class.root) if set_relation?(self.class.root)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def set_relation?(name) # rubocop:disable Naming/AccessorMethodName
|
49
|
+
name && container.relations.key?(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
module DB
|
8
|
+
module Testing
|
9
|
+
# Replaces development suffix in test mode
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 2.2.0
|
13
|
+
DATABASE_NAME_SUFFIX = "_test"
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
# @since 2.2.0
|
17
|
+
DATABASE_NAME_MATCHER = /_dev(elopment)?$/
|
18
|
+
private_constant :DATABASE_NAME_MATCHER
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# @api private
|
22
|
+
# @since 2.2.0
|
23
|
+
def database_url(url)
|
24
|
+
url = parse_url(url)
|
25
|
+
|
26
|
+
case deconstruct_url(url)
|
27
|
+
in { scheme: "sqlite", opaque: nil, path: } unless path.nil?
|
28
|
+
url.path = database_filename(path)
|
29
|
+
in { path: String => path } if path =~ DATABASE_NAME_MATCHER
|
30
|
+
url.path = path.sub(DATABASE_NAME_MATCHER, DATABASE_NAME_SUFFIX)
|
31
|
+
in { path: String => path } unless path.end_with?(DATABASE_NAME_SUFFIX)
|
32
|
+
url.path << DATABASE_NAME_SUFFIX
|
33
|
+
else
|
34
|
+
# do nothing
|
35
|
+
end
|
36
|
+
|
37
|
+
stringify_url(url)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
# @since 2.2.0
|
44
|
+
def parse_url(url)
|
45
|
+
if url.is_a?(URI::Generic)
|
46
|
+
# URI#dup does not duplicate internal instance
|
47
|
+
# variables, making mutation dangerous.
|
48
|
+
URI(stringify_url(url))
|
49
|
+
else
|
50
|
+
URI(url.to_s)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
55
|
+
|
56
|
+
# Work around a bug in Ruby 3.0.x that erroneously omits
|
57
|
+
# the '//' prefix from hierarchical URLs.
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
# @since 2.2.0
|
61
|
+
def stringify_url(url)
|
62
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.1.0")
|
63
|
+
return url.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
require "stringio"
|
67
|
+
|
68
|
+
buf = StringIO.new
|
69
|
+
buf << url.scheme
|
70
|
+
buf << ":"
|
71
|
+
buf << (url.opaque || "//")
|
72
|
+
|
73
|
+
if url.user || url.password
|
74
|
+
buf << "#{url.user}:#{url.password}@"
|
75
|
+
end
|
76
|
+
|
77
|
+
if url.host
|
78
|
+
buf << url.host
|
79
|
+
end
|
80
|
+
|
81
|
+
if url.port
|
82
|
+
buf << ":"
|
83
|
+
buf << url.port
|
84
|
+
end
|
85
|
+
|
86
|
+
if url.path
|
87
|
+
buf << url.path
|
88
|
+
end
|
89
|
+
|
90
|
+
if url.query
|
91
|
+
buf << "?"
|
92
|
+
buf << url.query
|
93
|
+
end
|
94
|
+
|
95
|
+
if url.fragment
|
96
|
+
buf << "#"
|
97
|
+
buf << url.fragment
|
98
|
+
end
|
99
|
+
|
100
|
+
buf.string
|
101
|
+
end
|
102
|
+
|
103
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
|
104
|
+
|
105
|
+
# Deconstructs a URI::Generic for pattern-matching.
|
106
|
+
#
|
107
|
+
# @param url [URI] Database URL parsed as URI::Generic
|
108
|
+
#
|
109
|
+
# @return [Hash]
|
110
|
+
#
|
111
|
+
# @api private
|
112
|
+
# @since 2.2.0
|
113
|
+
def deconstruct_url(url)
|
114
|
+
%i[opaque path scheme].each_with_object({}) do |part, hash|
|
115
|
+
hash[part] = url.public_send(part)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Transform filename as with URI paths, but account for extname
|
120
|
+
#
|
121
|
+
# @param path [String] path component from URI
|
122
|
+
#
|
123
|
+
# @return [String]
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
# @since 2.2.0
|
127
|
+
def database_filename(path)
|
128
|
+
path = Pathname(path)
|
129
|
+
ext = path.extname
|
130
|
+
database = path.basename(ext).to_s
|
131
|
+
|
132
|
+
if database =~ /^dev(elopment)?$/
|
133
|
+
database = "test"
|
134
|
+
elsif database =~ DATABASE_NAME_MATCHER
|
135
|
+
database.sub!(DATABASE_NAME_MATCHER, DATABASE_NAME_SUFFIX)
|
136
|
+
elsif !database.end_with?(DATABASE_NAME_SUFFIX)
|
137
|
+
database << DATABASE_NAME_SUFFIX
|
138
|
+
end
|
139
|
+
|
140
|
+
path.dirname.join(database + ext).to_s
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/hanami/db.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom"
|
4
|
+
require "rom-sql"
|
5
|
+
require "zeitwerk"
|
6
|
+
|
7
|
+
module Hanami
|
8
|
+
module DB
|
9
|
+
require_relative "db/gem_inflector"
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
# @since 2.2.0
|
13
|
+
def self.loader
|
14
|
+
@loader ||= Zeitwerk::Loader.new.tap do |loader|
|
15
|
+
root = File.expand_path("..", __dir__)
|
16
|
+
|
17
|
+
loader.inflector = GemInflector.new("#{root}/hanami/db.rb")
|
18
|
+
loader.tag = "hanami-db"
|
19
|
+
loader.push_dir root
|
20
|
+
loader.ignore(
|
21
|
+
"#{root}/hanami-db.rb",
|
22
|
+
"#{root}/hanami/db/gem_inflector.rb"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
loader.setup
|
27
|
+
end
|
28
|
+
end
|
data/lib/hanami-db.rb
ADDED
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hanami-db
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hanami team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rom
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rom-sql
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.6'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 3.6.4
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.6'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 3.6.4
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: zeitwerk
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.6'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.6'
|
61
|
+
description:
|
62
|
+
email:
|
63
|
+
- admin@hanamirb.org
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files:
|
67
|
+
- README.md
|
68
|
+
- LICENSE.md
|
69
|
+
files:
|
70
|
+
- LICENSE.md
|
71
|
+
- README.md
|
72
|
+
- hanami-db.gemspec
|
73
|
+
- lib/hanami-db.rb
|
74
|
+
- lib/hanami/db.rb
|
75
|
+
- lib/hanami/db/gem_inflector.rb
|
76
|
+
- lib/hanami/db/relation.rb
|
77
|
+
- lib/hanami/db/repo.rb
|
78
|
+
- lib/hanami/db/struct.rb
|
79
|
+
- lib/hanami/db/testing.rb
|
80
|
+
- lib/hanami/db/version.rb
|
81
|
+
homepage: https://hanamirb.org
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata:
|
85
|
+
bug_tracker_uri: https://github.com/hanami/db/issues
|
86
|
+
changelog_uri: https://github.com/hanami/db/blob/main/CHANGELOG.md
|
87
|
+
documentation_uri: https://guides.hanamirb.org
|
88
|
+
funding_uri: https://github.com/sponsors/hanami
|
89
|
+
source_code_uri: https://github.com/hanami/db
|
90
|
+
rubygems_mfa_required: 'true'
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '3.1'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubygems_version: 3.5.9
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: The database layer for Hanami apps
|
110
|
+
test_files: []
|