Class: CouchbaseOrm::Base

Inherits:
Object
  • Object
show all
Extended by:
EnsureUnique, Enum, HasMany, Index, Join
Includes:
ActiveModel::Dirty, ActiveModel::Model, ActiveModel::Serializers::JSON, ActiveModel::Validations, ActiveModel::Validations::Callbacks, Associations, Persistence, Views
Defined in:
lib/couchbase-orm/base.rb

Defined Under Namespace

Classes: Metadata

Constant Summary collapse

ID_LOOKUP =
['id', :id].freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Associations

#destroy_associations!, #reset_associations

Methods included from Persistence

#delete, #destroy, #destroyed?, #new_record?, #persisted?, #reload, #save, #save!, #touch, #update, #update!, #update_attribute

Constructor Details

#initialize(model = nil, ignore_doc_type: false, **attributes) {|_self| ... } ⇒ Base

Add support for libcouchbase response objects

Yields:

  • (_self)

Yield Parameters:



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/couchbase-orm/base.rb', line 133

def initialize(model = nil, ignore_doc_type: false, **attributes)
    @__metadata__   = Metadata.new

    # Assign default values
    @__attributes__ = ::ActiveSupport::HashWithIndifferentAccess.new({type: self.class.design_document})
    self.class.attributes.each do |key, options|
        default = options[:default]
        if default.respond_to?(:call)
            write_attribute key, default.call
        else
            write_attribute key, default
        end
    end

    if model
        case model
        when ::Libcouchbase::Response
            doc = model.value || raise('empty response provided')
            type = doc.delete(:type)
            doc.delete(:id)

            if type && !ignore_doc_type && type.to_s != self.class.design_document
                raise "document type mismatch, #{type} != #{self.class.design_document}"
            end

            @__metadata__.key = model.key
            @__metadata__.cas = model.cas

            # This ensures that defaults are applied
            @__attributes__.merge! doc
        when CouchbaseOrm::Base
            attributes = model.attributes
            attributes.delete(:id)
            @__attributes__ = attributes
        else
            super(**attributes.merge(Hash(model)))
        end
    else
        super(**attributes)
    end

    yield self if block_given?

    run_callbacks :initialize
end

Class Method Details

.attribute(*names, **options) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/couchbase-orm/base.rb', line 68

def attribute(*names, **options)
    @attributes ||= {}
    names.each do |name|
        name = name.to_sym

        @attributes[name] = options

        unless self.instance_methods.include?(name)
            define_method(name) do
                read_attribute(name)
            end
        end

        eq_meth = :"#{name}="
        unless self.instance_methods.include?(eq_meth)
            define_method(eq_meth) do |value|
                value = yield(value) if block_given?
                write_attribute(name, value)
            end
        end
    end
end

.attributesObject



91
92
93
# File 'lib/couchbase-orm/base.rb', line 91

def attributes
    @attributes ||= {}
end

.bucketObject



51
52
53
# File 'lib/couchbase-orm/base.rb', line 51

def bucket
    @bucket ||= Connection.bucket
end

.bucket=(bucket) ⇒ Object



47
48
49
# File 'lib/couchbase-orm/base.rb', line 47

def bucket=(bucket)
    @bucket = bucket
end

.connect(**options) ⇒ Object



43
44
45
# File 'lib/couchbase-orm/base.rb', line 43

def connect(**options)
    @bucket = ::Libcouchbase::Bucket.new(**options)
end

.exists?(id) ⇒ Boolean Also known as: has_key?

Returns:



125
126
127
# File 'lib/couchbase-orm/base.rb', line 125

def exists?(id)
    !bucket.get(id, quiet: true).nil?
end

.find(*ids, **options) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/couchbase-orm/base.rb', line 95

def find(*ids, **options)
    options[:extended] = true
    options[:quiet] ||= false

    ids = ids.flatten.select { |id| id.present? }
    if ids.empty?
        return nil if options[:quiet]
        raise Libcouchbase::Error::EmptyKey, 'no id(s) provided'
    end

    records = bucket.get(*ids, **options)

    records = records.is_a?(Array) ? records : [records]
    records.map! { |record|
        if record
            self.new(record)
        else
            false
        end
    }
    records.select! { |rec| rec }
    ids.length > 1 ? records : records[0]
end

.find_by_id(*ids, **options) ⇒ Object Also known as: []



119
120
121
122
# File 'lib/couchbase-orm/base.rb', line 119

def find_by_id(*ids, **options)
    options[:quiet] = true
    find(*ids, **options)
end

.uuid_generatorObject



60
61
62
# File 'lib/couchbase-orm/base.rb', line 60

def uuid_generator
    @uuid_generator ||= IdGenerator
end

.uuid_generator=(generator) ⇒ Object



64
65
66
# File 'lib/couchbase-orm/base.rb', line 64

def uuid_generator=(generator)
    @uuid_generator = generator
end

Instance Method Details

#==(other) ⇒ Object

Public: Overrides == to compare via class and entity id.

other - Another object to compare to

Returns a boolean.



271
272
273
# File 'lib/couchbase-orm/base.rb', line 271

def ==(other)
    hash == other.hash
end

#attribute(name) ⇒ Object Also known as: read_attribute_for_serialization



225
226
227
228
# File 'lib/couchbase-orm/base.rb', line 225

def attribute(name)
    return self.id if ID_LOOKUP.include?(name)
    @__attributes__[name]
end

#attribute=(name, value) ⇒ Object



231
232
233
# File 'lib/couchbase-orm/base.rb', line 231

def attribute=(name, value)
    __send__(:"#{name}=", value)
end

#attributesObject



211
212
213
214
215
# File 'lib/couchbase-orm/base.rb', line 211

def attributes
    copy = @__attributes__.merge({id: id})
    copy.delete(:type)
    copy
end

#attributes=(attributes) ⇒ Object



217
218
219
220
221
222
# File 'lib/couchbase-orm/base.rb', line 217

def attributes=(attributes)
    attributes.each do |key, value|
        setter = :"#{key}="
        send(setter, value) if respond_to?(setter)
    end
end

#eql?(other) ⇒ Boolean

Public: Overrides eql? to use == in the comparison.

other - Another object to compare to

Returns a boolean.

Returns:



262
263
264
# File 'lib/couchbase-orm/base.rb', line 262

def eql?(other)
    self == other
end

#hashObject

Public: Hashes identifying properties of the instance

Ruby normally hashes an object to be used in comparisons. In our case we may have two techincally different objects referencing the same entity id.

Returns a string representing the unique key.



253
254
255
# File 'lib/couchbase-orm/base.rb', line 253

def hash
    "#{self.class.name}-#{self.id}-#{@__metadata__.cas}-#{@__attributes__.hash}".hash
end

#idObject

Document ID is a special case as it is not stored in the document



181
182
183
# File 'lib/couchbase-orm/base.rb', line 181

def id
    @__metadata__.key || @id
end

#id=(value) ⇒ Object



185
186
187
188
189
# File 'lib/couchbase-orm/base.rb', line 185

def id=(value)
    raise 'ID cannot be changed' if @__metadata__.cas
    attribute_will_change!(:id)
    @id = value.to_s
end

#read_attribute(attr_name) ⇒ Object Also known as: []



191
192
193
# File 'lib/couchbase-orm/base.rb', line 191

def read_attribute(attr_name)
    @__attributes__[attr_name]
end

#to_modelObject

Public: Allows for access to ActiveModel functionality.

Returns self.



243
244
245
# File 'lib/couchbase-orm/base.rb', line 243

def to_model
    self
end

#write_attribute(attr_name, value) ⇒ Object Also known as: []=



196
197
198
199
200
201
202
203
# File 'lib/couchbase-orm/base.rb', line 196

def write_attribute(attr_name, value)
    unless value.nil?
        coerce = self.class.attributes[attr_name][:type]
        value = Kernel.send(coerce.to_s, value) if coerce
    end
    attribute_will_change!(attr_name) unless @__attributes__[attr_name] == value
    @__attributes__[attr_name] = value
end