Skip to content

Instantly share code, notes, and snippets.

@lwalen
Created October 27, 2014 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lwalen/6715ddd463a7e62fb307 to your computer and use it in GitHub Desktop.
Save lwalen/6715ddd463a7e62fb307 to your computer and use it in GitHub Desktop.
A nice way to say if your models are 'live', whatever that means.
#
# Setup:
# * Put this file in lib
# * Put `require 'is_livable'` in an initializer
#
# Usage:
# * Within a class like Post, do something like
# `is_livable :released_at, status: APPROVED`
# * Then you can do
# `Post.live, Post.not_live, Post.first.live?`
# * Arguments to is_livable can be attribute names, or a hash
# of an attribute name and the thing that makes it live.
#
module IsLivable
# Could probably do something to eliminate the db call
def live?
self.class.live.where(:id => self.id).first.present?
end
end
class ActiveRecord::Base
LIVABLE_TYPES = {
# MySQL specific, probably need to use something else for postgres, etc.
datetime: "%s < CURTIME()",
boolean: "%s IS TRUE"
}.freeze
def self.is_livable(*args)
class_attribute :live_conditions
self.live_conditions = args.to_a
conditions = live_conditions.map do |a|
if a.is_a?(String) || a.is_a?(Symbol)
a = a.to_s
# Try to do string interpolation like "%s < CURTIME()" % "released_at"
LIVABLE_TYPES[self.columns_hash[a].type].try(:%, a)
elsif a.is_a?(Hash)
"#{a.first.first} = '#{a.first.last}'"
end
end
conditions = conditions.reject(&:nil?).join(" AND ")
scope :live, -> { where(conditions) }
scope :not_live, -> { where("NOT (#{conditions})") }
include IsLivable
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment