Class: CouchPillow::Document
- Inherits:
-
Object
- Object
- CouchPillow::Document
- Extended by:
- AttributeDirective, MigrateDirective, MultiDBDirective, RenameDirective, TTLDirective, TypeDirective, TypePrefixDirective
- Defined in:
- lib/couchpillow/document.rb
Constant Summary collapse
- EVENTS =
[ :cas_conflict ].freeze
- CAS_CONFLICT_RETRY_COUNT =
5
Constants included from RenameDirective
RenameDirective::RESERVED_KEYS
Instance Attribute Summary collapse
-
#id ⇒ Object
Returns the value of attribute id.
Class Method Summary collapse
-
.get(*ids) ⇒ Object
Get a Document given an id or multiple ids.
-
.inherited(subclass) ⇒ Object
Inherit directives.
-
.on(event, &block) ⇒ Object
Registers a listener on a specific event.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #[]=(key, value) ⇒ Object
-
#assign_defaults! ⇒ Object
Assign default values.
-
#auto_convert! ⇒ Object
Auto convert.
-
#delete! ⇒ Object
Delete this document from the server.
-
#doc_type ⇒ Object
Helper to get the type of this Document.
-
#has?(key) ⇒ Boolean
Check if this Document has the key.
-
#initialize(hash = {}, id = SecureRandom.hex, cas = nil) ⇒ Document
constructor
Constructor.
-
#migrate! ⇒ Object
Run the migration directive.
-
#rename! ⇒ Object
Rename the keys in this Document as specified by the RenameDirective#rename directive.
-
#save!(opts = {}) ⇒ Object
Save this document to the server.
-
#sort! ⇒ Object
Sort keys on this document.
-
#to_hash ⇒ Object
Convert this Document to a Hash.
-
#to_json(*a) ⇒ Object
Convert this Document to a JSON string.
-
#update(hash) ⇒ Object
Updates the attributes in the document.
-
#update!(opts = {}) ⇒ Object
Attempt to update this Document.
-
#validate! ⇒ Object
Go through each attribute, and validate the values.
-
#whitelist! ⇒ Object
Cleanup the @data hash so it only contains relevant fields.
Methods included from TypeDirective
Methods included from TypePrefixDirective
_is_type_prefixed?, type_prefix
Methods included from AttributeDirective
Methods included from MultiDBDirective
_default_db, _secondary_dbs, _threads, _write_to_secondary_dbs, db, wait
Methods included from RenameDirective
Methods included from MigrateDirective
Methods included from TTLDirective
Constructor Details
#initialize(hash = {}, id = SecureRandom.hex, cas = nil) ⇒ Document
Constructor.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/couchpillow/document.rb', line 44 def initialize hash = {}, id = SecureRandom.hex, cas = nil @data = CouchPillow.symbolize(hash) @original = Marshal.load(Marshal.dump(@data)) @id = self.class._is_type_prefixed? ? self.class._sanitize_id(id) : id time = CouchPillow::Iso8601Time.now.utc @data[:_created_at] ||= time @data[:_updated_at] ||= time @cas = cas rename! whitelist! assign_defaults! migrate! auto_convert! end |
Instance Attribute Details
#id ⇒ Object
Returns the value of attribute id.
13 14 15 |
# File 'lib/couchpillow/document.rb', line 13 def id @id end |
Class Method Details
.get(*ids) ⇒ Object
Get a Document given an id or multiple ids.
If multiple ids are passed, returns an array.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/couchpillow/document.rb', line 262 def self.get *ids results = [] if ids.length == 1 id = _sanitize_id(ids.first) tid = _is_type_prefixed? ? "#{_doc_type}::#{id}" : id result, _, cas = _default_db.get(tid, extended: true) results << create(result, id, cas) elsif ids.length > 1 # Sanitize ids first sanitized_ids = ids.map do |id| id = _sanitize_id(id) _is_type_prefixed? ? "#{_doc_type}::#{id}" : id end # Query the db db_result = _default_db.get(*sanitized_ids, extended: true) results = sanitized_ids.map do |k| result, _, cas = db_result[k] create(result, k, cas) end end results.size == 1 ? results.first : results end |
.inherited(subclass) ⇒ Object
Inherit directives
299 300 301 302 303 304 305 |
# File 'lib/couchpillow/document.rb', line 299 def self.inherited subclass attributes.each do |k, v| subclass.attributes[k] = v end subclass.type_prefix(_is_type_prefixed?) subclass.type(_doc_type) end |
Instance Method Details
#[](key) ⇒ Object
67 68 69 |
# File 'lib/couchpillow/document.rb', line 67 def [] key @data[key.to_s.to_sym] end |
#[]=(key, value) ⇒ Object
72 73 74 |
# File 'lib/couchpillow/document.rb', line 72 def []= key, value @data[key.to_s.to_sym] = value end |
#assign_defaults! ⇒ Object
Assign default values.
219 220 221 222 223 |
# File 'lib/couchpillow/document.rb', line 219 def assign_defaults! self.class.attributes.each do |k, attr| @data[k] = attr.trigger_default_directive if !has?(k) && attr.has_default? end end |
#auto_convert! ⇒ Object
Auto convert.
228 229 230 231 232 |
# File 'lib/couchpillow/document.rb', line 228 def auto_convert! self.class.attributes.each do |k, attr| @data[k] = attr.trigger_auto_convert_directive(@data[k]) if has?(k) end end |
#delete! ⇒ Object
Delete this document from the server.
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/couchpillow/document.rb', line 105 def delete! result = self.class._default_db.delete(db_id) # write to the secondary only if the primary succeeds self.class._write_to_secondary_dbs do |db| db.delete(db_id) end if result result end |
#doc_type ⇒ Object
Helper to get the type of this Document. Can’t really name this ‘type`. Need to avoid name conflict with Ruby’s own ‘type` method.
192 193 194 |
# File 'lib/couchpillow/document.rb', line 192 def doc_type self.class._doc_type end |
#has?(key) ⇒ Boolean
Check if this Document has the key
170 171 172 |
# File 'lib/couchpillow/document.rb', line 170 def has? key @data.has_key?(key) end |
#migrate! ⇒ Object
Run the migration directive
145 146 147 148 149 150 151 |
# File 'lib/couchpillow/document.rb', line 145 def migrate! self.class.migrate_keys.each do |k, pr| if @data.has_key? k @data[k] = pr.call @data[k] end end end |
#rename! ⇒ Object
Rename the keys in this Document as specified by the RenameDirective#rename directive.
199 200 201 202 203 204 205 |
# File 'lib/couchpillow/document.rb', line 199 def rename! self.class.rename_keys.each do |from, to| @data.has_key?(from) and @data[to] = @data[from] and @data.delete(from) end end |
#save!(opts = {}) ⇒ Object
Save this document to the server
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/couchpillow/document.rb', line 79 def save! opts = {} result = nil # write to the primary db first result = _cas_handler do whitelist! sort! validate! opts[:cas] = @cas opts[:ttl] ||= self.class.ttl_value self.class._default_db.set(db_id, _to_save, opts) end # write to the secondary only if the primary succeeds # and ignore CAS for secondary DBs. self.class._write_to_secondary_dbs do |db| db.set(db_id, _to_save) end if result result end |
#sort! ⇒ Object
Sort keys on this document.
252 253 254 |
# File 'lib/couchpillow/document.rb', line 252 def sort! @data = @data.sort.to_h end |
#to_hash ⇒ Object
Convert this Document to a Hash
184 185 186 |
# File 'lib/couchpillow/document.rb', line 184 def to_hash { :_id => @id, :_type => doc_type }.merge!(@data) end |
#to_json(*a) ⇒ Object
Convert this Document to a JSON string
177 178 179 |
# File 'lib/couchpillow/document.rb', line 177 def to_json *a to_hash.to_json(*a) end |
#update(hash) ⇒ Object
Updates the attributes in the document. Existing attributes will be overwritten and new ones will be added. Any other existing attributes that are not present in the hash will be ignored.
158 159 160 161 162 163 164 165 |
# File 'lib/couchpillow/document.rb', line 158 def update hash hash.each do |k,v| @data[k.to_sym] = v end rename! whitelist! auto_convert! end |
#update!(opts = {}) ⇒ Object
Attempt to update this Document. Fails if this Document does not yet exist in the database.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/couchpillow/document.rb', line 120 def update! opts = {} # write to the primary db first result = _cas_handler do whitelist! sort! validate! opts[:cas] = @cas result = self.class._default_db.replace(db_id, _to_save, opts) end # write to the secondary only if the primary succeeds # and ignore CAS for secondary DBs. opts.delete :cas self.class._write_to_secondary_dbs do |db| db.replace(db_id, _to_save) end if result result end |
#validate! ⇒ Object
Go through each attribute, and validate the values. Validation also perform auto-conversion if auto-conversion is enabled for that attribute.
238 239 240 241 242 243 244 245 246 247 |
# File 'lib/couchpillow/document.rb', line 238 def validate! self.class.attributes.each do |k, attr| if has?(k) @data[k] = attr.validate(@data[k]) else @data[k] = attr.trigger_default_directive if attr.has_default? raise ValidationError, "Attribute '#{k}' is required" if attr.required? && !has?(k) end end end |
#whitelist! ⇒ Object
Cleanup the @data hash so it only contains relevant fields.
210 211 212 213 214 |
# File 'lib/couchpillow/document.rb', line 210 def whitelist! @data.delete_if do |k, v| !self.class.attributes.has_key?(k) end end |