Class: Perry::Adapters::AbstractAdapter
- Inherits:
-
Object
- Object
- Perry::Adapters::AbstractAdapter
- Includes:
- Logger
- Defined in:
- lib/perry/adapters/abstract_adapter.rb
Overview
Perry::Adapters::AbstractAdapter
This is the base class from which all adapters should inherit from. Subclasses should overwrite one or all of read, write, and/or delete. They should also register themselves with a unique name using the register_as class method.
Adapters contain a stack of code that is executed on each request. Here is a diagram of the basic anatomy of the adaper stack:
+----------------+
| Perry::Base |
+----------------+
|
+----------------+
| Processors |
+----------------+
|
+----------------+
| ModelBridge |
+----------------+
|
+----------------+
| Middlewares |
+----------------+
|
+----------------+
| Adapter |
+----------------+
Each request is routed through registred processors, the ModelBridge, and registered middlewares before reaching the adapter. After the adapter does its operation the return value passes through each item in the stack allowing stack items to do both custom pre and post processing to every request.
Configuration
You can configure your adapters using the configure method on Perry::Base
configure(:read) do |config|
config.adapter_var_1 = :custom_value
config.adapter_var_2 = [:some, :values]
end
This block creates a new configuration context. Each context is merged onto the previous context allowing subclasses to override configuration set by their parent class.
Middlewares
Middlewares allow you to add custom logic between the model and the adapter. A good example is caching. A caching middleware could be implemented that intercepted a request to the adapter and returned the cached value for that request. If the request is a cache miss it could pass the request on to the adapter, and then cache the result for subsequent calls of the same request.
This is an example mof a no-op middleware:
class NoOpMiddleware
def initialize(adapter, config={})
@adapter = adapter
@config = config
end
def call()
@adapter.call()
end
end
Though this doesn’t do anything it serves to demonstrate the basic structure of a middleware. Logic could be added to perform caching, custom querying, or custom result processing.
Middlewares can also be chained to perform several independent actions. Middlewares are configured through a custom configuration method:
configure(:read) do |config|
config.add_middleware(MyMiddleware, :config => 'var', :foo => 'bar')
end
ModelBridge
The ModelBridge is simply a middleware that is always installed. It instantiates the records from the data returned by the adapter. It “bridges” the raw data to the mapped object.
Processors
Much like middlewares, processors allow you to insert logic into the request stack. The differentiation is that processors are able to manipulate the instantiated objects rather than just the raw data. Processors have access to the objects immediately before passing the data back to the model space.
The interface for a processor is identical to that of a middleware. The return value of the call to adapter; however, is an array of Perry::Base objects rather than Hashes of attributes.
Configuration is also very similar to middlewares:
configure(:read) do |config|
config.add_processor(MyProcessor, :config => 'var', :foo => 'bar')
end
Direct Known Subclasses
Defined Under Namespace
Classes: AdapterConfig
Instance Attribute Summary collapse
-
#config ⇒ Object
return the merged configuration object.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Class Method Summary collapse
-
.create(type, config) ⇒ Object
Wrapper to the standard init method that will lookup the adapter’s class based on its registered symbol name.
-
.register_as(name) ⇒ Object
New adapters should register themselves using this method.
Instance Method Summary collapse
-
#call(mode, options) ⇒ Object
runs the adapter in the specified type mode – designed to work with the middleware stack.
-
#delete(options) ⇒ Object
Abstract delete method – overridden by subclasses.
-
#execute(options) ⇒ Object
Proxy method for the stack and the actual adapter action.
-
#extend_adapter(config) ⇒ Object
Return a new adapter of the same type that adds the given configuration context.
-
#initialize(type, config) ⇒ AbstractAdapter
constructor
Accepts type as :read, :write, or :delete and a base configuration context for this adapter.
-
#middlewares ⇒ Object
Return an array of added middlewares.
-
#processors ⇒ Object
Return an array of added processors.
-
#read(options) ⇒ Object
Abstract read method – overridden by subclasses.
-
#write(options) ⇒ Object
Abstract write method – overridden by subclasses.
Methods included from Logger
Constructor Details
#initialize(type, config) ⇒ AbstractAdapter
Accepts type as :read, :write, or :delete and a base configuration context for this adapter.
112 113 114 115 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 112 def initialize(type, config) @type = type.to_sym @configuration_contexts = config.is_a?(Array) ? config : [config] end |
Instance Attribute Details
#config ⇒ Object
return the merged configuration object
131 132 133 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 131 def config @config end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
108 109 110 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 108 def type @type end |
Class Method Details
.create(type, config) ⇒ Object
Wrapper to the standard init method that will lookup the adapter’s class based on its registered symbol name.
119 120 121 122 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 119 def self.create(type, config) klass = @@registered_adapters[type.to_sym] klass.new(type, config) end |
.register_as(name) ⇒ Object
New adapters should register themselves using this method
187 188 189 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 187 def self.register_as(name) @@registered_adapters[name.to_sym] = self end |
Instance Method Details
#call(mode, options) ⇒ Object
runs the adapter in the specified type mode – designed to work with the middleware stack
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 136 def call(mode, ) @stack ||= self.stack_items.inject(self.method(:execute)) do |below, (above_klass, above_config)| above_klass.new(below, above_config) end [:mode] = mode.to_sym if [:relation] && [:relation].modifiers_value[:noop] [:noop] = [:relation].modifiers_value[:noop] end @stack.call() end |
#delete(options) ⇒ Object
Abstract delete method – overridden by subclasses
180 181 182 183 184 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 180 def delete() raise(NotImplementedError, "You must not use the abstract adapter. Implement an adapter that extends the " + "Perry::Adapters::AbstractAdapter class and overrides this method.") end |
#execute(options) ⇒ Object
Proxy method for the stack and the actual adapter action. This method passes the call on to the appropriate method based on options unless the query has a :noop modifier in which case it returns nil.
161 162 163 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 161 def execute() self.send([:mode], ) unless [:noop] end |
#extend_adapter(config) ⇒ Object
Return a new adapter of the same type that adds the given configuration context
125 126 127 128 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 125 def extend_adapter(config) config = config.is_a?(Array) ? config : [config] self.class.create(self.type, @configuration_contexts + config) end |
#middlewares ⇒ Object
Return an array of added middlewares
149 150 151 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 149 def middlewares self.config[:middlewares] || [] end |
#processors ⇒ Object
Return an array of added processors
154 155 156 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 154 def processors self.config[:processors] || [] end |
#read(options) ⇒ Object
Abstract read method – overridden by subclasses
166 167 168 169 170 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 166 def read() raise(NotImplementedError, "You must not use the abstract adapter. Implement an adapter that extends the " + "Perry::Adapters::AbstractAdapter class and overrides this method.") end |
#write(options) ⇒ Object
Abstract write method – overridden by subclasses
173 174 175 176 177 |
# File 'lib/perry/adapters/abstract_adapter.rb', line 173 def write() raise(NotImplementedError, "You must not use the abstract adapter. Implement an adapter that extends the " + "Perry::Adapters::AbstractAdapter class and overrides this method.") end |