solidus_support 0.12.0 → 0.14.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88870615f95d8fe0794ee093b13f2875de6c84390a137352c196c7a6aa97d469
4
- data.tar.gz: 2aa7188af2b42c60e90201d4b366673ed4f1b8333cc31d11ce9da7fde534e659
3
+ metadata.gz: 2cdd9849818af1dc56048136d30a8198d6d79c7245250824283659a47c396932
4
+ data.tar.gz: e82afa4bcca816ad08c7b0afb4ff09279104c99c111818d96ba26cf0f7dab2f7
5
5
  SHA512:
6
- metadata.gz: 2f090251b1f4511057d6ec13781d63af4e951d3875818c157b7382e55c1d654a05ff464569af85fdafaa021a0ac3c998af29d29b3a70acb776c976e1becbb943
7
- data.tar.gz: dfa6ba3b3ac590ac623f1c707edfb1d09ce369435bb8508feba37feed3908dcacc59c35b9b01ecf3774c3378d42d68c038472c318596e689d30190b43d002b92
6
+ metadata.gz: f619198e4c09da849dbab523854002358b35183d9c1cf13c5a24ae4001a986b6d5c38c5edc8d4ea06412581f4f14080a0abc1628d948409dbf47dc7be5364ee0
7
+ data.tar.gz: bb3060ebe160c24dca44376cab8d5c1cdb3bf377cc47312a1a70d15eaeabee3df045d566d464433f86b0943a24dbd5e2cbfd907a89c21374808defc0a054de72
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/solidusio/solidus_support/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/solidusio/solidus_support/tree/main)
2
+
1
3
  # SolidusSupport
2
4
 
3
5
  This gem contains common runtime functionality for Solidus extensions.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/deprecation"
4
+ require "flickwerk"
4
5
 
5
6
  module SolidusSupport
6
7
  module EngineExtensions
@@ -9,6 +10,7 @@ module SolidusSupport
9
10
 
10
11
  def self.included(engine)
11
12
  engine.extend ClassMethods
13
+ engine.include Flickwerk
12
14
 
13
15
  engine.class_eval do
14
16
  solidus_decorators_root.glob('*') do |decorators_folder|
@@ -27,6 +29,25 @@ module SolidusSupport
27
29
  module ClassMethods
28
30
  def activate
29
31
  load_solidus_decorators_from(solidus_decorators_root)
32
+ load_solidus_subscribers_from(solidus_subscribers_root)
33
+ end
34
+
35
+ # Loads Solidus event subscriber files.
36
+ #
37
+ # This allows to add event subscribers to extensions without explicitly subscribing them,
38
+ # similarly to what happens in Solidus core.
39
+ def load_solidus_subscribers_from(path)
40
+ if SolidusSupport::LegacyEventCompat.using_legacy?
41
+ path.glob("**/*_subscriber.rb") do |subscriber_path|
42
+ require_dependency(subscriber_path)
43
+ end
44
+
45
+ if Spree::Event.respond_to?(:activate_all_subscribers)
46
+ Spree::Event.activate_all_subscribers
47
+ else
48
+ Spree::Event.subscribers.each(&:subscribe!)
49
+ end
50
+ end
30
51
  end
31
52
 
32
53
  # Loads decorator files.
@@ -83,7 +104,7 @@ module SolidusSupport
83
104
  # by those gems, we work around those gems by adding our paths before
84
105
  # `initialize_cache`, which is the Rails initializer called before
85
106
  # `set_load_path`.
86
- initializer "#{name}_#{engine}_paths", before: :initialize_cache do
107
+ initializer "#{engine_name}_#{engine}_paths", before: :initialize_cache do
87
108
  if SolidusSupport.send(:"#{engine}_available?")
88
109
  paths['app/controllers'] << "lib/controllers/#{engine}"
89
110
  paths['app/views'] << "lib/views/#{engine}"
@@ -92,9 +113,11 @@ module SolidusSupport
92
113
 
93
114
  if SolidusSupport.send(:"#{engine}_available?")
94
115
  decorators_path = root.join("lib/decorators/#{engine}")
116
+ patches_path = root.join("lib/patches/#{engine}")
95
117
  controllers_path = root.join("lib/controllers/#{engine}")
96
118
  components_path = root.join("lib/components/#{engine}")
97
119
  config.autoload_paths += decorators_path.glob('*')
120
+ config.autoload_paths += patches_path.glob("*")
98
121
  config.autoload_paths << controllers_path if controllers_path.exist?
99
122
  config.autoload_paths << components_path if components_path.exist?
100
123
 
@@ -105,6 +128,30 @@ module SolidusSupport
105
128
  end
106
129
  end
107
130
  end
131
+
132
+ initializer "#{engine_name}_#{engine}_patch_paths" do
133
+ patch_paths = root.join("lib/patches/#{engine}").glob("*")
134
+ Flickwerk.patch_paths += patch_paths
135
+ end
136
+
137
+ initializer "#{engine_name}_#{engine}_user_patches" do |app|
138
+ app.reloader.to_prepare do
139
+ Flickwerk.aliases["Spree.user_class"] = Spree.user_class_name
140
+ end
141
+ end
142
+
143
+ initializer "eager_load_#{engine_name}_#{engine}_patches" do |app|
144
+ # Solidus versions < 4.5 `require` some of their application code.
145
+ # This leads to hard-to-debug problems with Flickwerk patches.
146
+ # What this does is eager-load all the patches in a `to_prepare`
147
+ # hook by constantizing them.
148
+ # You can override this behavior by setting the environment variable `SOLIDUS_LAZY_LOAD_PATCHES`.
149
+ if Spree.solidus_gem_version < Gem::Version.new("4.5.0.a") && !ENV["SOLIDUS_LAZY_LOAD_PATCHES"]
150
+ app.reloader.to_prepare do
151
+ Flickwerk.patches.each_value { _1.each(&:constantize) }
152
+ end
153
+ end
154
+ end
108
155
  end
109
156
  end
110
157
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusSupport
4
+ module LegacyEventCompat
5
+ # Compatibility for some event-driven operations
6
+ module Bus
7
+ # Publication of an event
8
+ #
9
+ # If extensions want to support the legacy sytem, they need to use a
10
+ # compatible API. That means it's not possible to publish an instance as
11
+ # event, which is something supported by Omnes but not the legacy adapter.
12
+ # Instead, a payload can be given. E.g.:
13
+ #
14
+ # ```
15
+ # SolidusSupport::LegacyEventCompat::Bus.publish(:foo, bar: :baz)
16
+ # ```
17
+ #
18
+ # Legacy subscribers will receive an
19
+ # `ActiveSupport::Notifications::Fanout`, while omnes subscribers will get
20
+ # an `Omnes::UnstructuredEvent`. Both instances are compatible as they
21
+ # implement a `#payload` method.
22
+ #
23
+ # @param event_name [Symbol]
24
+ # @param payload [Hash<Symbol, Any>]
25
+ def self.publish(event_name, **payload)
26
+ SolidusSupport.deprecator.warn(
27
+ "SolidusSupport::LegacyEventCompat::Bus is deprecated and will be removed in solidus_support 1.0." \
28
+ " Please use Spree::Bus.publish instead."
29
+ )
30
+ if SolidusSupport::LegacyEventCompat.using_legacy?
31
+ Spree::Event.fire(event_name, payload)
32
+ else
33
+ Spree::Bus.publish(event_name, **payload, caller_location: caller_locations(1)[0])
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "omnes"
5
+ rescue LoadError
6
+ end
7
+
8
+ module SolidusSupport
9
+ module LegacyEventCompat
10
+ # Compatibility for subscriber modules
11
+ #
12
+ # Thanks to this module, extensions can create legacy subscriber modules
13
+ # (see {Spree::Event::Subscriber}) and translate them automatically to an
14
+ # {Omnes::Subscriber}). E.g.:
15
+ #
16
+ # ```
17
+ # module MyExtension
18
+ # module MySubscriber
19
+ # include Spree::Event::Subscriber
20
+ # include SolidusSupport::LegacyEventCompat::Subscriber
21
+ #
22
+ # event_action :order_finalized
23
+ #
24
+ # def order_finalized(event)
25
+ # event.payload[:order].do_something
26
+ # end
27
+ # end
28
+ # end
29
+ #
30
+ # MyExtension::MySubscriber.omnes_subscriber.subscribe_to(Spree::Bus)
31
+ # ```
32
+ #
33
+ # The generated omnes subscriptions will call the corresponding legacy
34
+ # subscriber method with the omnes event. It'll compatible as long as the
35
+ # omnes event responds to the `#payload` method (see
36
+ # {Omnes::UnstructuredEvent}).
37
+ module Subscriber
38
+ # @api private
39
+ ADAPTER = lambda do |legacy_subscriber, legacy_subscriber_method, _omnes_subscriber, omnes_event|
40
+ legacy_subscriber.send(legacy_subscriber_method, omnes_event)
41
+ end
42
+
43
+ def self.included(legacy_subscriber)
44
+ SolidusSupport.deprecator.warn(
45
+ "SolidusSupport::LegacyEventCompat::Subscriber is deprecated and will be removed in solidus_support 1.0." \
46
+ " Please `include Omnes::Subscriber` in `#{legacy_subscriber.name}` instead."
47
+ )
48
+ legacy_subscriber.define_singleton_method(:omnes_subscriber) do
49
+ @omnes_subscriber ||= Class.new.include(::Omnes::Subscriber).tap do |subscriber|
50
+ legacy_subscriber.event_actions.each do |(legacy_subscriber_method, event_name)|
51
+ subscriber.handle(event_name.to_sym, with: ADAPTER.curry[legacy_subscriber, legacy_subscriber_method])
52
+ end
53
+ end.new
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_support/legacy_event_compat/bus'
4
+ require 'solidus_support/legacy_event_compat/subscriber'
5
+
6
+ module SolidusSupport
7
+ # Compatibility middleman for {Spree::Event} and {Spree::Bus}
8
+ #
9
+ # Solidus v3.2 changed to use [Omnes](https://github.com/nebulab/omnes) as the
10
+ # backbone for event-driven behavior (see {Spree::Bus}) by default. Before
11
+ # that, a custom adapter based on {ActiveSupport::Notifications} was used (see
12
+ # {Spree::Event}. Both systems are still supported on v3.2.
13
+ #
14
+ # This module provides compatibility support so that extensions can easily
15
+ # target both systems regardless of the underlying circumstances:
16
+ #
17
+ # - Solidus v3.2 with the new system.
18
+ # - Solidus v3.2 with the legacy system.
19
+ # - Solidus v2.9 to v3.1, when only {Spree::Event} existed.
20
+ # - Possible future versions of Solidus, whether the legacy system is
21
+ # eventually removed or not.
22
+ module LegacyEventCompat
23
+ # Returns whether the application is using the legacy event system
24
+ #
25
+ # @return [Boolean]
26
+ def self.using_legacy?
27
+ legacy_present? &&
28
+ (legacy_alone? ||
29
+ legacy_chosen?)
30
+ end
31
+
32
+ def self.legacy_present?
33
+ defined?(Spree::Event)
34
+ end
35
+ private_class_method :legacy_present?
36
+
37
+ def self.legacy_alone?
38
+ !Spree::Config.respond_to?(:use_legacy_events)
39
+ end
40
+ private_class_method :legacy_alone?
41
+
42
+ def self.legacy_chosen?
43
+ Spree::Config.use_legacy_events
44
+ end
45
+ private_class_method :legacy_chosen?
46
+ end
47
+ end
@@ -3,15 +3,10 @@
3
3
  module SolidusSupport
4
4
  module Migration
5
5
  def self.[](version)
6
- if Rails.gem_version >= Gem::Version.new('5.x')
7
- ActiveRecord::Migration[version]
8
- else
9
- # Rails < 5 doesn't support specifying rails version of migrations, but
10
- # it _is_ rails 4.2, so we can use that when requested.
11
- return ActiveRecord::Migration if version.to_s == '4.2'
12
-
13
- raise ArgumentError, "Unknown migration version '#{version}'; expected one of '4.2'"
14
- end
6
+ SolidusSupport.deprecator.warn(
7
+ "SolidusSupport::Migration[#{version}] is deprecated. Please use ActiveRecord::Migration[#{version}] instead."
8
+ )
9
+ ActiveRecord::Migration[version]
15
10
  end
16
11
  end
17
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusSupport
4
- VERSION = '0.12.0'
4
+ VERSION = '0.14.0'
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'solidus_support/version'
4
4
  require 'solidus_support/deprecator'
5
5
  require 'solidus_support/migration'
6
+ require 'solidus_support/legacy_event_compat'
6
7
  require 'solidus_support/engine_extensions'
7
8
  require 'solidus_core'
8
9
 
@@ -28,6 +28,9 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ["lib"]
30
30
 
31
+ spec.add_dependency 'flickwerk', '~> 0.3.4'
32
+ spec.add_dependency 'solidus_core', '~> 4.1'
33
+
31
34
  spec.add_development_dependency 'rails'
32
35
  spec.add_development_dependency 'bundler'
33
36
  spec.add_development_dependency 'rake'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe SolidusSupport::LegacyEventCompat::Bus do
4
+ describe '#publish' do
5
+ if SolidusSupport::LegacyEventCompat.using_legacy?
6
+ it 'forwards to Spree::Event' do
7
+ box = nil
8
+ subscription = Spree::Event.subscribe(:foo) { |event| box = event.payload[:bar] }
9
+
10
+ described_class.publish(:foo, bar: :baz)
11
+
12
+ expect(box).to be(:baz)
13
+ ensure
14
+ Spree::Event.unsubscribe(subscription)
15
+ end
16
+ else
17
+ it 'forwards to Spree::Bus' do
18
+ box = nil
19
+ Spree::Bus.register(:foo)
20
+ subscription = Spree::Bus.subscribe(:foo) { |event| box = event.payload[:bar] }
21
+
22
+ described_class.publish(:foo, bar: :baz)
23
+
24
+ expect(box).to be(:baz)
25
+ ensure
26
+ Spree::Bus.unsubscribe(subscription)
27
+ Spree::Bus.registry.unregister(:foo)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omnes'
4
+
5
+ RSpec.describe SolidusSupport::LegacyEventCompat::Subscriber, if: Spree.solidus_version < Gem::Version.new("4.0.0.dev") do
6
+ subject { Module.new.include(Spree::Event::Subscriber).include(described_class) }
7
+
8
+ describe '#omnes_subscriber' do
9
+ it 'returns an Omnes::Subscriber' do
10
+ subject.module_eval do
11
+ event_action :foo
12
+
13
+ def foo(_event); end
14
+ end
15
+
16
+ expect(subject.omnes_subscriber.is_a?(Omnes::Subscriber)).to be(true)
17
+ end
18
+
19
+ it 'adds single-event definitions matching legacy event actions' do
20
+ subject.module_eval do
21
+ event_action :foo
22
+
23
+ def foo(_event); end
24
+ end
25
+ bus = Omnes::Bus.new
26
+ bus.register(:foo)
27
+
28
+ subscriptions = subject.omnes_subscriber.subscribe_to(bus)
29
+
30
+ event = Struct.new(:omnes_event_name).new(:foo)
31
+ expect(subscriptions.first.matches?(event)).to be(true)
32
+ end
33
+
34
+ it 'coerces event names given as Strings' do
35
+ subject.module_eval do
36
+ event_action 'foo'
37
+
38
+ def foo(_event); end
39
+ end
40
+ bus = Omnes::Bus.new
41
+ bus.register(:foo)
42
+
43
+ subscriptions = subject.omnes_subscriber.subscribe_to(bus)
44
+
45
+ event = Struct.new(:omnes_event_name).new(:foo)
46
+ expect(subscriptions.first.matches?(event)).to be(true)
47
+ end
48
+
49
+ it 'executes legacy event action methods as handlers with the omnes event' do
50
+ subject.module_eval do
51
+ event_action :foo
52
+
53
+ def foo(event)
54
+ event[:bar]
55
+ end
56
+ end
57
+ bus = Omnes::Bus.new
58
+ bus.register(:foo)
59
+
60
+ subscriptions = subject.omnes_subscriber.subscribe_to(bus)
61
+
62
+ expect(
63
+ bus.publish(:foo, bar: :baz).executions.first.result
64
+ ).to be(:baz)
65
+ end
66
+
67
+ it 'distingish when event name is given explicitly' do
68
+ subject.module_eval do
69
+ event_action :foo, event_name: :bar
70
+
71
+ def foo(_event)
72
+ :bar
73
+ end
74
+ end
75
+ bus = Omnes::Bus.new
76
+ bus.register(:bar)
77
+
78
+ subscriptions = subject.omnes_subscriber.subscribe_to(bus)
79
+
80
+ expect(
81
+ bus.publish(:bar).executions.first.result
82
+ ).to be(:bar)
83
+ end
84
+
85
+ it "returns the same omnes subscriber instance if called again" do
86
+ expect(subject.omnes_subscriber).to be(subject.omnes_subscriber)
87
+ end
88
+
89
+ it "doesn't fail when no event action has been defined" do
90
+ expect { subject.omnes_subscriber }.not_to raise_error
91
+ end
92
+ end
93
+ end
@@ -14,9 +14,6 @@ module DummyApp
14
14
  class Application < ::Rails::Application
15
15
  config.eager_load = false
16
16
  config.paths['config/database'] = File.expand_path('dummy_app/database.yml', __dir__)
17
- if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR < 1
18
- config.active_record.legacy_connection_handling = false
19
- end
20
17
  end
21
18
  end
22
19
 
metadata CHANGED
@@ -1,16 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
8
8
  - Solidus Team
9
- autorequire:
10
9
  bindir: exe
11
10
  cert_chain: []
12
- date: 2024-12-17 00:00:00.000000000 Z
11
+ date: 2025-02-11 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: flickwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: solidus_core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.1'
14
41
  - !ruby/object:Gem::Dependency
15
42
  name: rails
16
43
  requirement: !ruby/object:Gem::Requirement
@@ -123,7 +150,6 @@ dependencies:
123
150
  - - "~>"
124
151
  - !ruby/object:Gem::Version
125
152
  version: 0.2.2
126
- description:
127
153
  email: contact@solidus.io
128
154
  executables: []
129
155
  extensions: []
@@ -146,9 +172,14 @@ files:
146
172
  - lib/solidus_support.rb
147
173
  - lib/solidus_support/deprecator.rb
148
174
  - lib/solidus_support/engine_extensions.rb
175
+ - lib/solidus_support/legacy_event_compat.rb
176
+ - lib/solidus_support/legacy_event_compat/bus.rb
177
+ - lib/solidus_support/legacy_event_compat/subscriber.rb
149
178
  - lib/solidus_support/migration.rb
150
179
  - lib/solidus_support/version.rb
151
180
  - solidus_support.gemspec
181
+ - spec/solidus_support/legacy_event_compat/bus_spec.rb
182
+ - spec/solidus_support/legacy_event_compat/legacy_event_compat_spec.rb
152
183
  - spec/solidus_support_spec.rb
153
184
  - spec/spec_helper.rb
154
185
  - spec/support/dummy_app.rb
@@ -160,7 +191,6 @@ metadata:
160
191
  homepage_uri: https://github.com/solidusio/solidus_support
161
192
  source_code_uri: https://github.com/solidusio/solidus_support
162
193
  changelog_uri: https://github.com/solidusio/solidus_support/releases
163
- post_install_message:
164
194
  rdoc_options: []
165
195
  require_paths:
166
196
  - lib
@@ -175,11 +205,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
205
  - !ruby/object:Gem::Version
176
206
  version: '0'
177
207
  requirements: []
178
- rubygems_version: 3.5.22
179
- signing_key:
208
+ rubygems_version: 3.6.3
180
209
  specification_version: 4
181
210
  summary: Common runtime helpers for Solidus extensions.
182
211
  test_files:
212
+ - spec/solidus_support/legacy_event_compat/bus_spec.rb
213
+ - spec/solidus_support/legacy_event_compat/legacy_event_compat_spec.rb
183
214
  - spec/solidus_support_spec.rb
184
215
  - spec/spec_helper.rb
185
216
  - spec/support/dummy_app.rb