Class: RightScraper::RegisteredBase

Inherits:
Object
  • Object
show all
Defined in:
lib/right_scraper/registered_base.rb

Overview

Abstract base class for a registered type.

Example:

class Foo < RegisteredBase
  ...

  register_self(:foo)
end

Defined Under Namespace

Classes: RegisteredTypeError

Class Method Summary collapse

Class Method Details

.query_registered_type(type) ⇒ RightScraper::Repositories::Base

Queries the implementation class for a registered type.

Parameters:

  • type (Symbol|String)

    for query

Returns:

Raises:

  • (::ArgumentError)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/right_scraper/registered_base.rb', line 104

def self.query_registered_type(type)
  raise ::ArgumentError, 'type is required' unless type

  # a quick-out when given a known registerd type. autoloading types makes
  # things more interesting for unknown types.
  type = type.to_s
  unless clazz = registered_types[type]
    # default module implementations may be auto-loading so try default
    # namespace before giving up (assumes snake-case types). types
    # declared in a different namespace can also be autoloaded if fully
    # qualified using forward slashes (require-style).
    class_path = type.split('/').map do |snake_case|
      camel_case = snake_case.split('_').map{ |e| e.capitalize }.join
    end

    # assume no registered types at global scope and insert registration
    # module before any simple name.
    if class_path.size == 1
      class_path = registration_module.name.split('::') + class_path
    end

    # walk class path from global scope because const_get doesn't understand
    # the '::' notation. autoloading is usually setup to support walking
    # from the base module.
    last_item = nil
    begin
      parent_item = ::Object
      class_path.each do |item|
        last_item = parent_item.const_get(item)
        parent_item = last_item
      end
    rescue ::NameError => e
      if e.message =~ /uninitialized constant/
        last_item = nil
      else
        raise
      end
    end
    if last_item
      # type still needs to successfully self-register upon definition.
      unless clazz = registered_types[type]
        raise RegisteredTypeError, "Discovered type did not register itself properly: #{type.inspect} => #{last_item.inspect}"
      end
    else
      raise RegisteredTypeError, "Unknown registered type: #{type.inspect}"
    end
  end
  clazz
end

.register_class(type, clazz) ⇒ TrueClass

Registers given class.

Parameters:

  • type (Symbol|String)

    to register

  • clazz (Class)

    to register

Returns:

  • (TrueClass)

    always true

Raises:

  • (::ArgumentError)


92
93
94
95
96
97
# File 'lib/right_scraper/registered_base.rb', line 92

def self.register_class(type, clazz)
  raise ::ArgumentError, 'clazz is required' unless clazz
  raise ::ArgumentError, 'type is required' unless type
  registered_types[type.to_s] = clazz
  true
end

.register_self(type = nil) ⇒ TrueClass

Registers self.

Parameters:

  • type (Symbol) (defaults to: nil)

    to register or nil

Returns:

  • (TrueClass)

    always true



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/right_scraper/registered_base.rb', line 67

def self.register_self(type = nil)
  # automatically determine registered type from self, if necessary.
  unless type
    class_name = self.name
    default_module_name = registration_module.name + '::'
    if class_name.start_with?(default_module_name)
      subname = class_name[default_module_name.length..-1]
      class_name = subname unless subname.index('::')
    end
    type = class_name.
      gsub(/::/, '/').
      gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
      gsub(/([a-z\d])([A-Z])/,'\1_\2').
      downcase
  end
  self.register_class(type, self)
  true
end

.registered_typesHash

Returns mapping of registered types to classes or empty.

Returns:

  • (Hash)

    mapping of registered types to classes or empty



54
55
56
57
58
59
60
# File 'lib/right_scraper/registered_base.rb', line 54

def self.registered_types
  unless types = registration_module.instance_variable_get(:@registered_types)
    types = {}
    registration_module.instance_variable_set(:@registered_types, types)
  end
  types
end

.registration_moduleModule

Provides a module from which a specific set of registered types is derived (for registration, autoloading, etc.). It is not necessary for all types of the set to be declared within the scope of that module, but doing so will simplify registration and query.

Returns:

  • (Module)

    module or base class in common

Raises:

  • (NotImplementedError)


49
50
51
# File 'lib/right_scraper/registered_base.rb', line 49

def self.registration_module
  raise NotImplementedError
end