Bring configuration and preferences code from spree_core

This commit is contained in:
Luis Ramos
2020-08-06 11:39:09 +01:00
parent 54a51a4995
commit 8b42543ca3
11 changed files with 1114 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
# This is the primary location for defining spree preferences
#
# The expectation is that this is created once and stored in
# the spree environment
#
# setters:
# a.color = :blue
# a[:color] = :blue
# a.set :color = :blue
# a.preferred_color = :blue
#
# getters:
# a.color
# a[:color]
# a.get :color
# a.preferred_color
#
require "spree/core/search/base"
module Spree
class AppConfiguration < Preferences::Configuration
# Alphabetized to more easily lookup particular preferences
preference :address_requires_state, :boolean, default: true # should state/state_name be required
preference :admin_interface_logo, :string, default: 'logo/spree_50.png'
preference :admin_products_per_page, :integer, default: 10
preference :allow_backorder_shipping, :boolean, default: false # should only be true if you don't need to track inventory
preference :allow_checkout_on_gateway_error, :boolean, default: false
preference :allow_guest_checkout, :boolean, default: true
preference :allow_ssl_in_development_and_test, :boolean, default: false
preference :allow_ssl_in_production, :boolean, default: true
preference :allow_ssl_in_staging, :boolean, default: true
preference :alternative_billing_phone, :boolean, default: false # Request extra phone for bill addr
preference :alternative_shipping_phone, :boolean, default: false # Request extra phone for ship addr
preference :always_put_site_name_in_title, :boolean, default: true
preference :auto_capture, :boolean, default: false # automatically capture the credit card (as opposed to just authorize and capture later)
preference :check_for_spree_alerts, :boolean, default: true
preference :checkout_zone, :string, default: nil # replace with the name of a zone if you would like to limit the countries
preference :company, :boolean, default: false # Request company field for billing and shipping addr
preference :currency, :string, default: "USD"
preference :currency_decimal_mark, :string, default: "."
preference :currency_symbol_position, :string, default: "before"
preference :currency_thousands_separator, :string, default: ","
preference :display_currency, :boolean, default: false
preference :default_country_id, :integer
preference :default_meta_description, :string, default: 'Spree demo site'
preference :default_meta_keywords, :string, default: 'spree, demo'
preference :default_seo_title, :string, default: ''
preference :dismissed_spree_alerts, :string, default: ''
preference :hide_cents, :boolean, default: false
preference :last_check_for_spree_alerts, :string, default: nil
preference :layout, :string, default: 'spree/layouts/spree_application'
preference :logo, :string, default: 'logo/spree_50.png'
preference :max_level_in_taxons_menu, :integer, default: 1 # maximum nesting level in taxons menu
preference :orders_per_page, :integer, default: 15
preference :prices_inc_tax, :boolean, default: false
preference :products_per_page, :integer, default: 12
preference :redirect_https_to_http, :boolean, :default => false
preference :require_master_price, :boolean, default: true
preference :shipment_inc_vat, :boolean, default: false
preference :shipping_instructions, :boolean, default: false # Request instructions/info for shipping
preference :show_only_complete_orders_by_default, :boolean, default: true
preference :show_variant_full_price, :boolean, default: false #Displays variant full price or difference with product price. Default false to be compatible with older behavior
preference :show_products_without_price, :boolean, default: false
preference :show_raw_product_description, :boolean, :default => false
preference :site_name, :string, default: 'Spree Demo Site'
preference :site_url, :string, default: 'demo.spreecommerce.com'
preference :tax_using_ship_address, :boolean, default: true
preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
# Preferences related to image settings
preference :attachment_default_url, :string, default: '/spree/products/:id/:style/:basename.:extension'
preference :attachment_path, :string, default: ':rails_root/public/spree/products/:id/:style/:basename.:extension'
preference :attachment_url, :string, default: '/spree/products/:id/:style/:basename.:extension'
preference :attachment_styles, :string, default: "{\"mini\":\"48x48>\",\"small\":\"100x100>\",\"product\":\"240x240>\",\"large\":\"600x600>\"}"
preference :attachment_default_style, :string, default: 'product'
preference :s3_access_key, :string
preference :s3_bucket, :string
preference :s3_secret, :string
preference :s3_headers, :string, default: "{\"Cache-Control\":\"max-age=31557600\"}"
preference :use_s3, :boolean, default: false # Use S3 for images rather than the file system
preference :s3_protocol, :string
preference :s3_host_alias, :string
# Default mail headers settings
preference :enable_mail_delivery, :boolean, :default => false
preference :mails_from, :string, :default => 'spree@example.com'
preference :mail_bcc, :string, :default => 'spree@example.com'
preference :intercept_email, :string, :default => nil
# Default smtp settings
preference :override_actionmailer_config, :boolean, :default => true
preference :mail_host, :string, :default => 'localhost'
preference :mail_domain, :string, :default => 'localhost'
preference :mail_port, :integer, :default => 25
preference :secure_connection_type, :string, :default => Core::MailSettings::SECURE_CONNECTION_TYPES[0]
preference :mail_auth_type, :string, :default => Core::MailSettings::MAIL_AUTH[0]
preference :smtp_username, :string
preference :smtp_password, :string
# searcher_class allows spree extension writers to provide their own Search class
def searcher_class
@searcher_class ||= Spree::Core::Search::Base
end
def searcher_class=(sclass)
@searcher_class = sclass
end
attr_writer :package_factory, :order_updater_decorator
def package_factory
@package_factory ||= Spree::Stock::Package
end
def order_updater_decorator
@order_updater_decorator ||= NullDecorator
end
end
end

View File

@@ -0,0 +1,35 @@
class Spree::Preference < ActiveRecord::Base
serialize :value
validates :key, presence: true
validates :value_type, presence: true
scope :valid, -> { where(Spree::Preference.arel_table[:key].not_eq(nil)).where(Spree::Preference.arel_table[:value_type].not_eq(nil)) }
# The type conversions here should match
# the ones in spree::preferences::preferrable#convert_preference_value
def value
if self[:value_type].present?
case self[:value_type].to_sym
when :string, :text
self[:value].to_s
when :password
self[:value].to_s
when :decimal
BigDecimal.new(self[:value].to_s).round(2, BigDecimal::ROUND_HALF_UP)
when :integer
self[:value].to_i
when :boolean
(self[:value].to_s =~ /^[t|1]/i) != nil
else
self[:value].is_a?(String) ? YAML.load(self[:value]) : self[:value]
end
else
self[:value]
end
end
def raw_value
self[:value]
end
end

View File

@@ -0,0 +1,71 @@
# This takes the preferrable methods and adds some
# syntatic sugar to access the preferences
#
# class App < Configuration
# preference :color, :string
# end
#
# a = App.new
#
# setters:
# a.color = :blue
# a[:color] = :blue
# a.set :color = :blue
# a.preferred_color = :blue
#
# getters:
# a.color
# a[:color]
# a.get :color
# a.preferred_color
#
#
module Spree::Preferences
class Configuration
include Spree::Preferences::Preferable
def configure
yield(self) if block_given?
end
def preference_cache_key(name)
[ENV['RAILS_CACHE_ID'], self.class.name, name].flatten.join('::').underscore
end
def reset
preferences.each do |name, value|
set_preference name, preference_default(name)
end
end
alias :[] :get_preference
alias :[]= :set_preference
alias :get :get_preference
def set(*args)
options = args.extract_options!
options.each do |name, value|
set_preference name, value
end
if args.size == 2
set_preference args[0], args[1]
end
end
def method_missing(method, *args)
name = method.to_s.gsub('=', '')
if has_preference? name
if method.to_s =~ /=$/
set_preference(name, args.first)
else
get_preference name
end
else
super
end
end
end
end

View File

@@ -0,0 +1,137 @@
# The preference_cache_key is used to determine if the preference
# can be set. The default behavior is to return nil if there is no
# id value. On ActiveRecords, new objects will have their preferences
# saved to a pending hash until it is persisted.
#
# class_attributes are inheritied unless you reassign them in
# the subclass, so when you inherit a Preferable class, the
# inherited hook will assign a new hash for the subclass definitions
# and copy all the definitions allowing the subclass to add
# additional defintions without affecting the base
module Spree::Preferences::Preferable
def self.included(base)
base.class_eval do
extend Spree::Preferences::PreferableClassMethods
if respond_to?(:after_create)
after_create do |obj|
obj.save_pending_preferences
end
end
if respond_to?(:after_destroy)
after_destroy do |obj|
obj.clear_preferences
end
end
end
end
def get_preference(name)
has_preference! name
send self.class.preference_getter_method(name)
end
alias :preferred :get_preference
alias :prefers? :get_preference
def set_preference(name, value)
has_preference! name
send self.class.preference_setter_method(name), value
end
def preference_type(name)
has_preference! name
send self.class.preference_type_getter_method(name)
end
def preference_default(name)
has_preference! name
send self.class.preference_default_getter_method(name)
end
def preference_description(name)
has_preference! name
send self.class.preference_description_getter_method(name)
end
def has_preference!(name)
raise NoMethodError.new "#{name} preference not defined" unless has_preference? name
end
def has_preference?(name)
respond_to? self.class.preference_getter_method(name)
end
def preferences
prefs = {}
methods.grep(/^prefers_.*\?$/).each do |pref_method|
prefs[pref_method.to_s.gsub(/prefers_|\?/, '').to_sym] = send(pref_method)
end
prefs
end
def prefers?(name)
get_preference(name)
end
def preference_cache_key(name)
return unless id
[ENV["RAILS_CACHE_ID"], self.class.name, name, id].join('::').underscore
end
def save_pending_preferences
return unless @pending_preferences
@pending_preferences.each do |name, value|
set_preference(name, value)
end
end
def clear_preferences
preferences.keys.each {|pref| preference_store.delete preference_cache_key(pref)}
end
private
def add_pending_preference(name, value)
@pending_preferences ||= {}
@pending_preferences[name] = value
end
def get_pending_preference(name)
return unless @pending_preferences
@pending_preferences[name]
end
def convert_preference_value(value, type)
case type
when :string, :text
value.to_s
when :password
value.to_s
when :decimal
BigDecimal.new(value.to_s).round(2, BigDecimal::ROUND_HALF_UP)
when :integer
value.to_i
when :boolean
if value.is_a?(FalseClass) ||
value.nil? ||
value == 0 ||
value =~ /^(f|false|0)$/i ||
(value.respond_to? :empty? and value.empty?)
false
else
true
end
else
value
end
end
def preference_store
Spree::Preferences::Store.instance
end
end

View File

@@ -0,0 +1,86 @@
module Spree::Preferences
module PreferableClassMethods
def preference(name, type, *args)
options = args.extract_options!
options.assert_valid_keys(:default, :description)
default = options[:default]
description = options[:description] || name
# cache_key will be nil for new objects, then if we check if there
# is a pending preference before going to default
define_method preference_getter_method(name) do
# perference_cache_key will only be nil/false for new records
#
if preference_cache_key(name)
preference_store.get(preference_cache_key(name), default)
else
get_pending_preference(name) || default
end
end
alias_method prefers_getter_method(name), preference_getter_method(name)
define_method preference_setter_method(name) do |value|
value = convert_preference_value(value, type)
if preference_cache_key(name)
preference_store.set preference_cache_key(name), value, type
else
add_pending_preference(name, value)
end
end
alias_method prefers_setter_method(name), preference_setter_method(name)
define_method preference_default_getter_method(name) do
default
end
define_method preference_type_getter_method(name) do
type
end
define_method preference_description_getter_method(name) do
description
end
end
def remove_preference(name)
remove_method preference_getter_method(name) if method_defined? preference_getter_method(name)
remove_method preference_setter_method(name) if method_defined? preference_setter_method(name)
remove_method prefers_getter_method(name) if method_defined? prefers_getter_method(name)
remove_method prefers_setter_method(name) if method_defined? prefers_setter_method(name)
remove_method preference_default_getter_method(name) if method_defined? preference_default_getter_method(name)
remove_method preference_type_getter_method(name) if method_defined? preference_type_getter_method(name)
remove_method preference_description_getter_method(name) if method_defined? preference_description_getter_method(name)
end
def preference_getter_method(name)
"preferred_#{name}".to_sym
end
def preference_setter_method(name)
"preferred_#{name}=".to_sym
end
def prefers_getter_method(name)
"prefers_#{name}?".to_sym
end
def prefers_setter_method(name)
"prefers_#{name}=".to_sym
end
def preference_default_getter_method(name)
"preferred_#{name}_default".to_sym
end
def preference_type_getter_method(name)
"preferred_#{name}_type".to_sym
end
def preference_description_getter_method(name)
"preferred_#{name}_description".to_sym
end
end
end

View File

@@ -0,0 +1,98 @@
# Use singleton class Spree::Preferences::Store.instance to access
#
# StoreInstance has a persistence flag that is on by default,
# but we disable database persistence in testing to speed up tests
#
require 'singleton'
module Spree::Preferences
class StoreInstance
attr_accessor :persistence
def initialize
@cache = Rails.cache
@persistence = true
end
def set(key, value, type)
@cache.write(key, value)
persist(key, value, type)
end
def exist?(key)
@cache.exist?(key) ||
should_persist? && Spree::Preference.where(:key => key).exists?
end
def get(key,fallback=nil)
# return the retrieved value, if it's in the cache
# use unless nil? incase the value is actually boolean false
#
unless (val = @cache.read(key)).nil?
return val
end
if should_persist?
# If it's not in the cache, maybe it's in the database, but
# has been cleared from the cache
# does it exist in the database?
if Spree::Preference.table_exists? && preference = Spree::Preference.find_by_key(key)
# it does exist, so let's put it back into the cache
@cache.write(preference.key, preference.value)
# and return the value
return preference.value
end
end
unless fallback.nil?
# cache fallback so we won't hit the db above on
# subsequent queries for the same key
#
@cache.write(key, fallback)
end
return fallback
end
def delete(key)
@cache.delete(key)
destroy(key)
end
def clear_cache
@cache.clear
end
private
def persist(cache_key, value, type)
return unless should_persist?
preference = Spree::Preference.where(:key => cache_key).first_or_initialize
preference.value = value
preference.value_type = type
preference.save
end
def destroy(cache_key)
return unless should_persist?
preference = Spree::Preference.find_by_key(cache_key)
preference.destroy if preference
end
def should_persist?
@persistence && Spree::Preference.connected? && Spree::Preference.table_exists?
end
end
class Store < StoreInstance
include Singleton
end
end

View File

@@ -0,0 +1,61 @@
require 'spec_helper'
describe Spree::AppConfiguration do
let (:prefs) { Rails.application.config.spree.preferences }
it "should be available from the environment" do
prefs.site_name = "TEST SITE NAME"
prefs.site_name.should eq "TEST SITE NAME"
end
it "should be available as Spree::Config for legacy access" do
Spree::Config.site_name = "Spree::Config TEST SITE NAME"
Spree::Config.site_name.should eq "Spree::Config TEST SITE NAME"
end
it "uses base searcher class by default" do
prefs.searcher_class = nil
prefs.searcher_class.should eq Spree::Core::Search::Base
end
it 'uses Spree::Stock::Package by default' do
prefs.package_factory = nil
prefs.package_factory.should eq Spree::Stock::Package
end
context 'when a package factory is specified' do
class TestPackageFactory; end
around do |example|
default_factory = prefs.package_factory
example.run
prefs.package_factory = default_factory
end
it 'uses the set package factory' do
prefs.package_factory = TestPackageFactory
prefs.package_factory.should eq TestPackageFactory
end
end
it 'uses Spree::NullDecorator by default' do
prefs.order_updater_decorator = nil
prefs.order_updater_decorator.should eq Spree::NullDecorator
end
context 'when an order_updater_decorator is specified' do
class FakeOrderUpdaterDecorator; end
around do |example|
default_decorator = prefs.order_updater_decorator
example.run
prefs.order_updater_decorator = default_decorator
end
it 'uses the set order_updater_decorator' do
prefs.order_updater_decorator = FakeOrderUpdaterDecorator
prefs.order_updater_decorator.should eq FakeOrderUpdaterDecorator
end
end
end

View File

@@ -0,0 +1,98 @@
require 'spec_helper'
describe Spree::Preference do
it "should require a key" do
@preference = Spree::Preference.new
@preference.key = :test
@preference.value_type = :boolean
@preference.value = true
@preference.should be_valid
end
describe "type coversion for values" do
def round_trip_preference(key, value, value_type)
p = Spree::Preference.new
p.value = value
p.value_type = value_type
p.key = key
p.save
Spree::Preference.find_by_key(key)
end
it ":boolean" do
value_type = :boolean
value = true
key = "boolean_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it "false :boolean" do
value_type = :boolean
value = false
key = "boolean_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":integer" do
value_type = :integer
value = 10
key = "integer_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":decimal" do
value_type = :decimal
value = 1.5
key = "decimal_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":string" do
value_type = :string
value = "This is a string"
key = "string_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":text" do
value_type = :text
value = "This is a string stored as text"
key = "text_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":password" do
value_type = :password
value = "This is a password"
key = "password_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
it ":any" do
value_type = :any
value = [1, 2]
key = "any_key"
pref = round_trip_preference(key, value, value_type)
pref.value.should eq value
pref.value_type.should == value_type.to_s
end
end
end

View File

@@ -0,0 +1,30 @@
require 'spec_helper'
describe Spree::Preferences::Configuration do
before :all do
class AppConfig < Spree::Preferences::Configuration
preference :color, :string, :default => :blue
end
@config = AppConfig.new
end
it "has named methods to access preferences" do
@config.color = 'orange'
@config.color.should eq 'orange'
end
it "uses [ ] to access preferences" do
@config[:color] = 'red'
@config[:color].should eq 'red'
end
it "uses set/get to access preferences" do
@config.set :color, 'green'
@config.get(:color).should eq 'green'
end
end

View File

@@ -0,0 +1,331 @@
require 'spec_helper'
describe Spree::Preferences::Preferable do
before :all do
class A
include Spree::Preferences::Preferable
attr_reader :id
def initialize
@id = rand(999)
end
preference :color, :string, :default => 'green', :description => "My Favorite Color"
end
class B < A
preference :flavor, :string
end
end
before :each do
@a = A.new
@a.stub(:persisted? => true)
@b = B.new
@b.stub(:persisted? => true)
# ensure we're persisting as that is the default
#
store = Spree::Preferences::Store.instance
store.persistence = true
end
describe "preference definitions" do
it "parent should not see child definitions" do
@a.has_preference?(:color).should be_true
@a.has_preference?(:flavor).should_not be_true
end
it "child should have parent and own definitions" do
@b.has_preference?(:color).should be_true
@b.has_preference?(:flavor).should be_true
end
it "instances have defaults" do
@a.preferred_color.should eq 'green'
@b.preferred_color.should eq 'green'
@b.preferred_flavor.should be_nil
end
it "can be asked if it has a preference definition" do
@a.has_preference?(:color).should be_true
@a.has_preference?(:bad).should be_false
end
it "can be asked and raises" do
expect {
@a.has_preference! :flavor
}.to raise_error(NoMethodError, "flavor preference not defined")
end
it "has a type" do
@a.preferred_color_type.should eq :string
@a.preference_type(:color).should eq :string
end
it "has a default" do
@a.preferred_color_default.should eq 'green'
@a.preference_default(:color).should eq 'green'
end
it "has a description" do
@a.preferred_color_description.should eq "My Favorite Color"
@a.preference_description(:color).should eq "My Favorite Color"
end
it "raises if not defined" do
expect {
@a.get_preference :flavor
}.to raise_error(NoMethodError, "flavor preference not defined")
end
end
describe "preference access" do
it "handles ghost methods for preferences" do
@a.preferred_color = 'blue'
@a.preferred_color.should eq 'blue'
@a.prefers_color = 'green'
@a.prefers_color?.should eq 'green'
end
it "has genric readers" do
@a.preferred_color = 'red'
@a.prefers?(:color).should eq 'red'
@a.preferred(:color).should eq 'red'
end
it "parent and child instances have their own prefs" do
@a.preferred_color = 'red'
@b.preferred_color = 'blue'
@a.preferred_color.should eq 'red'
@b.preferred_color.should eq 'blue'
end
it "raises when preference not defined" do
expect {
@a.set_preference(:bad, :bone)
}.to raise_exception(NoMethodError, "bad preference not defined")
end
it "builds a hash of preferences" do
@b.preferred_flavor = :strawberry
@b.preferences[:flavor].should eq 'strawberry'
@b.preferences[:color].should eq 'green' #default from A
end
context "database fallback" do
before do
@a.instance_variable_set("@pending_preferences", {})
end
it "retrieves a preference from the database before falling back to default" do
preference = double(:value => "chatreuse", :key => 'a/color/123')
Spree::Preference.should_receive(:find_by_key).and_return(preference)
@a.preferred_color.should == 'chatreuse'
end
it "defaults if no database key exists" do
Spree::Preference.should_receive(:find_by_key).and_return(nil)
@a.preferred_color.should == 'green'
end
end
context "converts integer preferences to integer values" do
before do
A.preference :is_integer, :integer
end
it "with strings" do
@a.set_preference(:is_integer, '3')
@a.preferences[:is_integer].should == 3
@a.set_preference(:is_integer, '')
@a.preferences[:is_integer].should == 0
end
end
context "converts decimal preferences to BigDecimal values" do
before do
A.preference :if_decimal, :decimal
end
it "returns a BigDecimal" do
@a.set_preference(:if_decimal, 3.3)
@a.preferences[:if_decimal].class.should == BigDecimal
end
it "with strings" do
@a.set_preference(:if_decimal, '3.3')
@a.preferences[:if_decimal].should == 3.3
@a.set_preference(:if_decimal, '')
@a.preferences[:if_decimal].should == 0.0
end
end
context "converts boolean preferences to boolean values" do
before do
A.preference :is_boolean, :boolean, :default => true
end
it "with strings" do
@a.set_preference(:is_boolean, '0')
@a.preferences[:is_boolean].should be_false
@a.set_preference(:is_boolean, 'f')
@a.preferences[:is_boolean].should be_false
@a.set_preference(:is_boolean, 't')
@a.preferences[:is_boolean].should be_true
end
it "with integers" do
@a.set_preference(:is_boolean, 0)
@a.preferences[:is_boolean].should be_false
@a.set_preference(:is_boolean, 1)
@a.preferences[:is_boolean].should be_true
end
it "with an empty string" do
@a.set_preference(:is_boolean, '')
@a.preferences[:is_boolean].should be_false
end
it "with an empty hash" do
@a.set_preference(:is_boolean, [])
@a.preferences[:is_boolean].should be_false
end
end
context "converts any preferences to any values" do
before do
A.preference :product_ids, :any, :default => []
A.preference :product_attributes, :any, :default => {}
end
it "with array" do
@a.preferences[:product_ids].should == []
@a.set_preference(:product_ids, [1, 2])
@a.preferences[:product_ids].should == [1, 2]
end
it "with hash" do
@a.preferences[:product_attributes].should == {}
@a.set_preference(:product_attributes, {:id => 1, :name => 2})
@a.preferences[:product_attributes].should == {:id => 1, :name => 2}
end
end
end
describe "persisted preferables" do
before(:all) do
class CreatePrefTest < ActiveRecord::Migration
def self.up
create_table :pref_tests do |t|
t.string :col
end
end
def self.down
drop_table :pref_tests
end
end
@migration_verbosity = ActiveRecord::Migration.verbose
ActiveRecord::Migration.verbose = false
CreatePrefTest.migrate(:up)
class PrefTest < ActiveRecord::Base
preference :pref_test_pref, :string, :default => 'abc'
preference :pref_test_any, :any, :default => []
end
end
after(:all) do
CreatePrefTest.migrate(:down)
ActiveRecord::Migration.verbose = @migration_verbosity
end
before(:each) do
@pt = PrefTest.create
end
describe "pending preferences for new activerecord objects" do
it "saves preferences after record is saved" do
pr = PrefTest.new
pr.set_preference(:pref_test_pref, 'XXX')
pr.get_preference(:pref_test_pref).should == 'XXX'
pr.save!
pr.get_preference(:pref_test_pref).should == 'XXX'
end
it "saves preferences for serialized object" do
pr = PrefTest.new
pr.set_preference(:pref_test_any, [1, 2])
pr.get_preference(:pref_test_any).should == [1, 2]
pr.save!
pr.get_preference(:pref_test_any).should == [1, 2]
end
end
describe "requires a valid id" do
it "for cache_key" do
pref_test = PrefTest.new
pref_test.preference_cache_key(:pref_test_pref).should be_nil
pref_test.save
pref_test.preference_cache_key(:pref_test_pref).should_not be_nil
end
it "but returns default values" do
pref_test = PrefTest.new
pref_test.get_preference(:pref_test_pref).should == 'abc'
end
it "adds prefs in a pending hash until after_create" do
pref_test = PrefTest.new
pref_test.should_receive(:add_pending_preference).with(:pref_test_pref, 'XXX')
pref_test.set_preference(:pref_test_pref, 'XXX')
end
end
it "clear preferences" do
@pt.set_preference(:pref_test_pref, 'xyz')
@pt.preferred_pref_test_pref.should == 'xyz'
@pt.clear_preferences
@pt.preferred_pref_test_pref.should == 'abc'
end
it "clear preferences when record is deleted" do
@pt.save!
@pt.preferred_pref_test_pref = 'lmn'
@pt.save!
@pt.destroy
@pt1 = PrefTest.new(:col => 'aaaa')
@pt1.id = @pt.id
@pt1.save!
@pt1.get_preference(:pref_test_pref).should_not == 'lmn'
@pt1.get_preference(:pref_test_pref).should == 'abc'
end
end
it "builds cache keys" do
@a.preference_cache_key(:color).should match /a\/color\/\d+/
end
it "can add and remove preferences" do
A.preference :test_temp, :boolean, :default => true
@a.preferred_test_temp.should be_true
A.remove_preference :test_temp
@a.has_preference?(:test_temp).should be_false
@a.respond_to?(:preferred_test_temp).should be_false
end
end

View File

@@ -0,0 +1,47 @@
require 'spec_helper'
describe Spree::Preferences::Store do
before :each do
@store = Spree::Preferences::StoreInstance.new
end
it "sets and gets a key" do
@store.set :test, 1, :integer
@store.exist?(:test).should be_true
@store.get(:test).should eq 1
end
it "can set and get false values when cache return nil" do
@store.set :test, false, :boolean
@store.get(:test).should be_false
end
it "will return db value when cache is emtpy and cache the db value" do
preference = Spree::Preference.where(:key => 'test').first_or_initialize
preference.value = '123'
preference.value_type = 'string'
preference.save
Rails.cache.clear
@store.get(:test).should eq '123'
Rails.cache.read(:test).should eq '123'
end
it "should return and cache fallback value when supplied" do
Rails.cache.clear
@store.get(:test, false).should be_false
Rails.cache.read(:test).should be_false
end
it "should return and cache fallback value when persistence is disabled (i.e. during bootstrap)" do
Rails.cache.clear
@store.stub(:should_persist? => false)
@store.get(:test, true).should be_true
Rails.cache.read(:test).should be_true
end
it "should return nil when key can't be found and fallback value is not supplied" do
@store.get(:random_key).should be_nil
end
end