diff --git a/core/lib/spree/preferences/static_model_preferences.rb b/core/lib/spree/preferences/static_model_preferences.rb index 6b213d801a6..dd5dfdbce33 100644 --- a/core/lib/spree/preferences/static_model_preferences.rb +++ b/core/lib/spree/preferences/static_model_preferences.rb @@ -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) @@ -27,20 +22,29 @@ def []=(key, value) def to_hash @preferences.deep_dup end + + delegate :keys, to: :@preferences end def initialize - @store = Hash.new do |data, klass| - data[klass] = {} - end + @store = {} end def add(klass, name, preferences) - @store[klass.to_s][name] = Definition.new(klass, preferences) + @store[klass.to_s] ||= {} + @store[klass.to_s][name] = Definition.new(klass.to_s, preferences) end def for_class(klass) - @store[klass.to_s] + (@store[klass.to_s] || {}).tap do |names_with_prefs| + names_with_prefs.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.to_sentence} (expected keys: #{klass_keys.to_sentence})" + end + end end end end diff --git a/core/spec/models/spree/preferences/static_model_preferences_spec.rb b/core/spec/models/spree/preferences/static_model_preferences_spec.rb index 9781a12d0f6..1c3e6f9c086 100644 --- a/core/spec/models/spree/preferences/static_model_preferences_spec.rb +++ b/core/spec/models/spree/preferences/static_model_preferences_spec.rb @@ -32,9 +32,13 @@ module Spree end it "errors assigning invalid preferences" do + subject.add(preference_class, 'my_definition', { ice_cream: 'chocolate' }) + expect { - subject.add(preference_class, 'my_definition', { ice_cream: 'chocolate' }) - }.to raise_error(/\APreference :ice_cream is not defined/) + subject.for_class(preference_class) + }.to raise_error( + /\AUnexpected keys found for #{Regexp.escape preference_class.to_s} under my_definition: ice_cream \(expected keys: color\)/ + ) end context "with stored definitions" do