Skip to content
Add ability to draft/publish/withdraw/embargo models
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Mark models as has_publishing to publish, draft and embargo models. Easy peasy!

Build Status


  • published, draft, embargoed scopes for easy filtering/finding
  • Rails environment-based default scoping: if your site is using draft, draft/embargoed records will still be found - if you use RAILS_ENV=published, though, only published records will be found.
  • In use in production on multiple sites
  • Covered by automated tests


Add this line to your application's Gemfile:

gem 'has_publishing'

And then execute:

$ bundle

Or install it yourself as:

$ gem install has_publishing


Simply add has_publishing to the model of your choice, and then generate the publishing attributes for your model:

bundle exec rails generate migration [YOUR MODEL NAME] embargoed_until:datetime published_at:datetime published_id:integer kind:string

…and then of course run rake db:migrate

(If anyone would like to add a generator to automate this process, it would be very much appreciated)

A note on publishing

Publishing is typically used in an environment where there may be two installations of the Rails application sharing a common database. This at least is the set up that has_publishing is designed to operate in - something like the following:

|-- Admin RAILS_ENV=draft --| >>>>> SharedDatabase <<<<<< |-- Published Site RAILS_ENV=published --|

Because of this, the gem applies a default_scope to all instances of this model to either:

  • Only return published records if Rails.env matches HasPublishing.config.published_rails_environment (which by default is 'published')
  • Only return draft records otherwise

This prevents 'duplicate' records from appearing for the user (since each 'record' has two representations - 'draft' and 'published/withdrawn')


  1. If you would prefer that this default scope NOT be applied, then simply set HasPublishing.config.scope_records to false.
  2. If you want the default scope to apply properly, ensure that you set the Rails environment of your published application in HasPublishing.config.published_rails_environment.

Injecting your own attributes to be saved

When you call publish! and withdraw! you can pass a hash of attributes with it to be updated with your ActiveRecord::Model object.

This is usefull if you are using a gem like ancestry, for example:

  @page = Page.find_by_slug('foo-bar-page')
  @page.publish!(:parent => (@page.parent.published unless @page.is_root?))


  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request
You can’t perform that action at this time.