Class: Clouder::Entity
- Inherits:
-
OpenStruct
- Object
- OpenStruct
- Clouder::Entity
- Defined in:
- lib/clouder/entity.rb
Overview
This is the base class to be used when accessing resources in a CloudKit server. It contains all the basic persistence methods and attributes. See the entity_spec.rb file for sample usages.
A Note class should be declared as follows:
class Note < Clouder::Entity
uri "http://localhost:9292/notes"
end
Instance Attribute Summary collapse
-
#etag ⇒ Object
readonly
ETag, a UUID.
-
#id ⇒ Object
readonly
Unique object id - not an URI, just a UUID.
-
#last_modified ⇒ Object
readonly
Last modified timestamp.
Class Method Summary collapse
-
.all(options = {}) ⇒ Object
If
options
is nil, returns an array containing all URIs of existing objects for this class. -
.create(hsh = {}) ⇒ Object
Creates and saves an object with the attributes and values passed as a hash.
-
.get(id_or_uri) ⇒ Object
Retrieves an existing object with the given id or uri.
-
.id_from_uri(uri) ⇒ Object
Extracts object ids from absolute or partial URIs.
-
.options(uri = self.uri) ⇒ Object
Returns an array of allowed HTTP methods to be requested at
uri
. -
.uri(address = nil) ⇒ Object
If
address
is passed, sets the URI for the target class. -
.uri_from_id(id) ⇒ Object
Composes a full URI from an object id or partial URI.
Instance Method Summary collapse
-
#delete ⇒ Object
Deletes an existing object.
-
#deleted? ⇒ Boolean
true
if object was deleted,false
otherwise. -
#initialize(attributes = {}) ⇒ Entity
constructor
Constructs a new, unsaved object.
- #inspect ⇒ Object
-
#new? ⇒ Boolean
true
if object was not saved yet,false
otherwise. -
#options ⇒ Object
Returns an array of allowed HTTP methods to be requested for this object.
-
#path ⇒ Object
Partial URI for the object (without the protocol, hostname) => ā/notes/ce655c90-cf09-012b-cd41-0016cb91f13dā.
-
#save ⇒ Object
Saves a new or existing object.
-
#uri ⇒ Object
Full URI for the object => ālocalhost:9292/notes/ce655c90-cf09-012b-cd41-0016cb91f13dā.
-
#versions(options = {}) ⇒ Object
Retrieves older versions of the object.
Constructor Details
#initialize(attributes = {}) ⇒ Entity
Constructs a new, unsaved object. If attributes
are passed in a hash the new object is initialized with the corresponding attributes and values.
note = Note.new # => new, empty
note = Note.new(:text => "Ready note", :author => "Myself") # => new, with attributes set
144 145 146 147 |
# File 'lib/clouder/entity.rb', line 144 def initialize(attributes = {}) @id, @etag, @last_modified, @deleted = nil build(attributes) end |
Instance Attribute Details
#etag ⇒ Object (readonly)
ETag, a UUID
122 123 124 |
# File 'lib/clouder/entity.rb', line 122 def etag @etag end |
#id ⇒ Object (readonly)
Unique object id - not an URI, just a UUID
119 120 121 |
# File 'lib/clouder/entity.rb', line 119 def id @id end |
#last_modified ⇒ Object (readonly)
Last modified timestamp
125 126 127 |
# File 'lib/clouder/entity.rb', line 125 def last_modified @last_modified end |
Class Method Details
.all(options = {}) ⇒ Object
If options
is nil, returns an array containing all URIs of existing objects for this class. Sort order is from the most recent to the oldest.
For other results, options
can be:
- :resolved
-
If
true
, returns full objects instead of URIs. - :offset
-
A positive integer, starting at 0, offsetting the result.
- :limit
-
A positive integer, limiting the results.
All options can be combined.
Note.all
Note.all(:resolved => true)
Note.all(:offset => 20, :limit => 10)
Note.all(:resolved => true, :limit => 20, :offset => 10)
41 42 43 44 45 |
# File 'lib/clouder/entity.rb', line 41 def all( = {}) uri = [:resolved] ? File.join(@uri, "_resolved") : @uri result = Rest.get(Rest.paramify_url(uri, )) [:resolved] ? result["documents"].map { |d| new(d) } : result["uris"] end |
.create(hsh = {}) ⇒ Object
Creates and saves an object with the attributes and values passed as a hash. Returns the newly created object.
note = Note.create(:text => "My note", :author => "John Doe")
51 52 53 54 55 |
# File 'lib/clouder/entity.rb', line 51 def create(hsh = {}) obj = self.new(hsh || {}) obj.save obj end |
.get(id_or_uri) ⇒ Object
Retrieves an existing object with the given id or uri. Returns nil if the object is not found.
note = Note.get("ce655c90-cf09-012b-cd41-0016cb91f13d")
61 62 63 64 65 66 67 68 69 |
# File 'lib/clouder/entity.rb', line 61 def get(id_or_uri) uri = uri_from_id(id_or_uri) document = Rest.get(uri) new({'uri' => uri, 'etag' => document.headers[:etag], 'last_modified' => document.headers[:last_modified], 'document' => document }) rescue RestClient::ResourceNotFound nil end |
.id_from_uri(uri) ⇒ Object
Extracts object ids from absolute or partial URIs.
Note.id_from_uri("http://localhost:9292/notes/ce655c90-cf09-012b-cd41-0016cb91f13d")
=> "ce655c90-cf09-012b-cd41-0016cb91f13d"
84 85 86 87 88 89 90 91 92 |
# File 'lib/clouder/entity.rb', line 84 def id_from_uri(uri) id = URI.parse(uri) # /notes/abc if id.path[0,1] == "/" id.path.split("/")[2] else id.to_s end end |
.options(uri = self.uri) ⇒ Object
Returns an array of allowed HTTP methods to be requested at uri
. If uri
is nil, the class URI is queried.
Note. # => [ "GET", "HEAD", "POST", "OPTIONS" ]
75 76 77 78 |
# File 'lib/clouder/entity.rb', line 75 def (uri = self.uri) doc = Rest.custom(:options, uri) doc["allow"].to_s.split(",").map { |s| s.strip } end |
.uri(address = nil) ⇒ Object
If address
is passed, sets the URI for the target class. If nothing is passed, returns the current URI for the target class.
Note.uri "http://localhost:8989/notes" # changes the old URI
Note.uri # => "http://localhost:8989/notes"
22 23 24 |
# File 'lib/clouder/entity.rb', line 22 def uri(address = nil) address ? @uri = address : @uri end |
.uri_from_id(id) ⇒ Object
Composes a full URI from an object id or partial URI.
Note.uri_from_id("/notes/ce655c90-cf09-012b-cd41-0016cb91f13d")
=> "http://localhost:9292/notes/ce655c90-cf09-012b-cd41-0016cb91f13d"
Note.uri_from_id("ce655c90-cf09-012b-cd41-0016cb91f13d")
=> "http://localhost:9292/notes/ce655c90-cf09-012b-cd41-0016cb91f13d"
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/clouder/entity.rb', line 101 def uri_from_id(id) url = URI.parse(id) if url.absolute? url.to_s else # /notes/1234 if url.path[0,1] == "/" (URI.parse(self.uri) + url).to_s # 1234 else File.join("#{self.uri}", id) end end end |
Instance Method Details
#delete ⇒ Object
Deletes an existing object. Its etag should match the etag in the database, otherwise the operation fails.
Returns true
if save was successful, false
otherwise.
note = Note.new("ce655c90-cf09-012b-cd41-0016cb91f13d")
note.delete # => true
172 173 174 175 176 177 178 179 |
# File 'lib/clouder/entity.rb', line 172 def delete Rest.delete uri, "If-Match" => etag @deleted = true freeze true rescue RestClient::RequestFailed false end |
#deleted? ⇒ Boolean
true
if object was deleted, false
otherwise.
187 |
# File 'lib/clouder/entity.rb', line 187 def deleted?; @deleted end |
#inspect ⇒ Object
224 225 226 |
# File 'lib/clouder/entity.rb', line 224 def inspect "#<#{self.class.name} uri=#{uri}, id=#{id}, etag=#{@etag}, last_modified=#{@last_modified}, #{@table.inspect}>" end |
#new? ⇒ Boolean
true
if object was not saved yet, false
otherwise.
182 183 184 |
# File 'lib/clouder/entity.rb', line 182 def new? @uri == nil and @etag == nil and @last_modified == nil end |
#options ⇒ Object
Returns an array of allowed HTTP methods to be requested for this object.
note = Note.new("ce655c90-cf09-012b-cd41-0016cb91f13d") # => existing object
note. # => [ "DELETE", "GET", "HEAD", "PUT", "OPTIONS" ]
220 221 222 |
# File 'lib/clouder/entity.rb', line 220 def self.class.(uri) end |
#path ⇒ Object
Partial URI for the object (without the protocol, hostname)
=> "/notes/ce655c90-cf09-012b-cd41-0016cb91f13d"
135 136 137 |
# File 'lib/clouder/entity.rb', line 135 def path URI.parse(uri).path end |
#save ⇒ Object
Saves a new or existing object. If the object already exists, then its etag should match the etag in the database, otherwise the operation fails.
Returns true
if save was successful, false
otherwise.
note = Note.new(:text => "Ready note", :author => "Myself")
note.save # => true
156 157 158 159 160 161 162 163 164 |
# File 'lib/clouder/entity.rb', line 156 def save result = new? ? Rest.post(collection_uri, @table) : Rest.put(uri, @table, "If-Match" => etag) @id, @etag, @last_modified = result.values_at("uri", "etag", "last_modified") @id = self.class.id_from_uri(@id) @last_modified = Time.parse(@last_modified) true rescue RestClient::RequestFailed false end |
#uri ⇒ Object
Full URI for the object
=> "http://localhost:9292/notes/ce655c90-cf09-012b-cd41-0016cb91f13d"
129 130 131 |
# File 'lib/clouder/entity.rb', line 129 def uri @uri ||= self.class.uri_from_id(id) if id end |
#versions(options = {}) ⇒ Object
Retrieves older versions of the object. Sort order is from the current version to the oldest one. The options
parameter works as in all
.
note = Note.new("ce655c90-cf09-012b-cd41-0016cb91f13d")
older_versions = note.versions(:resolved, :limit => 3)
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/clouder/entity.rb', line 195 def versions( = {}) if uri url = File.join(uri, "versions") if [:etag] url = File.join(url, [:etag]) self.class.get(url) else url = [:resolved] ? File.join(url, "_resolved") : url result = Rest.get(Rest.paramify_url(url, )) if [:resolved] result["documents"].map { |d| self.class.new(d) } else result["uris"] end end else [] end end |