kwbock/clipster

View on GitHub
app/models/clipster/clip.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Clipster
  class Clip < ActiveRecord::Base
    include ActionView::Helpers::DateHelper

    before_create :default_values

    self.primary_key = :id

    attr_accessible :clip, :language, :title, :private, :expires, :lifespan
    cattr_reader :lifespans
    cattr_accessor :current_user, :lifespan

    belongs_to :user, :class_name => Clipster.config.user_class.to_s if Clipster.config.associates_clip_with_user

    # Define all supported lifespans and their time offset
    @@lifespans = [["Forever", nil],
                   ["An Hour", :hours=>1],
                   ["A Day", :days=>1],
                   ["A Week", :days=>7],
                   ["A Month", :months=>1],
                   ["A Year", :years=>1]]

    validates :clip, :length => {:minimum   => 3}
    validates :title, :length => {:minimum   => 1}
    validates :language, :inclusion => { :in => CodeRay::Scanners.list.map(&:to_s),
          :message => "%{value} is not supported, please choose from: " +
          CodeRay::Scanners.list.map(&:to_s).to_s }
    validates :lifespan, :inclusion => { :in => @@lifespans.flatten,
          :message => "%{value} is not supported, please choose from:" +
          lifespans.map(&:first).to_s}

    # Search all public clips using title, language, and content
    def self.search(term)
      where("(title LIKE :term or language LIKE :term or clip LIKE :term) and (expires is null OR expires > :now)",{
          :term => "#{term}%".gsub('*','%').gsub(/%+/, '%'),
          :now => DateTime.now
      })
    end

    # All clips that are public, language specific, and not expired
    def self.language_for_public(lang)
      where("private = :private AND
             language = :lang AND
             (expires is null OR expires > :now)",{
          :private => false,
          :lang => lang,
          :now  => DateTime.now
      })
    end

    # All clips that are public, and not expired
    def self.public
      where("private = :private AND
             (expires is null OR expires > :now)",{
          :private => false,
          :now  => DateTime.now
      })
    end

    # Setter to convert user's choice of 'A Week', etc. to an actual DateTime
    def lifespan=(lifespan)
      @lifespan = lifespan
      @@lifespans.each_with_index do |span, index|
        if span[0] == lifespan && lifespan != "Forever"
          self.expires = DateTime.now.advance(@@lifespans[index][1])
        end
      end
    end

    def lifespan
      @lifespan
    end

    # Getter to convert an expire date to '1 Month', '1 Year', etc.
    def expires_in_words
      unless self.expires.nil?
        time_ago_in_words(self.expires).humanize
      else
        "The end of time"
      end
    end

    # Utility method called by either cron job or when an expired clip is accessed
    def Clip.delete_expired
      Clip.destroy_all(["expires is not null AND expires <= ?", DateTime.now])
    end

    # Creates the div for the clip
    def div
      cr_scanner = CodeRay.scan(self.clip, self.language)
      # Only show line numbers if its greater than 1
      if cr_scanner.loc <= 1
        return cr_scanner.div
      else
        return cr_scanner.div(:line_numbers => :table)
      end
    end

    protected
      def default_values
        self.user_id = self.current_user if Clipster.config.associates_clip_with_user
        self.id = Time.now.to_f.to_s.gsub('.','').to_i.to_s(36)
      end
  end
end