Skip to content

Commit

Permalink
Merge pull request #4967 from nebulab/waiting-for-dev/static_preferen…
Browse files Browse the repository at this point in the history
…ces_string_v31

[v3.1] Allow storing static preferences using string class names
  • Loading branch information
waiting-for-dev authored Mar 7, 2023
2 parents 0cd3541 + fde8460 commit 718468b
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
1 change: 1 addition & 0 deletions core/lib/spree/core/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Engine < ::Rails::Engine

config.after_initialize do
Spree::Config.check_load_defaults_called('Spree::Config')
Spree::Config.static_model_preferences.validate!
end

config.after_initialize do
Expand Down
35 changes: 25 additions & 10 deletions core/lib/spree/preferences/static_model_preferences.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@ class Definition
attr_reader :preferences

def initialize(klass, hash)
hash = hash.symbolize_keys
hash.keys.each do |key|
if !klass.defined_preferences.include?(key)
raise "Preference #{key.inspect} is not defined on #{klass}"
end
end
@preferences = hash
@klass = klass
@preferences = hash.symbolize_keys
end

def fetch(key, &block)
Expand All @@ -27,6 +22,8 @@ def []=(key, value)
def to_hash
@preferences.deep_dup
end

delegate :keys, to: :@preferences
end

def initialize
Expand All @@ -36,14 +33,32 @@ def initialize
end

def add(klass, name, preferences)
# We use class name instead of class to allow reloading in dev
raise "Static model preference '#{name}' on #{klass} is already defined" if @store[klass.to_s][name]
@store[klass.to_s][name] = Definition.new(klass, preferences)
@store[klass.to_s][name] = Definition.new(klass.to_s, preferences)
end

def for_class(klass)
@store[klass.to_s]
end

def validate!
@store.keys.map(&:constantize).each do |klass|
validate_for_class!(klass)
end
end

private

def validate_for_class!(klass)
for_class(klass).each do |name, preferences|
klass_keys = klass.defined_preferences.map(&:to_s)
extra_keys = preferences.keys.map(&:to_s) - klass_keys
next if extra_keys.empty?

raise \
"Unexpected keys found for #{klass} under #{name}: #{extra_keys.sort.join(', ')} " \
"(expected keys: #{klass_keys.sort.join(', ')})"
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ module Spree
expect(definitions).to have_key('my_definition')
end

it "errors assigning invalid preferences" do
expect {
subject.add(preference_class, 'my_definition', { ice_cream: 'chocolate' })
}.to raise_error(/\APreference :ice_cream is not defined/)
it "can replace preferences" do
subject.add(preference_class, 'my_definition', { color: "red" })

subject.add(preference_class, 'my_definition', { color: "blue" })

expect(definitions['my_definition'].fetch(:color)).to eq("blue")
end

context "with stored definitions" do
Expand Down Expand Up @@ -75,5 +77,18 @@ module Spree
expect(subject.for_class(other_class)).to be_empty
end
end

describe '.validate!' do
it "errors assigning invalid preferences" do
stub_const("SomeClass", preference_class)
subject.add(preference_class, 'my_definition', { ice_cream: 'chocolate', spoon: true })

expect {
subject.validate!
}.to raise_error(
/\AUnexpected keys found for SomeClass under my_definition: ice_cream, spoon \(expected keys: color\)/
)
end
end
end
end

0 comments on commit 718468b

Please sign in to comment.