Skip to content

Instantly share code, notes, and snippets.

@maknoll
Created November 14, 2012 22:32
Show Gist options
  • Save maknoll/4075328 to your computer and use it in GitHub Desktop.
Save maknoll/4075328 to your computer and use it in GitHub Desktop.
require "azure"
require "net/http"
require 'active_support/inflector'
require "random-word"
Azure.configure do |config|
config.account_name = "martinmd"
config.access_key = "P9m7mlh1+jDAcRKvj8PV0pTRuL+2qHJ/YNdRn1YRRpfMwSNSh/QRFoqk3gMM5gqrSZcE3au13mvdbyfrd0vkUg=="
end
module AzureRecord
SIGNER = Azure::Tables::Auth::SharedKey.new
AUTH = Azure::Auth.new
class Base
attr :attributes
def initialize attributes = {}
@attributes = attributes
end
def self.all options = {}
query = options.map { |k,v| "#{(k.class == Symbol ? '$' + k.to_s : k)}=#{URI.escape v.to_s}"}.join '&'
request = Request.new :get, self.uri(query)
puts self.uri(query)
AUTH.sign request, SIGNER
response = request.request!
puts response.class
feed = Atom::Feed.load_feed(response.body)
entries = feed.entries.map do |entry|
attributes = entry.content.m_properties.inject({}) do |a, e|
a.merge e.name.underscore.to_sym => self.cast(e.content, e.attributes['type'])
end
self.new attributes
end
if response["x-ms-continuation-nextpartitionkey"] and not options[:top]
options.update "NextPartitionKey" => response["x-ms-continuation-nextpartitionkey"], "NextRowKey" => response["x-ms-continuation-nextrowkey"]
entries + self.all(options)
else
entries
end
end
def save
body = Atom::Entry.new do |entry|
entry.updated = Time.now.utc
entry.properties.merge(attributes.inject({}) { |a, (k, v)| a.merge k.to_s.camelize => v})
end
request = Request.new :post, self.class.uri, body.to_xml
AUTH.sign request, SIGNER
request.request!
end
def method_missing symbol
@attributes[symbol]
end
private
def self.uri query = nil
account_name = Azure.config.account_name
URI("http://#{account_name}.table.core.windows.net/#{self.to_s.pluralize}?#{query}")
end
def self.cast(serialized, type)
case type
when "Edm.Double"
serialized.to_f
when "Edm.DateTime"
Time.parse(serialized)
when "Edm.Int32", "Edm.Int64"
serialized.to_i
when "Edm.Boolean"
/true/i === serialized
else
serialized.to_s
end
end
end
class Request
attr :uri, :headers, :method, :body
def initialize method, uri, body = nil
@method = method
@uri = uri
@body = body
@headers = {}
calculate_headers
end
def request!
Net::HTTP.start uri.host, uri.port do |http|
request = Net::HTTP.const_get(method.to_s.capitalize).new uri.request_uri, headers
request.body = body if body
http.request request
end
end
private
def calculate_headers
headers["x-ms-date"] = Time.now.httpdate
headers["x-ms-version"] = "2011-08-18"
headers["DataServiceVersion"] = "2.0;NetFx"
headers["MaxDataServiceVersion"] = "2.0;NetFx"
if body
headers["Content-Type"] = "application/atom+xml; charset=utf-8"
headers["Content-Length"] = body.bytesize.to_s
headers["Content-MD5"] = Base64.strict_encode64(Digest::MD5.digest(body))
else
headers["Content-Length"] = "0"
end
end
end
end
class Employee < AzureRecord::Base
def self.median_salary_for country
e = Employee.all filter: " Position eq 'Developer' and PartitionKey ge '#{country}_PLZ00000' and PartitionKey lt '#{country}_PLZ999999'"
e.inject(0) { |a, x| a + x.salary } / e.length
end
def self.manager_in_germany
Employee.all(filter: "Position eq 'Manager' and PartitionKey ge 'Germany_PLZ30000' and PartitionKey lt 'Germany_PLZ80000'").length
end
end
class Range
def sample
self.to_a.sample
end
end
def generate range
range.map do |index|
prefix = ["USA", "UK", "Germany"].sample
plz = (10000..99999).sample
suffix = "_PLZ#{plz}"
Employee.new partition_key: prefix + suffix,
row_key: index.to_s,
name: "#{RandomWord.adjs.next.titleize} #{RandomWord.nouns.next.titleize}",
address: "#{RandomWord.adjs.next.titleize} Street, #{plz} #{RandomWord.nouns.next.titleize}",
salary: (20000..100000).sample,
position: ["Developer", "Manager", "Tester"].sample
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment