class Settingson::Store

Public Class Methods

new(klass:, path: nil) click to toggle source
# File lib/settingson/store.rb, line 6
def initialize(klass:, path: nil)
  @__klass    = klass
  @__path     = path
  @__config   = klass.configure
end

Public Instance Methods

empty?()
Alias for: nil?
method_missing(symbol, *args) click to toggle source
# File lib/settingson/store.rb, line 36
def method_missing(symbol, *args)
  __debug
  __debug("from\n\t#{caller[1..@__config.trace].join("\n\t")}") if
    @__config.trace > 0

  __references_action(symbol, *args) or __rescue_action(symbol.to_s, *args)
  # __rescue_action(symbol.to_s, *args)
end
nil?() click to toggle source
# File lib/settingson/store.rb, line 20
def nil?
  true
end
Also aliased as: empty?
to_a() click to toggle source
# File lib/settingson/store.rb, line 24
def to_a
  []
end
Also aliased as: to_ary
to_ary()
Alias for: to_a
to_i() click to toggle source
# File lib/settingson/store.rb, line 16
def to_i
  0
end
to_key() click to toggle source
# File lib/settingson/store.rb, line 28
def to_key
  nil
end
to_s() click to toggle source
# File lib/settingson/store.rb, line 12
def to_s
  ''
end
Also aliased as: to_str
to_str()
Alias for: to_s

Protected Instance Methods

__cache_key(key) click to toggle source
# File lib/settingson/store.rb, line 172
def __cache_key(key)
  [ @__config.cache.namespace, key ].join('/')
end
__debug(message="") click to toggle source

TODO: move all methods to support class

# File lib/settingson/store.rb, line 47
def __debug(message="")
  return unless @__config.debug
  message = sprintf("%s#%20s: %s",
                    self.class.name,
                    caller_locations.first.label,
                    message)
  Rails.logger.debug(message)
end
__from_cache(key) click to toggle source
# File lib/settingson/store.rb, line 176
def __from_cache(key)
  __debug("looking in cache '#{__cache_key(key)}'")
  Rails.cache.fetch(
    __cache_key(key),
    expires_in:         @__config.cache.expires,
    race_condition_ttl: @__config.cache.race_condition_ttl
  ) do
    __debug("ask DB '#{key}'")
    __from_db(key)
  end
end
__from_db(key) click to toggle source
# File lib/settingson/store.rb, line 188
def __from_db(key)
  @__klass.find_by!(key: key).value
rescue ActiveRecord::RecordNotFound
  __debug("not found")
  ActiveRecord::RecordNotFound.new
end
__get(key) click to toggle source
# File lib/settingson/store.rb, line 101
def __get(key)
  __update_search_path(key)
  result = __look_up_value(@__path)

  if result.is_a?(ActiveRecord::RecordNotFound) or
     result.is_a?(Settingson::Store::Default)
    __debug("return self with path: #{@__path}")
    self
  else
    __debug("return result")
    result
  end
end
__look_up_value(key) click to toggle source
# File lib/settingson/store.rb, line 161
def __look_up_value(key)
  result = @__config.cache.enabled ? __from_cache(key) : __from_db(key)

  if result.is_a?(ActiveRecord::RecordNotFound)
    __debug("looking in #{@__klass.name}.defaults[#{key}]")
    @__klass.defaults[key]
  else
    result
  end
end
__reference_id(key) click to toggle source
# File lib/settingson/store.rb, line 149
def __reference_id(key)
  key.try(:to_key).try(:join, '_') || key.id
end
__references_action(symbol, *args) click to toggle source
# File lib/settingson/store.rb, line 56
def __references_action(symbol, *args)
  # Proxy pass only one method
  # return nil
  # return nil unless ['model_name', 'to_model'].include?(symbol.to_s)
  if @__klass and @__klass.respond_to?(symbol)
    __debug("#{@__klass} know what to do with #{symbol}")
    @__klass.send(symbol, *args)
  end
end
__rescue_action(key, *args) click to toggle source
# File lib/settingson/store.rb, line 66
def __rescue_action(key, *args)
  __debug("key: #{key}:#{key.class} args: #{args}:#{args.class} " +
          "path: '#{@__path}'")
  case key
  when '[]'     # object reference[, with :field]
    __debug("reference '#{args}'")
    __get( __with_reference(args[0], args[1]) )
  when '[]='    # object reference setter
    __debug("reference setter '#{args}'")
    if args.size == 3 # [@setting, :key]= form
      __set( __with_reference(args[0], args[1]), args[2] )
    else # [@settings]= form
      __set( __with_reference(args.first), args.last )
    end
  when /(.+)=/  # setter
    __debug("set '#{$1}' args '#{args.first}'")
    __set($1, args.first)
  else          # returns result or self
    __debug("get '#{key}'")
    __get(key)
  end
end
__set(key, value) click to toggle source
# File lib/settingson/store.rb, line 89
def __set(key, value)
  __update_search_path(key)
  if record = @__klass.find_by(key: @__path)
    record.update!(value: value)
  else
    @__klass.create!(key: @__path, value: value)
  end

  Rails.cache.write(__cache_key(@__path), value) if @__config.cache.enabled
  value
end
__underscore(camel_cased_word) click to toggle source
# File lib/settingson/store.rb, line 139
def __underscore(camel_cased_word)
  word = camel_cased_word.to_s.dup
  word.gsub!(/::/, '_')
  word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
  word.tr!('-', '_')
  word.downcase!
  word
end
__update_search_path(key) click to toggle source
# File lib/settingson/store.rb, line 157
def __update_search_path(key)
  @__path = _search_path(key)
end
__with_reference(key, field=nil) click to toggle source

@profile = Profile.first # any ActiveRecord::Base object Settings.some.host = 'value'

# File lib/settingson/store.rb, line 117
def __with_reference(key, field=nil)
  case key
  when String
    key
  when Symbol
    key.to_s
  when ActiveRecord::Base
    @__reference = key
    if field.nil?
      class_name = __underscore(key.class)
      ref_id = __reference_id(key)
      "#{class_name}_#{ref_id || 'new'}"
    else
      key.send(field.to_sym)
    end
  else
    raise ArgumentError.new(
      'String/Symbol/ActiveRecord::Base variable required'
    )
  end
end
_search_path(key) click to toggle source
# File lib/settingson/store.rb, line 153
def _search_path(key)
  [@__path, key].compact.join('.')
end