-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Allow safe reloads of the component registry
This adds a new `ComponentRegistry` class that allows: - setting component classes as strings (to allow for easy reloading) - getting nice errors when requesting components that don't exist - getting nice errors when setting a component to a non-existing class It also moves some of the logic from `SolidusAdmin::Configuration` into a separate class. I've decided not to add memoization here as I'm not sure this would make a giant difference performance-wise, and also the Rails Guide on Reloading constants very clearly says: ``` Bottom line: do not cache reloadable classes or modules. ```
Showing
5 changed files
with
80 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
module SolidusAdmin | ||
class ComponentRegistry | ||
ComponentNotFoundError = Class.new(NameError) | ||
|
||
def initialize | ||
@names = {} | ||
end | ||
|
||
def []=(key, value) | ||
@names[key] = value | ||
end | ||
|
||
def [](key) | ||
(@names[key] || "solidus_admin/#{key}/component".classify).constantize | ||
rescue NameError => error | ||
if @names[key] | ||
raise error | ||
else | ||
prefix = "#{SolidusAdmin::Configuration::ENGINE_ROOT}/app/components/solidus_admin/" | ||
suffix = "/component.rb" | ||
dictionary = Dir["#{prefix}**#{suffix}"].map { _1.delete_prefix(prefix).delete_suffix(suffix) } | ||
corrections = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(key.to_s) | ||
|
||
raise ComponentNotFoundError.new( | ||
"Unknown component #{key}#{DidYouMean.formatter.message_for(corrections)}", | ||
key.classify, | ||
receiver: ::SolidusAdmin | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
RSpec.describe SolidusAdmin::ComponentRegistry do | ||
let(:registry) { described_class.new } | ||
let(:key) { "ui/button" } | ||
|
||
subject { registry[key] } | ||
|
||
context "with a default class" do | ||
it { is_expected.to eq(SolidusAdmin::UI::Button::Component) } | ||
end | ||
|
||
context "with a spelling mistake" do | ||
let(:key) { "ui/buton" } | ||
|
||
it "raises an understandable error" do | ||
expect { subject }.to raise_error("Unknown component ui/buton\nDid you mean? ui/button") | ||
end | ||
end | ||
|
||
context "with a custom class" do | ||
before do | ||
# Using an existing class here so I don't have to define a new one. | ||
# Extensions that use this should use their own. | ||
registry["ui/button"] = "SolidusAdmin::UI::Panel::Component" | ||
end | ||
|
||
it { is_expected.to eq(SolidusAdmin::UI::Panel::Component) } | ||
end | ||
|
||
context "with a custom class with a spelling mistake" do | ||
before do | ||
registry["ui/button"] = "DoesNotExistClass" | ||
end | ||
|
||
it "raises an NameError" do | ||
expect { subject }.to raise_error("uninitialized constant DoesNotExistClass") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters