summaryrefslogtreecommitdiff
path: root/vendor/gems/couchrest_session_store/lib/couchrest/model/database_method.rb
blob: 6ecc8f37029699f8631d5e06309a95d45d2d303c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#
# Allow setting the database to happen dynamically.
#
# Unlike normal CouchRest::Model, the database is not automatically created
# unless you call database!()
#
# The method specified by `database_method` must exist as a class method but
# may optionally also exist as an instance method.
#

module CouchRest
  module Model
    module DatabaseMethod
      extend ActiveSupport::Concern

      def database
        if self.class.database_method
          self.class.server.database(call_database_method)
        else
          self.class.database
        end
      end

      def database!
        if self.class.database_method
          self.class.server.database!(call_database_method)
        else
          self.class.database!
        end
      end

      def database_exists?(db_name)
        self.class.database_exists?(db_name)
      end

      #
      # The normal CouchRest::Model::Base comparison checks if the model's
      # database objects are the same. That is not good for use here, since
      # the objects will always be different. Instead, we compare the string
      # that each database evaluates to.
      #
      def ==(other)
        return false unless other.is_a?(Base)
        if id.nil? && other.id.nil?
          to_hash == other.to_hash
        else
          id == other.id && database.to_s == other.database.to_s
        end
      end
      alias :eql? :==

      protected

      def call_database_method
        if self.respond_to?(self.class.database_method)
          name = self.send(self.class.database_method)
          self.class.db_name_with_prefix(name)
        else
          self.class.send(:call_database_method)
        end
      end

      module ClassMethods

        def database_method(method = nil)
          if method
            @database_method = method
          end
          @database_method
        end
        alias :use_database_method :database_method

        def database
          if database_method
            if !self.respond_to?(database_method)
              raise ArgumentError.new("Incorrect argument to database_method(): no such method '#{method}' found in class #{self}.")
            end
            self.server.database(call_database_method)
          else
            @database ||= prepare_database(super)
          end
        end

        def database!
          if database_method
            self.server.database!(call_database_method)
          else
            @database ||= prepare_database(super)
          end
        end

        #
        # same as database(), but allows for an argument that gets passed through to
        # database method.
        #
        def choose_database(*args)
          self.server.database(call_database_method(*args))
        end

        def db_name_with_prefix(name)
          conf = self.send(:connection_configuration)
          [conf[:prefix], name, conf[:suffix]].reject{|i|i.to_s.empty?}.join(conf[:join])
        end

        def database_exists?(name)
          name = db_name_with_prefix(name)
          begin
            CouchRest.head "#{self.server.uri}/#{name}"
            return true
          rescue CouchRest::NotFound
            return false
          end
        end

        protected

        def call_database_method(*args)
          name = nil
          method = self.method(database_method)
          if method.arity == 0
            name = method.call
          else
            name = method.call(*args)
          end
          db_name_with_prefix(name)
        end

      end
    end
  end
end