hanami 2.2.0.beta1 → 2.2.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ada7b19a9d5205199e825e57d41758bbc67c350f3d565b01cd4720b9ed8f3ad4
4
- data.tar.gz: 2af8c539547dcbc78dde70db5e31fc72bafa9578dcf391178ec342b618ea6467
3
+ metadata.gz: 6d6bd309aaaf86dce283f25dbdf786db6da76567ae8b00aed92c34de637f8909
4
+ data.tar.gz: 3b6430d47afb052bdc4df9ce200ceb3b2888b733b040bdb4de056052a8e99db2
5
5
  SHA512:
6
- metadata.gz: ed3735c73b897db477ba35cd3d2f0aee79c98940eb4cba651590e5bedf74f34d3969a8dc8200fcae2cfda1a1f7345e873b9bcd075a3f3a627d81eef0ac36ac94
7
- data.tar.gz: 65aebf467d397b29148dda81262550c528469adbd75759615415e89293cefd0cdb1444bd7fc1513c07d46da290ac2092f31752c4d3adeb856f709c04d540497f
6
+ metadata.gz: a73cfea60952ba798fe2d04b2cf430996f8b81960959054251e4277b9f0a53aadfdad23850d389fcedcdb3f77a0855acd2e128e5d8aa3cc8a82df485ae11d592
7
+ data.tar.gz: 05a033e21dd6b9499b125583de931a39f128828ef5f8d730c7ef1522db765ffef35eb1938013b8f58d1199d68aa8564d5183a726bb733e4d1c5b1aaae9f79f7f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  The web, with simplicity.
4
4
 
5
+ ## v2.2.0.beta2 - 2024-09-26
6
+
7
+ ### Added
8
+
9
+ - [Tim Riley] Support multiple gateways within each slice's `:db` provider (#1452)
10
+ - [Tim Riley] Register ROM commands and mappers in `db/commands/` and `db/mappers/`. Support registration of components from deeply nested files within these directories. (#1448)
11
+ - [Adam Lassek, Tim Riley] Make `slice` available inside providers (as an alias for `target`) (#1446)
12
+
13
+ ### Changed
14
+
15
+ - [Tim Riley] Register deeply nested relation files with ROM (#1448)
16
+ - [Kyle Plump] Raise helpful error when preparing `:db` provider if the relevant driver gem for the configured database type is not installed (#1453)
17
+ - [Sean Collins] Remove "disabled" attribute on the `<option>` generated via the `select` helper's `prompt:`, so it shows properly on the select box in the browser (#1444)
18
+
5
19
  ## v2.2.0.beta1 - 2024-07-16
6
20
 
7
21
  ### Added
data/hanami.gemspec CHANGED
@@ -36,9 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "dry-core", "~> 1.0", "< 2"
37
37
  spec.add_dependency "dry-inflector", "~> 1.0", ">= 1.1.0", "< 2"
38
38
  spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
39
- spec.add_dependency "dry-system", "= 1.1.0.beta1"
39
+ spec.add_dependency "dry-system", "= 1.1.0.beta2"
40
40
  spec.add_dependency "dry-logger", "~> 1.0", "< 2"
41
- spec.add_dependency "hanami-cli", "= 2.2.0.beta1"
41
+ spec.add_dependency "hanami-cli", "= 2.2.0.beta2"
42
42
  spec.add_dependency "hanami-utils", "~> 2.2.beta"
43
43
  spec.add_dependency "zeitwerk", "~> 2.6"
44
44
 
@@ -52,4 +52,8 @@ module Hanami
52
52
  # @api private
53
53
  RB_EXT = ".rb"
54
54
  private_constant :RB_EXT
55
+
56
+ # @api private
57
+ RB_EXT_REGEXP = %r{.rb$}
58
+ private_constant :RB_EXT_REGEXP
55
59
  end
@@ -938,7 +938,7 @@ module Hanami
938
938
  #
939
939
  # =>
940
940
  # <select name="book[store]" id="book-store" class="form-control">
941
- # <option disabled="disabled">Select a store</option>
941
+ # <option>Select a store</option>
942
942
  # <option value="it">Italy</option>
943
943
  # <option value="au">Australia</option>
944
944
  # </select>
@@ -995,7 +995,7 @@ module Hanami
995
995
  input_value = _value(name)
996
996
 
997
997
  option_tags = []
998
- option_tags << tag.option(prompt, disabled: true) if prompt
998
+ option_tags << tag.option(prompt) if prompt
999
999
 
1000
1000
  already_selected = nil
1001
1001
  values.each do |content, value|
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Provider
5
+ class Source < Dry::System::Provider::Source
6
+ attr_reader :slice
7
+
8
+ def initialize(slice:, **options, &block)
9
+ @slice = slice
10
+ super(**options, &block)
11
+ end
12
+
13
+ def target_container = slice
14
+ end
15
+ end
16
+ end
@@ -19,8 +19,10 @@ module Hanami
19
19
  @slice = slice
20
20
  end
21
21
 
22
- def target_container
23
- slice
22
+ def provider_source_class = Hanami::Provider::Source
23
+
24
+ def provider_source_options
25
+ {slice: slice}
24
26
  end
25
27
  end
26
28
  end
@@ -9,7 +9,7 @@ module Hanami
9
9
  #
10
10
  # @api private
11
11
  # @since 2.0.0
12
- class Assets < Dry::System::Provider::Source
12
+ class Assets < Hanami::Provider::Source
13
13
  # @api private
14
14
  def prepare
15
15
  require "hanami/assets"
@@ -17,9 +17,9 @@ module Hanami
17
17
 
18
18
  # @api private
19
19
  def start
20
- root = target.app.root.join("public", "assets", Hanami::Assets.public_assets_dir(target).to_s)
20
+ root = slice.app.root.join("public", "assets", Hanami::Assets.public_assets_dir(target).to_s)
21
21
 
22
- assets = Hanami::Assets.new(config: target.config.assets, root: root)
22
+ assets = Hanami::Assets.new(config: slice.config.assets, root: root)
23
23
 
24
24
  register(:assets, assets)
25
25
  end
@@ -4,7 +4,7 @@ require "dry/configurable"
4
4
 
5
5
  module Hanami
6
6
  module Providers
7
- class DB < Dry::System::Provider::Source
7
+ class DB < Hanami::Provider::Source
8
8
  # @api public
9
9
  # @since 2.2.0
10
10
  class Adapter
@@ -30,6 +30,13 @@ module Hanami
30
30
  @skip_defaults[setting_name]
31
31
  end
32
32
 
33
+ # @api private
34
+ def configure_from_adapter(other_adapter)
35
+ return if skip_defaults?
36
+
37
+ plugins.concat(other_adapter.plugins).uniq! unless skip_defaults?(:plugins)
38
+ end
39
+
33
40
  # @api private
34
41
  def configure_for_database(database_url)
35
42
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Hanami
4
4
  module Providers
5
- class DB < Dry::System::Provider::Source
5
+ class DB < Hanami::Provider::Source
6
6
  # @api public
7
7
  # @since 2.2.0
8
8
  class Adapters
@@ -17,6 +17,12 @@ module Hanami
17
17
 
18
18
  def_delegators :adapters, :[], :[]=, :each, :to_h
19
19
 
20
+ # @api private
21
+ # @since 2.2.0
22
+ def self.new_adapter(name)
23
+ ADAPTER_CLASSES[name].new
24
+ end
25
+
20
26
  # @api private
21
27
  # @since 2.2.0
22
28
  attr_reader :adapters
@@ -25,7 +31,7 @@ module Hanami
25
31
  # @since 2.2.0
26
32
  def initialize
27
33
  @adapters = Hash.new do |hsh, key|
28
- hsh[key] = ADAPTER_CLASSES[key].new
34
+ hsh[key] = self.class.new_adapter(key)
29
35
  end
30
36
  end
31
37
 
@@ -4,12 +4,20 @@ require "dry/core"
4
4
 
5
5
  module Hanami
6
6
  module Providers
7
- class DB < Dry::System::Provider::Source
7
+ class DB < Hanami::Provider::Source
8
8
  # @api public
9
9
  # @since 2.2.0
10
10
  class Config < Dry::Configurable::Config
11
11
  include Dry::Core::Constants
12
12
 
13
+ # @api public
14
+ # @since 2.2.0
15
+ def gateway(key)
16
+ gateway = (gateways[key] ||= Gateway.new)
17
+ yield gateway if block_given?
18
+ gateway
19
+ end
20
+
13
21
  # @api public
14
22
  # @since 2.2.0
15
23
  def adapter_name
@@ -30,34 +38,22 @@ module Hanami
30
38
  # @since 2.2.0
31
39
  def any_adapter
32
40
  adapter = (adapters[nil] ||= Adapter.new)
33
- yield adapter if block_given?
41
+ yield adapter if block_given?
34
42
  adapter
35
43
  end
36
44
 
37
45
  # @api private
38
- # @since 2.2.0
39
- def gateway_cache_keys
40
- adapters[adapter_name].gateway_cache_keys
41
- end
42
-
43
- # @api private
44
- # @since 2.2.0
45
- def gateway_options
46
- adapters[adapter_name].gateway_options
47
- end
48
-
49
- # @api public
50
- # @since 2.2.0
51
46
  def each_plugin
52
- universal_plugins = adapters[nil].plugins
53
- adapter_plugins = adapters[adapter_name].plugins
47
+ return to_enum(__method__) unless block_given?
54
48
 
55
- plugins = universal_plugins + adapter_plugins
49
+ universal_plugins = adapters[nil].plugins
56
50
 
57
- return to_enum(__method__) unless block_given?
51
+ gateways.values.group_by(&:adapter_name).each do |adapter_name, adapter_gateways|
52
+ per_adapter_plugins = adapter_gateways.map { _1.adapter.plugins }.flatten(1)
58
53
 
59
- plugins.each do |plugin_spec, config_block|
60
- yield plugin_spec, config_block
54
+ (universal_plugins + per_adapter_plugins).uniq.each do |plugin_spec, config_block|
55
+ yield adapter_name, plugin_spec, config_block
56
+ end
61
57
  end
62
58
  end
63
59
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/configurable"
4
+ require "dry/core"
5
+
6
+ module Hanami
7
+ module Providers
8
+ class DB < Hanami::Provider::Source
9
+ # @api public
10
+ # @since 2.2.0
11
+ class Gateway
12
+ include Dry::Core::Constants
13
+ include Dry::Configurable
14
+
15
+ setting :database_url
16
+ setting :adapter_name, default: :sql
17
+ setting :adapter, mutable: true
18
+
19
+ # @api public
20
+ # @since 2.2.0
21
+ def adapter(name = Undefined)
22
+ return config.adapter if name.eql?(Undefined)
23
+
24
+ if block_given?
25
+ # If a block is given, explicitly configure the gateway's adapter
26
+ config.adapter_name = name
27
+ adapter = (config.adapter ||= Adapters.new_adapter(name))
28
+ yield adapter
29
+ adapter
30
+ else
31
+ # If an adapter name is given without a block, use the default adapter configured with
32
+ # the same name
33
+ config.adapter_name = adapter_name
34
+ end
35
+ end
36
+
37
+ # @api private
38
+ def configure_adapter(default_adapters)
39
+ default_adapter = default_adapters[config.adapter_name]
40
+ config.adapter ||= default_adapter.dup
41
+
42
+ config.adapter.configure_from_adapter(default_adapter)
43
+ config.adapter.configure_from_adapter(default_adapters[nil])
44
+ config.adapter.configure_for_database(config.database_url)
45
+
46
+ self
47
+ end
48
+
49
+ # @api private
50
+ def cache_keys
51
+ [config.database_url, config.adapter.gateway_cache_keys]
52
+ end
53
+
54
+ private
55
+
56
+ def method_missing(name, *args, &block)
57
+ if config.respond_to?(name)
58
+ config.public_send(name, *args, &block)
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ def respond_to_missing?(name, _include_all = false)
65
+ config.respond_to?(name) || super
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Hanami
4
4
  module Providers
5
- class DB < Dry::System::Provider::Source
5
+ class DB < Hanami::Provider::Source
6
6
  # @api public
7
7
  # @since 2.2.0
8
8
  class SQLAdapter < Adapter
@@ -22,6 +22,20 @@ module Hanami
22
22
  config.extensions ||= []
23
23
  end
24
24
 
25
+ # @api private
26
+ def configure_from_adapter(other_adapter)
27
+ super
28
+
29
+ return if skip_defaults?
30
+
31
+ # As part of gateway configuration, every gateway will receive the "any adapter" here,
32
+ # which is a plain `Adapter`, not an `SQLAdapter`. Its configuration will have been merged
33
+ # by `super`, so no further work is required.
34
+ return unless other_adapter.is_a?(self.class)
35
+
36
+ extensions.concat(other_adapter.extensions).uniq! unless skip_defaults?(:extensions)
37
+ end
38
+
25
39
  # @api private
26
40
  def configure_for_database(database_url)
27
41
  return if skip_defaults?
@@ -34,13 +48,19 @@ module Hanami
34
48
  private def configure_plugins
35
49
  return if skip_defaults?(:plugins)
36
50
 
37
- plugin relations: :instrumentation do |plugin|
38
- plugin.notifications = target["notifications"]
39
- end
51
+ # Configure the plugin via a frozen proc, so it can be properly uniq'ed when configured
52
+ # for multiple gateways. See `Hanami::Providers::DB::Config#each_plugin`.
53
+ plugin(relations: :instrumentation, &INSTRUMENTATION_PLUGIN_CONFIG)
40
54
 
41
55
  plugin relations: :auto_restrictions
42
56
  end
43
57
 
58
+ # @api private
59
+ INSTRUMENTATION_PLUGIN_CONFIG = -> plugin {
60
+ plugin.notifications = target["notifications"]
61
+ }.freeze
62
+ private_constant :INSTRUMENTATION_PLUGIN_CONFIG
63
+
44
64
  # @api private
45
65
  private def configure_extensions(database_url)
46
66
  return if skip_defaults?(:extensions)
@@ -53,7 +73,7 @@ module Hanami
53
73
  )
54
74
 
55
75
  # Extensions for specific databases
56
- if database_url.to_s.start_with?("postgresql://")
76
+ if database_url.to_s.start_with?(%r{postgres(ql)*://}) # FIXME: what is the canonical postgres URL?
57
77
  extension(
58
78
  :pg_array,
59
79
  :pg_enum,