Protopack knows how to load object definitions (prototypes) from packages of yml files and apply them to your object repository. It's built to work seamslessly with ActiveRecord but doesn't depend on any component of Rails.
Add this line to your application's Gemfile:
And then execute:
Or install it yourself as:
$ gem install protopack
Store package items in a directory structure such as this:
config |- packages |- this-package | |- package-config.yml | |- this-first-item.yml | |- this-second-item.yml | |- this-third-item.yml |- that-package |- package-config.yml |- that-first-item.yml |- that-second-item.yml |- that-third-item.yml
Each "item" file stores attributes of the prototypes you want to be able to create.
Protopack::Package distinguishes between items that already exist, and items that are missing.
In order to add only missing items to your repository, call
In order to apply all package items, overwriting existing items in your repository and adding any missing items, call
Protopack expects your models to implement a class method #existence to provide the interface for querying and creating objects. The expected interface is the same as that returned by Rails' ActiveRelation, so it works seamlessly with ActiveRecord.
exists = YourModel.existence(attributes) exists.empty? # => boolean exists.create!(attributes) # => create an instance using the given attributes exists.first.update_attributes(attributes) # => overwrite attributes of an existing instance
Each package requires a package-config.yml file, with at least a "name" key. You can add whatever other keys you like that may be useful to your application for selecting and presenting packages.
--- name: my-widget-package title: en: A sample package of prototypes fr: Un package exemplaire plain de prototypes description: en: Widgets to set up the widgeting process. Remember to enscarfle the widget feature if you install this package. fr: Machins pour initialiser le processus de machination. Une fois install
Protopack::Package looks for item files in the same directory as the package-config.yml file. Item file names must match the glob pattern "item.yml". This pattern allows you give locale-specific names to items, if l10n is a concern: "widget-item.fr.yml", for example.
Each *-item.yml contains at least three keys: "id", "type" and "attributes". Protopack calls #constantize on the "type" value in order to get a reference to the target class. The "attributes" are then passed to your #existence method as described above. If you specify an "ordinal" key, it must be numeric, and both Package#apply_all and Package#apply_missing will apply items after sorting by #ordinal, putting nil ordinals last.
You can add other keys that you might find useful for selecting and presenting items, for example, a "locale" key to show only items in the current user's locale.
Protopack does no pre- or post-processing. Instead, define attributes on your models that will know what to do, perhaps in conjunction with a :before_save or :after_save handler.
Example item file:
--- id: example-widget description: "This is a kind of widget that's good for widgeting" locale: en type: Widgets::PublicWidget attributes: name: good-widget lang: en size: 42 next-widget-name: better-widget permissions: widget-admin, widget-user
Packages are executable code. Don't let end-users provide packages or package items. Protopack allows package authors call any method on any class.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature)
- Commit your changes (
git commit -am 'Add some feature')
- Push to the branch (
git push origin my-new-feature)
- Create new Pull Request