{"id":16068081,"url":"https://github.com/ged/pluginfactory","last_synced_at":"2025-03-18T05:31:03.036Z","repository":{"id":1130716,"uuid":"1006435","full_name":"ged/pluginfactory","owner":"ged","description":"A Ruby module for adding plugin-like behavior to classes","archived":false,"fork":false,"pushed_at":"2012-02-20T19:37:41.000Z","size":304,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-28T07:33:14.898Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://deveiate.org/projects/PluginFactory","language":"Ruby","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ged.png","metadata":{"files":{"readme":"README.rdoc","changelog":"History.rdoc","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-10-19T17:01:03.000Z","updated_at":"2021-11-29T00:04:26.000Z","dependencies_parsed_at":"2022-08-16T12:10:32.957Z","dependency_job_id":null,"html_url":"https://github.com/ged/pluginfactory","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ged%2Fpluginfactory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ged%2Fpluginfactory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ged%2Fpluginfactory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ged%2Fpluginfactory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ged","download_url":"https://codeload.github.com/ged/pluginfactory/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243903166,"owners_count":20366434,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-09T06:08:25.356Z","updated_at":"2025-03-18T05:31:01.980Z","avatar_url":"https://github.com/ged.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"= pluginfactory\n\n* http://deveiate.org/projects/PluginFactory\n\n\n== Description\n\nPluginFactory is a mixin module that turns an including class into a factory for\nits derivatives, capable of searching for and loading them by name. This is\nuseful when you have an abstract base class which defines an interface and basic\nfunctionality for a part of a larger system, and a collection of subclasses\nwhich implement the interface for different underlying functionality.\n\nAn example of where this might be useful is in a program which talks to a\ndatabase. To avoid coupling it to a specific database, you use a Driver class\nwhich encapsulates your program's interaction with the database behind a useful\ninterface. Now you can create a concrete implementation of the Driver class for\neach kind of database you wish to talk to. If you make the base Driver class a\nPluginFactory, too, you can add new drivers simply by dropping them in a\ndirectory and using the Driver's `create` method to instantiate them:\n\n=== Synopsis\n\nin driver.rb:\n\n\trequire \"PluginFactory\"\n\t\n\tclass Driver\n\t\tinclude PluginFactory\n\t\tdef self::derivative_dirs\n\t\t   [\"drivers\"]\n\t\tend\n\tend\n\nin drivers/mysql.rb:\n\n\trequire 'driver'\n\t\n\tclass MysqlDriver \u003c Driver\n\t\t...implementation...\n\tend\n\nin /usr/lib/ruby/1.8/PostgresDriver.rb:\n\n\trequire 'driver'\n\t\n\tclass PostgresDriver \u003c Driver\n\t\t...implementation...\n\tend\n\nelsewhere\n\n\trequire 'driver'\n\t\n\tconfig[:driver_type] #=\u003e \"mysql\"\n\tdriver = Driver.create( config[:driver_type] )\n\tdriver.class #=\u003e MysqlDriver\n\tpgdriver = Driver.create( \"PostGresDriver\" )\n\n=== How Plugins Are Loaded\n\nThe +create+ class method added to your class by PluginFactory searches for your\nmodule using several different strategies. It tries various permutations of the\nbase class's name in combination with the derivative requested. For example,\nassume we want to make a +DataDriver+ base class, and then use plugins to define\ndrivers for different kinds of data sources:\n\n\trequire 'pluginfactory'\n\t\n\tclass DataDriver\n\t  include PluginFactory\n\tend\n\nWhen you attempt to load the 'socket' data-driver class like so:\n\n\tDataDriver.create( 'socket' )\n\nPluginFactory searches for modules with the following names:\n\n\t'socketdatadriver'\n\t'socket_datadriver'\n\t'socketDataDriver'\n\t'socket_DataDriver'\n\t'SocketDataDriver'\n\t'Socket_DataDriver'\n\t'socket'\n\t'Socket'\n\nObviously the last one will load something other than what is intended, so you\ncan also tell PluginFactory that plugins should be loaded from a subdirectory by\ndeclaring a class method called `derivative_dirs` in the base class. It should\nreturn an Array that contains a list of subdirectories to try:\n\n\tclass DataDriver\n\t  include PluginFactory\n\t\n\t  def self::derivative_dirs\n\t    ['drivers']\n\t  end\n\tend\n\nThis will change the list that is required to:\n\n\t'drivers/socketdatadriver'\n\t'drivers/socket_datadriver'\n\t'drivers/socketDataDriver'\n\t'drivers/socket_DataDriver'\n\t'drivers/SocketDataDriver'\n\t'drivers/Socket_DataDriver'\n\t'drivers/socket'\n\t'drivers/Socket'\n\nIf you return more than one subdirectory, each of them will be tried in turn:\n\n\tclass DataDriver\n\t  include PluginFactory\n\t\n\t  def self::derivative_dirs\n\t    ['drivers', 'datadriver']\n\t  end\n\tend\n\nwill change the search to include:\n\n\t'drivers/socketdatadriver'\n\t'drivers/socket_datadriver'\n\t'drivers/socketDataDriver'\n\t'drivers/socket_DataDriver'\n\t'drivers/SocketDataDriver'\n\t'drivers/Socket_DataDriver'\n\t'drivers/socket'\n\t'drivers/Socket'\n\t'datadriver/socketdatadriver'\n\t'datadriver/socket_datadriver'\n\t'datadriver/socketDataDriver'\n\t'datadriver/socket_DataDriver'\n\t'datadriver/SocketDataDriver'\n\t'datadriver/Socket_DataDriver'\n\t'datadriver/socket'\n\t'datadriver/Socket'\n\nIf the plugin is not found, a FactoryError is raised, and the message will list\nall the permutations that were tried.\n\n=== Logging\n\nIf you need a little more insight into what's going on, PluginFactory uses\n'Logger' from the standard library. Just set its logger to your own to include\nlog messages about plugins being loaded:\n\n\n\trequire 'pluginfactory'\n\trequire 'logger'\n\t\n\tclass DataDriver\n\t  include PluginFactory\n\t\n\tend\n\t\n\t$logger = Logger.new( $stderr )\n\t$logger.level = Logger::DEBUG\n\tPluginFactory.logger = $logger\n\t\n\tDataDriver.create( 'ringbuffer' )\n\nthis might generate a log that looks like:\n\n\tD, [...] DEBUG -- : Loading derivative ringbuffer\n\tD, [...] DEBUG -- : Subdirs are: [\"\"]\n\tD, [...] DEBUG -- : Path is: [\"ringbufferdatadriver\", \"ringbufferDataDriver\", \n\t      \"ringbuffer\"]...\n\tD, [...] DEBUG -- : Trying ringbufferdatadriver...\n\tD, [...] DEBUG -- : No module at 'ringbufferdatadriver', trying the next \n\t      alternative: 'no such file to load -- ringbufferdatadriver'\n\tD, [...] DEBUG -- : Trying ringbufferDataDriver...\n\tD, [...] DEBUG -- : No module at 'ringbufferDataDriver', trying the next \n\t      alternative: 'no such file to load -- ringbufferDataDriver'\n\tD, [...] DEBUG -- : Trying ringbuffer...\n\tD, [...] DEBUG -- : No module at 'ringbuffer', trying the next alternative: \n\t      'no such file to load -- ringbuffer'\n\tD, [...] DEBUG -- : fatals = []\n\tE, [...] ERROR -- : Couldn't find a DataDriver named 'ringbuffer': \n\t      tried [\"ringbufferdatadriver\", \"ringbufferDataDriver\", \"ringbuffer\"]\n\n\n\n== Installation\n\n    gem install pluginfactory\n\n\n== Contributing\n\nYou can check out the current development source with Mercurial via its\n{Mercurial repo}[http://repo.deveiate.org/PluginFactory]. Or if you prefer\nGit, via {its Github mirror}[https://github.com/ged/pluginfactory].\n\nAfter checking out the source, run:\n\n    $ rake newb\n\nThis task will install any missing dependencies, run the tests/specs,\nand generate the API documentation.\n\n\n== License\n\nCopyright (c) 2008-2012, Michael Granger and Martin Chase\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the author/s, nor the names of the project's\n  contributors may be used to endorse or promote products derived from this\n  software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fged%2Fpluginfactory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fged%2Fpluginfactory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fged%2Fpluginfactory/lists"}