1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 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 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
[](http://rubygems.org/gems/ddplugin)
[](http://rubygems.org/gems/ddplugin)
[](https://travis-ci.org/ddfreyne/ddplugin)
[](https://codeclimate.com/github/ddfreyne/ddplugin)
[](https://coveralls.io/r/ddfreyne/ddplugin)
# ddplugin
*ddplugin* is a library for managing plugins.
Designing a library so that third parties can easily extend it greatly improves its usefulness. *ddplugin* helps solve this problem using *plugins*, which are classes of a certain type and with a given identifier (Ruby symbol).
This code was extracted from Nanoc, where it has been in production for years.
## Use case
Many projects can make use of plugins. Here are a few examples:
* a **text processing library** with *filters* such as `colorize-syntax`, `markdown` and `smartify-quotes`.
* an **image processing library** with *filters* such as `resize`, `desaturate` and `rotate`.
* a **database driver abstraction** with *connectors* such as `postgres`, `sqlite3` and `mysql`.
* a **document management system** with *data sources* such as `filesystem` and `database`.
In *ddplugin*, the filters, connectors and data sources would be *plugin types*, while the actual plugins, such as `markdown`, `rotate`, `postgres` and `database` would be *plugins*.
A typical way to use plugins would be to store the plugin names in a configuration file, so that the actual plugin implementations can be discovered at runtime.
## Requirements
*ddplugin* requires Ruby 2.3 or higher.
## Versioning
*ddplugin* adheres to [Semantic Versioning 2.0.0](http://semver.org).
## Installation
If your library where you want to use *ddplugin* has a gemspec, add *ddplugin* as a runtime dependency to the gemspec:
```ruby
spec.add_runtime_dependency 'ddplugin', '~> 1.0'
```
If you use Bundler instead, add it to the `Gemfile`:
```ruby
gem 'ddplugin', '~> 1.0'
```
## Usage
Plugin type are classes that extend `DDPlugin::Plugin`:
```ruby
class Filter
extend DDPlugin::Plugin
end
class DataSource
extend DDPlugin::Plugin
end
```
To define a plugin, create a class that inherits from the plugin type and sets the identifier, either as a symbol or a string:
```ruby
class ERBFilter < Filter
# Specify the identifier as a symbol…
identifier :erb
end
class HamlFilter < Filter
# … or as a string …
identifier 'haml'
end
class FilesystemDataSource < DataSource
# … or even provide multiple.
identifiers :filesystem, :file_system
end
class PostgresDataSource < DataSource
# … or mix and match (not sure why you would, though)
identifier :postgres, 'postgresql'
end
```
To find a plugin of a given type and with a given identifier, call `.named` on the plugin type, passing an identifier:
```ruby
Filter.named(:erb)
# => ERBFilter
Filter.named('haml')
# => HamlFilter
DataSource.named(:filesystem)
# => FilesystemDataSource
DataSource.named(:postgres)
# => PostgresDataSource
```
In a real-world situation, the plugin types could be described in the environment:
```
% cat .env
DATA_SOURCE_TYPE=postgres
```
```ruby
DataSource.named(ENV.fetch('DATA_SOURCE_TYPE'))
# => PostgresDataSource
```
… or in a configuration file:
```
% cat config.yml
data_source: 'filesystem'
```
```ruby
config = YAML.load_file('config.yml')
DataSource.named(config.fetch('data_source'))
# => FilesystemDataSource
```
To get all plugins of a given type, call `.all` on the plugin type:
```ruby
Filter.all
# => [ERBFilter, HamlFilter]
DataSource.all
# => [FilesystemDataSource, PostgresDataSource]
```
To get the identifier of a plugin, call `.identifier`, which returns a symbol:
```ruby
Filter.named(:erb).identifier
# => :erb
Filter.named('haml').identifier
# => :haml
PostgresDataSource.identifier
# => :postgres
```
## Development
Pull requests and issues are greatly appreciated.
When you submit a pull request, make sure that your change is covered by tests, and that the `README` and [YARD](http://yardoc.org/) source code documentation are still up-to-date.
To run the tests:
```
% bundle install
% bundle exec rake
```
|