class TableSync::Utils::InterfaceChecker

Ruby does not support interfaces, and there is no way to implement them. Interfaces check a methods of a class after the initialization of the class is complete. But in Ruby, the initialization of a class cannot be completed. In execution time we can open any class and add some methods (monkey patching). Ruby has `define_method`, singleton methods, etc.

Duck typing is a necessary measure, the only one available in the Ruby architecture.

Interfaces can be implemented in particular cases with tests for example. But this is not suitable for gems that are used by third-party code.

So, we still want to check interfaces and have a nice error messages, even if it will be duck typing.

Next code do this.

Constants

INTERFACES

Attributes

object[R]

Public Class Methods

new(object) click to toggle source
# File lib/table_sync/utils/interface_checker.rb, line 24
def initialize(object)
  @object = object
end

Public Instance Methods

implements(interface_name) click to toggle source
# File lib/table_sync/utils/interface_checker.rb, line 28
def implements(interface_name)
  INTERFACES[interface_name].each do |method_name, options|
    unless object.respond_to?(method_name)
      raise_error(method_name, options)
    end

    unless include?(object.method(method_name).parameters, options[:parameters])
      raise_error(method_name, options)
    end
  end
  self
end

Private Instance Methods

filter(parameters) click to toggle source
# File lib/table_sync/utils/interface_checker.rb, line 56
def filter(parameters)
  ignored_keys = %i[req block] # for req and block parameters types we can ignore names
  parameters.map { |param| ignored_keys.include?(param.first) ? [param.first] : param }
end
include?(checked, expected) click to toggle source
# File lib/table_sync/utils/interface_checker.rb, line 43
def include?(checked, expected)
  (filter(expected) - filter(checked)).empty?
end
raise_error(method_name, options) click to toggle source
# File lib/table_sync/utils/interface_checker.rb, line 47
def raise_error(method_name, options)
  raise TableSync::InterfaceError.new(
    object,
    method_name,
    options[:parameters],
    options[:description],
  )
end