Class: WAZ::Tables::Service

Inherits:
Object
  • Object
show all
Includes:
Storage::SharedKeyCoreService
Defined in:
lib/waz/tables/service.rb

Overview

This is internally used by the waz-tables part of the gem and it exposes the Windows Azure Blob API REST methods implementation. You can use this class to perform an specific operation that isn’t provided by the current API.

Constant Summary collapse

DATASERVICES_NAMESPACE =
"http://schemas.microsoft.com/ado/2007/08/dataservices"
DATASERVICES_METADATA_NAMESPACE =
"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"

Instance Attribute Summary

Attributes included from Storage::SharedKeyCoreService

#access_key, #account_name, #base_url, #retry_count, #sharedaccesssignature, #type_of_service, #use_devenv, #use_sas_auth_only, #use_ssl

Instance Method Summary collapse

Methods included from Storage::SharedKeyCoreService

#canonicalize_headers, #canonicalize_message, #canonicalize_message20090919, #execute, #generate_request, #generate_request_uri, #generate_signature, #generate_signature20090919, #initialize

Instance Method Details

#create_table(table_name) ⇒ Object

Creates a table on the current Windows Azure Storage account.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/waz/tables/service.rb', line 12

def create_table(table_name)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)

  payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
            "<entry xmlns:d=\"#{DATASERVICES_NAMESPACE}\" xmlns:m=\"#{DATASERVICES_METADATA_NAMESPACE}\" xmlns=\"http://www.w3.org/2005/Atom\">" \
            "<title /><updated>#{Time.now.utc.iso8601}</updated><author><name/></author><id/>" \
            "<content type=\"application/xml\"><m:properties><d:TableName>#{table_name}</d:TableName></m:properties></content></entry>"

  begin
    execute :post, 'Tables', {}, default_headers, payload
    return {:name => table_name, :url => "#{self.base_url}/Tables('#{table_name}"}
  rescue RestClient::RequestFailed
    raise WAZ::Tables::TableAlreadyExists, table_name if $!.http_code == 409
  end
end

#delete_entity(table_name, partition_key, row_key) ⇒ Object

Delete an existing entity in a table.



102
103
104
105
106
107
108
109
110
111
# File 'lib/waz/tables/service.rb', line 102

def delete_entity(table_name, partition_key, row_key)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  
  begin
    execute :delete, "#{table_name}(PartitionKey='#{partition_key}',RowKey='#{row_key}')", {}, default_headers.merge({'If-Match' => '*'})
  rescue RestClient::ResourceNotFound
    raise WAZ::Tables::TableDoesNotExist, table_name if $!.http_code == 404 and $!.response.body.include?('TableNotFound')
    raise WAZ::Tables::EntityDoesNotExist, "(PartitionKey='#{partition_key}',RowKey='#{row_key}')" if $!.http_code == 404
  end
end

#delete_table(table_name) ⇒ Object

Delete a table on the current Windows Azure Storage account.



29
30
31
32
33
34
35
36
# File 'lib/waz/tables/service.rb', line 29

def delete_table(table_name)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  begin
    execute :delete, "Tables('#{table_name}')", {}, default_headers
  rescue RestClient::ResourceNotFound
    raise WAZ::Tables::TableDoesNotExist, table_name if $!.http_code == 404
  end
end

#get_entity(table_name, partition_key, row_key) ⇒ Object

Retrieves an existing entity on the current storage account. TODO: handle specific errors



115
116
117
118
119
# File 'lib/waz/tables/service.rb', line 115

def get_entity(table_name, partition_key, row_key)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  response = execute(:get, "#{table_name}(PartitionKey='#{partition_key}',RowKey='#{row_key}')", {}, default_headers)
  return parse_response(response)
end

#get_table(table_name) ⇒ Object

Retrieves an existing table on the current storage account. remove Content-Type if it’s not working



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/waz/tables/service.rb', line 55

def get_table(table_name)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)        
  
  begin
    content = execute :get, "Tables('#{table_name}')", {}, default_headers
    doc = REXML::Document.new(content)
    item = REXML::XPath.first(doc, "entry")
    return {  :name => REXML::XPath.first(item.elements['content'], "m:properties/d:TableName", {"m" => DATASERVICES_METADATA_NAMESPACE, "d" => DATASERVICES_NAMESPACE}).text,
              :url => REXML::XPath.first(item, "id").text }
  rescue RestClient::ResourceNotFound
    raise WAZ::Tables::TableDoesNotExist, table_name if $!.http_code == 404
  end        
end

#insert_entity(table_name, entity) ⇒ Object

Insert a new entity on the provided table for the current storage account TODO: catch all api errors as described on Table Service Error Codes on MSDN (msdn.microsoft.com/en-us/library/dd179438.aspx)



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/waz/tables/service.rb', line 71

def insert_entity(table_name, entity)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  raise WAZ::Tables::TooManyProperties, entity.length if entity.length > 252 
  
  begin
    response = execute(:post, table_name, {}, default_headers, generate_payload(table_name, entity))
    return parse_response(response)          
  rescue RestClient::RequestFailed          
    raise WAZ::Tables::EntityAlreadyExists, entity[:row_key] if $!.http_code == 409 and $!.response.body.include?('EntityAlreadyExists')          
  end     
end

#list_tables(next_table_name = nil) ⇒ Object

Lists all existing tables on the current storage account. remove Content-Type if it’s not working



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/waz/tables/service.rb', line 40

def list_tables(next_table_name = nil)
  query = { 'NextTableName' => next_table_name } unless next_table_name.nil?
  content = execute :get, "Tables", query ||= {}, default_headers

  doc = REXML::Document.new(content)
  tables = REXML::XPath.each(doc, '/feed/entry').map do |item|
      { :name => REXML::XPath.first(item.elements['content'], "m:properties/d:TableName", {"m" => DATASERVICES_METADATA_NAMESPACE, "d" => DATASERVICES_NAMESPACE}).text,
        :url => REXML::XPath.first(item, "id").text }
  end
  
  return tables, content.headers[:x_ms_continuation_nexttablename]
end

#merge_entity(table_name, entity) ⇒ Object

Merge an existing entity on the current storage account. The Merge Entity operation updates an existing entity by updating the entity’s properties. This operation does not replace the existing entity, as the Update Entity operation does TODO: handle specific errors



95
96
97
98
99
# File 'lib/waz/tables/service.rb', line 95

def merge_entity(table_name, entity)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  response = execute(:merge, "#{table_name}(PartitionKey='#{entity[:partition_key]}',RowKey='#{entity[:row_key]}')", {}, default_headers.merge({'If-Match' => '*'}), generate_payload(table_name, entity))
  return parse_response(response)
end

#query(table_name, options = {}) ⇒ Object

Retrieves a set of entities on the current storage account for a given query. When the :top => n is passed it returns only the first n rows that match with the query Optional parameters:



128
129
130
131
132
133
134
135
136
# File 'lib/waz/tables/service.rb', line 128

def query(table_name, options = {})
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  query = {'$filter' => (options[:expression] or '') }
  query.merge!({ '$top' => options[:top] }) unless options[:top].nil?
  query.merge!(options[:continuation_token]) unless options[:continuation_token].nil?
  response = execute :get, "#{table_name}()", query, default_headers
  continuation_token = {'NextPartitionKey' => response.headers[:x_ms_continuation_nextpartitionkey], 'NextRowKey' => response.headers[:x_ms_continuation_nextrowkey]}
  parse_response(response, continuation_token)
end

#update_entity(table_name, entity) ⇒ Object

Update an existing entity on the current storage account. TODO: handle specific errors



85
86
87
88
89
# File 'lib/waz/tables/service.rb', line 85

def update_entity(table_name, entity)
  raise WAZ::Tables::InvalidTableName, table_name unless WAZ::Storage::ValidationRules.valid_table_name?(table_name)
  response = execute(:put, "#{table_name}(PartitionKey='#{entity[:partition_key]}',RowKey='#{entity[:row_key]}')", {}, default_headers.merge({'If-Match' => '*'}) , generate_payload(table_name, entity))
  return parse_response(response)
end