Module: ActiveRecord::Singleton

Defined in:
lib/acts_as_singleton.rb

Overview

A lightweight singleton library for your Active Record models.

class HomepageSettings < ActiveRecord::Base
  include ActiveRecord::Singleton
end

HomepageSettings.instance # => #<Homepage...>

Like Ruby’s built-in module, it will not prevent you from instantiating more than one object, but it will make it more difficult.

HomepageSettings.__send__(:new).new_record? # => true

Most methods assuming more than one database record will be made private upon including this module. Make sure your public class methods do not clash with the ActiveRecord::Singleton::PRIVATE pattern, or define them after including the module.

Constant Summary collapse

VERSION =
"0.0.8"
PRIVATE =

This pattern matches methods that should be made private because they should not be used in singleton classes.

/^all$|create(?!_reflection|_callback)|find(?!er|_callback)|firs|mini|max|new|d_sco|^upd/

Class Method Summary collapse

Class Method Details

.included(model) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/acts_as_singleton.rb', line 27

def self.included(model)
  model.class_eval do
    private_class_method *methods.grep(PRIVATE) # Deny existent others.

    class << self
      def exists? # Refuse arguments.
        super
      end

      # Returns the first (presumably only) record in the database, or
      # creates one.
      #
      # If validation fails on creation, it will return an unsaved object.
      #
      #   HomepageSettings.instance.update_attributes :welcome => "Hello!"
      def instance
        first || create
      end

      def inspect
        super.sub(/id: .+?, /) {} # Irrelevant.
      end

      def find(*)
        unless caller.first.include?("lib/active_record")
          raise NoMethodError,
            "private method `find' called for #{inspect}"
        end
        super
      end

      def find_by_sql(*)
        unless caller.first.include?("lib/active_record")
          raise NoMethodError,
            "private method `find_by_sql' called for #{inspect}"
        end
        super
      end
    end

    def clone
      raise TypeError, "can't clone instance of singleton #{self.class}"
    end

    def dup
      raise TypeError, "can't dup instance of singleton #{self.class}"
    end

    def inspect
      super.sub(/id: .+?, /) {} # Irrelevant.
    end
  end
end