Add functionality to multiple models?


#1

Hello,

I’m working on a system for managing multiple different items, let’s say
articles and pictures. All these items can be published and unpublished.
They have a published_at datetime field that is nil in unpublished
state, and filled out in published state.

This is the code that I use in the models:

class SomeModel < ActiveRecord::Base
attr_protected :published_at

def published?
!published_at.nil?
end

def pending?
!published? || Time.now < published_at
end

def status
pending? ? :pending : :published
end

def publish
self.published_at = Time.now if self.pending?
end

def unpublish
self.published_at = nil
end

end

But, I want to keep it DRY, and I do not want to add these lines to any
model that should be publishable. I tried to create a
publishable_item.rb model class and to inherit from that, but in this
case Rails will look for a publishable_items table.

So I’m looking forward to your suggestions.


#2

On May 7, 11:35 am, rv dh removed_email_address@domain.invalid wrote:

[…]
end

But, I want to keep it DRY, and I do not want to add these lines to any
model that should be publishable. I tried to create a
publishable_item.rb model class and to inherit from that, but in this
case Rails will look for a publishable_items table.

Try using a mixin (module).

http://www.rubycentral.com/book/tut_modules.html


#3

Trochalakis C. wrote:

Try using a mixin (module).

http://www.rubycentral.com/book/tut_modules.html

Thanks, that did it. For anyone interested, the mixin looks like this
(model must have attribute published_at):

In any model:
include PublishableSystem
acts_as_publishable

#lib/publishable_system.rb:
module PublishableSystem

an die Klasse anhängen, die diese Erweiterung aufruft

def self.included(klass)
klass.extend ClassMethods
end

module ClassMethods
def acts_as_publishable
include PublishableSystem::InstanceMethods
attr_protected :published_at
end
end

module InstanceMethods
def published?
!published_at.nil?
end

def pending?
  !published? || Time.now < published_at
end

def status
  pending? ? :pending : :published
end

def publish
  self.published_at = Time.now if self.pending?
end

def unpublish
  self.published_at = nil
end

end
end