Module: Spree::Preferences::Preferable

Extended by:
ActiveSupport::Concern
Included in:
Configuration
Defined in:
lib/spree/preferences/preferable.rb

Overview

Preferable allows defining preference accessor methods.

A class including Preferable must implement #preferences which should return an object responding to .fetch(key), []=(key, val), and .delete(key). If #preferences is initialized with ‘default_preferences` and one of the preferences is another preference, it will cause a stack level too deep error. To avoid it do not memoize #preferences.

It may also define a ‘#context_for_default` method. It should return an array with the arguments to be provided to a proc used as the `default:` keyword for a preference.

The generated writer method performs typecasting before assignment into the preferences object.

Examples:

# Spree::Base includes Preferable and defines preferences as a serialized
# column.
class Settings < Spree::Base
  preference :color,       :string,  default: 'red'
  preference :temperature, :integer, default: 21
end

s = Settings.new
s.preferred_color # => 'red'
s.preferred_temperature # => 21

s.preferred_color = 'blue'
s.preferred_color # => 'blue'

# Typecasting is performed on assignment
s.preferred_temperature = '24'
s.preferred_color # => 24

# Modifications have been made to the .preferences hash
s.preferences #=> {color: 'blue', temperature: 24}

# Save the changes. All handled by activerecord
s.save!

Each preference gets rendered as a form field in Solidus backend.

As not all supported preference types are representable as a form field, only some of them get rendered per default. Arrays and Hashes for instance are supported preference field types, but do not represent well as a form field.

Overwrite allowed_admin_form_preference_types in your class if you want to provide more fields. If you do so, you also need to provide a preference field partial that lives in:

app/views/spree/admin/shared/preference_fields/

Instance Method Summary collapse

Instance Method Details

#admin_form_preference_namesArray

Preference names representable as form fields in Solidus backend

Not all preferences are representable as a form field.

Arrays and Hashes for instance are supported preference field types, but do not represent well as a form field.

As these kind of preferences are mostly developer facing and not admin facing we should not render them.

Overwrite allowed_admin_form_preference_types in your class that includes Spree::Preferable if you want to provide more fields. If you do so, you also need to provide a preference field partial that lives in:

app/views/spree/admin/shared/preference_fields/

Returns:

  • (Array)


145
146
147
148
149
# File 'lib/spree/preferences/preferable.rb', line 145

def admin_form_preference_names
  defined_preferences.keep_if do |type|
    preference_type(type).in? self.class.allowed_admin_form_preference_types
  end
end

#default_preferencesHash{Symbol => Object}

This may raise an infinite loop error if any of the defaults are dependent on other preferences defaults.

Returns:

  • (Hash{Symbol => Object})

    Default for all preferences defined on this class



119
120
121
122
123
124
125
# File 'lib/spree/preferences/preferable.rb', line 119

def default_preferences
  Hash[
    defined_preferences.map do |preference|
      [preference, preference_default(preference)]
    end
  ]
end

#defined_preferencesArray<Symbol>

Returns All preferences defined on this class.

Returns:

  • (Array<Symbol>)

    All preferences defined on this class



112
113
114
# File 'lib/spree/preferences/preferable.rb', line 112

def defined_preferences
  self.class.defined_preferences
end

#get_preference(name) ⇒ Object

Get a preference

Parameters:

  • name (#to_sym)

    name of preference

Returns:

  • (Object)

    The value of preference name



72
73
74
75
# File 'lib/spree/preferences/preferable.rb', line 72

def get_preference(name)
  has_preference! name
  send self.class.preference_getter_method(name)
end

#has_preference!(name) ⇒ Object

Raises an exception if the name preference is not defined on this class

Parameters:

  • name (#to_sym)

    name of preference



101
102
103
# File 'lib/spree/preferences/preferable.rb', line 101

def has_preference!(name)
  raise NoMethodError.new "#{name} preference not defined" unless has_preference? name
end

#has_preference?(name) ⇒ Boolean

Returns if preference exists on this class.

Parameters:

  • name (#to_sym)

    name of preference

Returns:

  • (Boolean)

    if preference exists on this class



107
108
109
# File 'lib/spree/preferences/preferable.rb', line 107

def has_preference?(name)
  defined_preferences.include?(name.to_sym)
end

#preference_default(name) ⇒ Object

Returns The default for preference name.

Parameters:

  • name (#to_sym)

    name of preference

Returns:

  • (Object)

    The default for preference name



94
95
96
97
# File 'lib/spree/preferences/preferable.rb', line 94

def preference_default(name)
  has_preference! name
  send self.class.preference_default_getter_method(name)
end

#preference_type(name) ⇒ Symbol

Returns The type of preference name.

Parameters:

  • name (#to_sym)

    name of preference

Returns:

  • (Symbol)

    The type of preference name



87
88
89
90
# File 'lib/spree/preferences/preferable.rb', line 87

def preference_type(name)
  has_preference! name
  send self.class.preference_type_getter_method(name)
end

#set_preference(name, value) ⇒ Object

Set a preference

Parameters:

  • name (#to_sym)

    name of preference

  • value (Object)

    new value for preference name



80
81
82
83
# File 'lib/spree/preferences/preferable.rb', line 80

def set_preference(name, value)
  has_preference! name
  send self.class.preference_setter_method(name), value
end