module Publishable::ClassMethods
Define scopes and methods for querying and manipulating Publishables.
Public Instance Methods
publishable(options = {})
click to toggle source
DSL method to link this behavior into your model. In your ActiveRecord model class, add publishable
to include the scopes and methods for publishable objects.
@example
class Post < ActiveRecord::Base publishable end
@param [Hash] options The publishable options. @option options [String, Symbol] :on (:publishable) The name of the publishable column on the model.
# File lib/publishable.rb, line 39 def publishable(options = {}) return unless table_exists? column_name = (options[:on] || :published).to_sym # silently ignore a missing column - since bombing on a missing column can make re-running migrations very hard return unless self.columns_hash[column_name.to_s].present? column_type = self.columns_hash[column_name.to_s].type if respond_to?(:scope) # define published/unpublished scope case column_type when :date scope :published, lambda { |*args| on_date = args[0] || Date.current where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].lteq(on_date)) } scope :unpublished, lambda { |*args| on_date = args[0] || Date.current where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].gt(on_date)) } when :datetime scope :published, lambda { |*args| at_time = args[0] || Time.now where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].lteq(at_time.utc)) } scope :unpublished, lambda { |*args| at_time = args[0] || Time.now where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].gt(at_time.utc)) } when :boolean scope :published, lambda { where(column_name => true) } scope :unpublished, lambda { where(column_name => false) } else raise ActiveRecord::ConfigurationError, "Invalid column_type #{column_type} for Publishable column on model #{self.name}" end # define recent/upcoming scopes if [:date, :datetime].include? column_type scope :recent, lambda { |*args| how_many = args[0] || nil col_name = arel_table[column_name].name published.limit(how_many).order("#{col_name} DESC") } scope :upcoming, lambda { |*args| how_many = args[0] || nil col_name = arel_table[column_name].name unpublished.limit(how_many).order("#{col_name} ASC") } end end case column_type when :datetime class_eval <<-EVIL, __FILE__, __LINE__ + 1 def published?(_when = Time.now) #{column_name} ? #{column_name} <= _when : false end def unpublished?(_when = Time.now) !published?(_when) end def publish(_when = Time.now) self.#{column_name} = _when unless published?(_when) end def publish!(_when = Time.now) publish(_when) && (!respond_to?(:save) || save) end def unpublish() self.#{column_name} = nil true end def unpublish!() unpublish() && (!respond_to?(:save) || save) end EVIL when :date class_eval <<-EVIL, __FILE__, __LINE__ + 1 def published?(_when = Date.current) #{column_name} ? #{column_name} <= _when : false end def unpublished?(_when = Date.current) !published?(_when) end def publish(_when = Date.current) self.#{column_name} = _when unless published?(_when) end def publish!(_when = Date.current) publish(_when) && (!respond_to?(:save) || save) end def unpublish() self.#{column_name} = nil end def unpublish!() unpublish() && (!respond_to?(:save) || save) end EVIL when :boolean class_eval <<-EVIL, __FILE__, __LINE__ + 1 def published?() #{column_name} end def unpublished?() !published?() end def publish() self.#{column_name} = true end def publish!() publish() save if respond_to?(:save) end def unpublish() self.#{column_name} = false end def unpublish!() unpublish() save if respond_to?(:save) end EVIL else raise ActiveRecord::ConfigurationError, "Invalid column_type #{column_type} for Publishable column on model #{self.name}" end end