module QuantumFields::NoSqlize

Module to enable virtual methods in moduls, it creates necessary methods to simulate the behavior that any field can exist, getting or setting it is like a migrated column behaves.

Public Instance Methods

_assign_attribute(key, value) click to toggle source

Overriding a ActiveRecord method that is used in `.create` and `.update` methods to assign a value into an attribute.

# File lib/quantum_fields/no_sqlize.rb, line 34
def _assign_attribute(key, value)
  initialize_fields
  public_send("#{key}=", value) ||
    try(fields_column).try(:except!, key.to_s)
end
method_missing(meth, *args, &block) click to toggle source

Overriding `method_missing` does the magic of assigning an absent field into `.parameters` JSON as a key-value pair, or recovering it's value if exists.

Calls superclass method
# File lib/quantum_fields/no_sqlize.rb, line 13
def method_missing(meth, *args, &block)
  method_name = meth.to_s
  super if method_name.ends_with?('!')
  bad_config! unless can_no_sqlize?
  no_sqlize!(method_name, *args, &block)
rescue StandardError
  super
end
respond_to_missing?(method_name, include_private = false) click to toggle source

Used to map which methods can be called in the instance, it is based on the premisse that you can always assign a value to any field and recover only existing fields or the ones that are in the `.parameters` JSON.

Calls superclass method
# File lib/quantum_fields/no_sqlize.rb, line 25
def respond_to_missing?(method_name, include_private = false)
  bad_config! unless can_no_sqlize?
  meth = method_name.to_s
  meth.ends_with?('=') || meth.ends_with?('?') ||
    try(fields_column).try(:[], meth).present? || super
end

Private Instance Methods

assing_to(param, value) click to toggle source

Assings a value to a key in :fields_column which allows saving any virtual attribute

# File lib/quantum_fields/no_sqlize.rb, line 77
def assing_to(param, value)
  try(fields_column).try(:[]=, param, value)
end
bad_config!() click to toggle source

Raises an exception indicating bad configuration of the gem

# File lib/quantum_fields/no_sqlize.rb, line 93
def bad_config!
  raise QuantumFields::NoSqlizedFieldsColumnMissing,
        "#{model.table_name} should have a `#{fields_column}` JSON column"
end
can_no_sqlize?() click to toggle source

Checks if requirements are met for the feature

# File lib/quantum_fields/no_sqlize.rb, line 82
def can_no_sqlize?
  model.column_names.include?(fields_column.to_s) &&
    %i[hstore json jsonb].include?(no_sqlize_column.type)
end
fields_column() click to toggle source

Retrieves fields_column configured in current scope

# File lib/quantum_fields/no_sqlize.rb, line 48
def fields_column
  model.fields_column
end
initialize_fields() click to toggle source

Checks for `.parameters` presence and initializes it.

# File lib/quantum_fields/no_sqlize.rb, line 53
def initialize_fields
  try("#{fields_column}=", {}) unless try(fields_column).present?
end
model() click to toggle source

Retrieves current model class

# File lib/quantum_fields/no_sqlize.rb, line 43
def model
  self.class
end
no_sqlize!(meth, *args, &_block) click to toggle source

The behavior that a noSQL method should have. It either assigns a value into an attribute or retrieves it's value, depending in the method called.

# File lib/quantum_fields/no_sqlize.rb, line 59
def no_sqlize!(meth, *args, &_block)
  initialize_fields
  if meth.ends_with?('=')
    assing_to(meth.chomp('='), args.first)
  elsif meth.ends_with?('?')
    read_nosqlized(meth.chomp('?')).present?
  else
    read_nosqlized(meth)
  end
end
no_sqlize_column() click to toggle source

Retrieve which column is being used to sqlize

# File lib/quantum_fields/no_sqlize.rb, line 88
def no_sqlize_column
  model.columns.find { |col| col.name == fields_column.to_s }
end
read_nosqlized(meth) click to toggle source

Read the value of a `meth` key in :fields_column

# File lib/quantum_fields/no_sqlize.rb, line 71
def read_nosqlized(meth)
  try(fields_column).try(:[], meth)
end