sds-rest 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +30 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +62 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +77 -0
- data/config/requirements.rb +15 -0
- data/lib/sds-activeresource.rb +183 -0
- data/lib/sds-rest.rb +255 -0
- data/lib/sds-rest/version.rb +10 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/authority_spec.rb +35 -0
- data/spec/blob_spec.rb +53 -0
- data/spec/container_spec.rb +46 -0
- data/spec/entity_spec.rb +118 -0
- data/spec/sdsactiveresource_spec.rb +88 -0
- data/spec/sdsconnection_spec.rb +49 -0
- data/spec/spec_helper.rb +24 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +85 -0
- data/website/index.txt +81 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +108 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
config/hoe.rb
|
7
|
+
config/requirements.rb
|
8
|
+
lib/sds-activeresource.rb
|
9
|
+
lib/sds-rest.rb
|
10
|
+
lib/sds-rest/version.rb
|
11
|
+
script/console
|
12
|
+
script/destroy
|
13
|
+
script/generate
|
14
|
+
script/txt2html
|
15
|
+
setup.rb
|
16
|
+
spec/authority_spec.rb
|
17
|
+
spec/blob_spec.rb
|
18
|
+
spec/container_spec.rb
|
19
|
+
spec/entity_spec.rb
|
20
|
+
spec/sdsactiveresource_spec.rb
|
21
|
+
spec/sdsconnection_spec.rb
|
22
|
+
spec/spec_helper.rb
|
23
|
+
tasks/deployment.rake
|
24
|
+
tasks/environment.rake
|
25
|
+
tasks/website.rake
|
26
|
+
website/index.html
|
27
|
+
website/index.txt
|
28
|
+
website/javascripts/rounded_corners_lite.inc.js
|
29
|
+
website/stylesheets/screen.css
|
30
|
+
website/template.html.erb
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
= sds-rest
|
2
|
+
|
3
|
+
* FIX (url)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
A ruby library for accessing the SDS REST interface.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
SDSRest Library
|
12
|
+
Active Resource Adapter
|
13
|
+
|
14
|
+
== SYNOPSIS:
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
== REQUIREMENTS:
|
19
|
+
|
20
|
+
gem install uuidtools
|
21
|
+
|
22
|
+
== INSTALL:
|
23
|
+
|
24
|
+
If you are new to ruby follow these instructions:
|
25
|
+
|
26
|
+
1) Install Ruby with the One-Click Installer - http://rubyforge.org/frs/download.php/29263/ruby186-26.exe
|
27
|
+
2) Install Ruby Gems - http://rubyforge.org/frs/download.php/38647/rubygems-1.2.0.zip
|
28
|
+
3) Install Rails - cmd line => gem install rails --include-dependencies
|
29
|
+
4) Install UUIDTools - cmd line => gem install uuidtools
|
30
|
+
|
31
|
+
== LICENSE:
|
32
|
+
|
33
|
+
Copyright (c) 2008 Microsoft
|
34
|
+
|
35
|
+
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
|
36
|
+
1. Definitions
|
37
|
+
|
38
|
+
The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the same meaning here as under U.S. copyright law.
|
39
|
+
|
40
|
+
A “contribution” is the original software, or any additions or changes to the software.
|
41
|
+
|
42
|
+
A “contributor” is any person that distributes its contribution under this license.
|
43
|
+
|
44
|
+
“Licensed patents” are a contributor’s patent claims that read directly on its contribution.
|
45
|
+
2. Grant of Rights
|
46
|
+
|
47
|
+
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
|
48
|
+
|
49
|
+
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
|
50
|
+
3. Conditions and Limitations
|
51
|
+
|
52
|
+
(A) No Trademark License- This license does not grant you rights to use any contributors’ name, logo, or trademarks.
|
53
|
+
|
54
|
+
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
|
55
|
+
|
56
|
+
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
|
57
|
+
|
58
|
+
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
|
59
|
+
|
60
|
+
(E) The software is licensed “as-is.” You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
|
61
|
+
|
62
|
+
See FAQ.html for answers to frequently asked questions about this license.
|
data/Rakefile
ADDED
data/config/hoe.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'sds-rest/version'
|
2
|
+
|
3
|
+
AUTHOR = 'James Avery' # can also be an array of Authors
|
4
|
+
EMAIL = "javery@infozerk.com"
|
5
|
+
DESCRIPTION = "description of gem"
|
6
|
+
GEM_NAME = 'sds-rest' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'sdsrest' # The unix name for your project
|
8
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
EXTRA_DEPENDENCIES = [
|
11
|
+
# ['activesupport', '>= 1.3.1']
|
12
|
+
] # An array of rubygem dependencies [name, version]
|
13
|
+
EXTRA_DEV_DEPENDENCIES = [
|
14
|
+
# ['rspec', '>= 1.1.5']
|
15
|
+
] # An array of rubygem dependencies [name, version]
|
16
|
+
|
17
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
18
|
+
@config = nil
|
19
|
+
RUBYFORGE_USERNAME = "unknown"
|
20
|
+
def rubyforge_username
|
21
|
+
unless @config
|
22
|
+
begin
|
23
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
24
|
+
rescue
|
25
|
+
puts <<-EOS
|
26
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
27
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
28
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
29
|
+
EOS
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
REV = nil
|
38
|
+
# UNCOMMENT IF REQUIRED:
|
39
|
+
# REV = YAML.load(`svn info`)['Revision']
|
40
|
+
VERS = SDSRest::VERSION::STRING + (REV ? ".#{REV}" : "")
|
41
|
+
RDOC_OPTS = ['--quiet', '--title', 'sds-rest documentation',
|
42
|
+
"--opname", "index.html",
|
43
|
+
"--line-numbers",
|
44
|
+
"--main", "README",
|
45
|
+
"--inline-source"]
|
46
|
+
|
47
|
+
class Hoe
|
48
|
+
def extra_deps
|
49
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
50
|
+
@extra_deps
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generate all the Rake tasks
|
55
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
56
|
+
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
57
|
+
p.developer(AUTHOR, EMAIL)
|
58
|
+
p.description = DESCRIPTION
|
59
|
+
p.summary = DESCRIPTION
|
60
|
+
p.url = HOMEPATH
|
61
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
62
|
+
p.test_globs = ["spec/**/*_spec.rb"]
|
63
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
64
|
+
|
65
|
+
# == Optional
|
66
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
67
|
+
p.extra_deps = EXTRA_DEPENDENCIES
|
68
|
+
p.extra_dev_deps = EXTRA_DEV_DEPENDENCIES
|
69
|
+
|
70
|
+
p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
71
|
+
end
|
72
|
+
|
73
|
+
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
74
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
75
|
+
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
76
|
+
$hoe.rsync_args = '-av --delete --ignore-errors'
|
77
|
+
$hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
%w[rake hoe newgem rubigen].each do |req_gem|
|
6
|
+
begin
|
7
|
+
require req_gem
|
8
|
+
rescue LoadError
|
9
|
+
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
|
+
puts "Installation: gem install #{req_gem} -y"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activesupport'
|
3
|
+
require 'activeresource'
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'uri'
|
6
|
+
require 'sds-rest'
|
7
|
+
|
8
|
+
module SDSActiveResource
|
9
|
+
|
10
|
+
class Base < ActiveResource::Base
|
11
|
+
|
12
|
+
def self.connection(refresh = false)
|
13
|
+
@connection = SDSConnection.new(super.site, super.format) if refresh || @connection.nil?
|
14
|
+
@connection.user = user
|
15
|
+
@connection.password = password
|
16
|
+
@connection
|
17
|
+
end
|
18
|
+
|
19
|
+
#we don't want to create XML, we want to pass the attributes directly to the SDS service where the XML can be created
|
20
|
+
def to_xml(options={})
|
21
|
+
newattributes = {}
|
22
|
+
newattributes.merge! attributes
|
23
|
+
newattributes["entityname"] = self.class.element_name
|
24
|
+
newattributes
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.query(query)
|
28
|
+
instantiate_collection(@connection.query(collection_path(), query))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SDSConnection < ActiveResource::Connection
|
33
|
+
|
34
|
+
def service
|
35
|
+
@service = SDSRest::Service.new :username => user, :password => password, :authority => get_authority(site), :url => get_url(site) if @service.nil?
|
36
|
+
@service
|
37
|
+
end
|
38
|
+
|
39
|
+
def query(path, query)
|
40
|
+
container = get_container(path)
|
41
|
+
query.gsub!(/AND/i, "%26%26 ")
|
42
|
+
response = service.query(container, query)
|
43
|
+
entity = REXML::Document.new(response.body)
|
44
|
+
entities = []
|
45
|
+
|
46
|
+
entity.root().elements.each { |element|
|
47
|
+
options = {}
|
48
|
+
element.elements.each { |element2|
|
49
|
+
options[element2.name] = parse_value(element.attributes["xsi:type"], element2.text)
|
50
|
+
}
|
51
|
+
entities.push(options)
|
52
|
+
}
|
53
|
+
|
54
|
+
entities
|
55
|
+
end
|
56
|
+
|
57
|
+
def post(path, body = '', headers = {})
|
58
|
+
container = get_container(path)
|
59
|
+
response = service.create_entity(container, body["entityname"], body["Id"], body)
|
60
|
+
response['location'] = "test/" + body["Id"].to_s
|
61
|
+
response
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete(path, body = '', headers = {})
|
65
|
+
container = get_container(path)
|
66
|
+
id = get_id(path)
|
67
|
+
service.delete_entity(container, id)
|
68
|
+
end
|
69
|
+
|
70
|
+
def put(path, body = '', headers = {})
|
71
|
+
container = get_container(path)
|
72
|
+
response = service.update_entity(container, body["name"], body["Id"], nil, body)
|
73
|
+
response['location'] = "test/" + body["Id"].to_s
|
74
|
+
response
|
75
|
+
end
|
76
|
+
|
77
|
+
def get(path, headers = {})
|
78
|
+
container = get_container(path)
|
79
|
+
entityname = get_entity(path)
|
80
|
+
id = get_id(path)
|
81
|
+
if(id.nil?)
|
82
|
+
query = 'from e in entities where e.Kind == "' + entityname.singularize + '" select e'
|
83
|
+
response = service.query(container, query)
|
84
|
+
entity = REXML::Document.new(response.body)
|
85
|
+
entities = []
|
86
|
+
|
87
|
+
entity.root().elements.each { |element|
|
88
|
+
options = {}
|
89
|
+
element.elements.each { |element2|
|
90
|
+
options[element2.name] = parse_value(element2.attributes["xsi:type"], element2.text)
|
91
|
+
}
|
92
|
+
entities.push(options)
|
93
|
+
}
|
94
|
+
|
95
|
+
entities
|
96
|
+
else
|
97
|
+
|
98
|
+
response = service.get_entity(container, id)
|
99
|
+
|
100
|
+
entity = REXML::Document.new(response.body)
|
101
|
+
|
102
|
+
options = {}
|
103
|
+
entity.root().elements.each { |element|
|
104
|
+
options[element.name] = parse_value(element.attributes["xsi:type"], element.text)
|
105
|
+
}
|
106
|
+
options['id'] = id
|
107
|
+
options
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_authority(path)
|
113
|
+
splitpath = URI::split(path.to_s)
|
114
|
+
splitpath[2].split('.')[0]
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_url(path)
|
118
|
+
splitpath = URI::split(path.to_s)
|
119
|
+
host = splitpath[2]
|
120
|
+
host[get_authority(path) + "."] = ""
|
121
|
+
host
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_params(path)
|
125
|
+
puts path
|
126
|
+
if(path.include? "?")
|
127
|
+
params = path.split('?')[1]
|
128
|
+
params || ""
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_container(path)
|
133
|
+
container = path.to_s.split('/')[1]
|
134
|
+
|
135
|
+
if(container.nil?)
|
136
|
+
raise "no container found"
|
137
|
+
end
|
138
|
+
container
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_entity(path)
|
142
|
+
path.delete! '.xml'
|
143
|
+
entity = path.split('/')[2]
|
144
|
+
|
145
|
+
if(entity.include? "?")
|
146
|
+
entity = entity.split('?')[0]
|
147
|
+
end
|
148
|
+
|
149
|
+
if(entity.nil?)
|
150
|
+
raise "no entity found"
|
151
|
+
end
|
152
|
+
entity
|
153
|
+
end
|
154
|
+
|
155
|
+
def parse_value(type, value)
|
156
|
+
if(type == "x:decimal")
|
157
|
+
if(value.include?("."))
|
158
|
+
Float(value)
|
159
|
+
else
|
160
|
+
Integer(value)
|
161
|
+
end
|
162
|
+
elsif(type == "x:boolean")
|
163
|
+
Boolean(value)
|
164
|
+
elsif(type == "x:dateTime")
|
165
|
+
DateTime.parse(value)
|
166
|
+
else
|
167
|
+
value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def get_id(path)
|
172
|
+
path.delete! '.xml'
|
173
|
+
path.to_s.split('/')[3]
|
174
|
+
end
|
175
|
+
|
176
|
+
def Boolean(string)
|
177
|
+
return true if string == true || string =~ /^true$/i
|
178
|
+
return false if string == false || string.nil? || string =~ /^false$/i
|
179
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{string}\"")
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
data/lib/sds-rest.rb
ADDED
@@ -0,0 +1,255 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rexml/document'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module SDSRest
|
6
|
+
|
7
|
+
ssds_config = "#{RAILS_ROOT}/config/ssds.yml"
|
8
|
+
|
9
|
+
if File.exist?(ssds_config)
|
10
|
+
SSDSCONFIG = YAML.load_file(ssds_config)[RAILS_ENV]
|
11
|
+
ENV['username'] = SSDSCONFIG['username']
|
12
|
+
ENV['password'] = SSDSCONFIG['password']
|
13
|
+
ENV['url'] = SSDSCONFIG['url']
|
14
|
+
ENV['authority'] = SSDSCONFIG['authority']
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class Service
|
19
|
+
|
20
|
+
def initialize(options={})
|
21
|
+
@username = options[:username] || ENV['username']
|
22
|
+
@password = options[:password] || ENV['password']
|
23
|
+
@url = options[:url] || ENV['url']
|
24
|
+
@authority = options[:authority] || ENV['authority']
|
25
|
+
end
|
26
|
+
|
27
|
+
def authority=(value)
|
28
|
+
@authority = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_authority(authority)
|
32
|
+
request_xml = REXML::Document.new()
|
33
|
+
request_xml.add_element('s:Authority')
|
34
|
+
request_xml.root().add_attribute('xmlns:s', 'http://schemas.microsoft.com/sitka/2008/03/')
|
35
|
+
request_xml.root().add_element("s:Id")
|
36
|
+
request_xml.root().elements["s:Id"].text = authority
|
37
|
+
req = create_post(request_xml)
|
38
|
+
execute_request req
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_authority(authority)
|
42
|
+
@authority = authority
|
43
|
+
get(get_request_url)
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_container(container)
|
47
|
+
request_xml = REXML::Document.new()
|
48
|
+
request_xml.add_element('s:Container')
|
49
|
+
request_xml.root().add_attribute('xmlns:s', 'http://schemas.microsoft.com/sitka/2008/03/')
|
50
|
+
request_xml.root().add_element("s:Id")
|
51
|
+
request_xml.root().elements["s:Id"].text = container
|
52
|
+
req = create_post(request_xml)
|
53
|
+
execute_request req
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_container(container)
|
57
|
+
delete(get_request_url(container))
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_container(container)
|
61
|
+
get(get_request_url(container))
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_entity(container, entity, id, options={})
|
65
|
+
request_xml = REXML::Document.new()
|
66
|
+
request_xml.add_element(entity)
|
67
|
+
request_xml.root().add_attribute('xmlns:s', 'http://schemas.microsoft.com/sitka/2008/03/')
|
68
|
+
request_xml.root().add_attribute('xmlns:x', 'http://www.w3.org/2001/XMLSchema')
|
69
|
+
request_xml.root().add_attribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' )
|
70
|
+
request_xml.root().add_element('s:Id')
|
71
|
+
request_xml.root().elements['s:Id'].text = id
|
72
|
+
|
73
|
+
options.each { |key, value|
|
74
|
+
request_xml.root().add_element(key.to_s)
|
75
|
+
request_xml.root().elements[key.to_s].add_attribute('xsi:type', infer_type(value))
|
76
|
+
request_xml.root().elements[key.to_s].text = value
|
77
|
+
}
|
78
|
+
req = create_post(request_xml, container)
|
79
|
+
execute_request req
|
80
|
+
end
|
81
|
+
|
82
|
+
# passing in a version number means that SSDS will only delete the entity if the version
|
83
|
+
# number equals the current version number.
|
84
|
+
def delete_entity(container, id, version = nil)
|
85
|
+
url = get_request_url(container, id)
|
86
|
+
delete(url, version)
|
87
|
+
end
|
88
|
+
|
89
|
+
# passing in a version number means that SSDS will only delete the entity if the version
|
90
|
+
# number equals the current version number.
|
91
|
+
def get_entity(container, id, version = nil)
|
92
|
+
url = get_request_url(container, id)
|
93
|
+
get(url, version)
|
94
|
+
end
|
95
|
+
|
96
|
+
# passing in a version number means that SSDS will only delete the entity if the version
|
97
|
+
# number equals the current version number.
|
98
|
+
def update_entity(container, entity, id, version = nil, options={})
|
99
|
+
results = get_entity container, id
|
100
|
+
entity = REXML::Document.new(results.body)
|
101
|
+
|
102
|
+
options.each { |key, value|
|
103
|
+
if(entity.root().elements[key.to_s].nil?)
|
104
|
+
entity.root().add_element(key.to_s)
|
105
|
+
entity.root().elements[key.to_s].add_attribute('xsi:type', infer_type(value))
|
106
|
+
end
|
107
|
+
|
108
|
+
entity.root().elements[key.to_s].text = value
|
109
|
+
}
|
110
|
+
url = get_request_url(container, id)
|
111
|
+
put(url, entity, version)
|
112
|
+
end
|
113
|
+
|
114
|
+
#sends a query using the SSDS query syntax
|
115
|
+
#
|
116
|
+
# examples:
|
117
|
+
# from c in entities select c - selects all entities
|
118
|
+
# from c in entities where c.Kind = 'Car' select c - select all entities of type 'Car'
|
119
|
+
# from c in entities where c["Make"] = 'Toyota' - select all entities with property Make that equals Toyota
|
120
|
+
def query(container, query)
|
121
|
+
url = get_request_url(container) + "?q=" + URI.escape(query)
|
122
|
+
get(url)
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_blob(container, blob, id)
|
126
|
+
url = get_request_url(container)
|
127
|
+
req = Net::HTTP::Post.new(url)
|
128
|
+
req.content_type = 'text'
|
129
|
+
req.content_length = blob.to_s.size.to_s
|
130
|
+
req['slug'] = id
|
131
|
+
req.basic_auth @username, @password
|
132
|
+
req.body = blob.to_s
|
133
|
+
execute_request(req)
|
134
|
+
end
|
135
|
+
|
136
|
+
def update_blob(container, blob, id)
|
137
|
+
url = get_request_url(container, id)
|
138
|
+
req = Net::HTTP::Put.new(url)
|
139
|
+
req.content_type = 'text'
|
140
|
+
req.content_length = blob.to_s.size.to_s
|
141
|
+
req['slug'] = id
|
142
|
+
req.basic_auth @username, @password
|
143
|
+
req.body = blob.to_s
|
144
|
+
execute_request(req)
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_blob(container, id)
|
148
|
+
delete(get_request_url(container, id))
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_blob(container, id)
|
152
|
+
get(get_request_url(container, id))
|
153
|
+
end
|
154
|
+
|
155
|
+
def infer_type(value)
|
156
|
+
if(value.is_a?(Integer) || value.is_a?(Float))
|
157
|
+
'x:decimal'
|
158
|
+
elsif(value.is_a?(true.class) || value.is_a?(false.class))
|
159
|
+
'x:boolean'
|
160
|
+
elsif(value.is_a?(DateTime))
|
161
|
+
'x:dateTime'
|
162
|
+
else
|
163
|
+
'x:string'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
private
|
169
|
+
#execute a request
|
170
|
+
def execute_request(req)
|
171
|
+
Net::HTTP.new(get_url).start {|http|
|
172
|
+
response = http.request(req)
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
#gets the base url to send the request to
|
177
|
+
def get_url
|
178
|
+
url = @url
|
179
|
+
if(!@authority.nil?)
|
180
|
+
url = @authority + "." + @url
|
181
|
+
end
|
182
|
+
|
183
|
+
url
|
184
|
+
end
|
185
|
+
|
186
|
+
#sends an HTTP delete request to SSDS
|
187
|
+
def delete(url, version = nil)
|
188
|
+
req = Net::HTTP::Delete.new(url)
|
189
|
+
req.content_type = 'application/x-ssds+xml'
|
190
|
+
|
191
|
+
if(!version.nil?)
|
192
|
+
req['if-match'] = version;
|
193
|
+
end
|
194
|
+
|
195
|
+
req.basic_auth @username, @password
|
196
|
+
execute_request(req)
|
197
|
+
end
|
198
|
+
|
199
|
+
#sends an HTTP get request to SSDS
|
200
|
+
def get(url, version = nil)
|
201
|
+
req = Net::HTTP::Get.new(url)
|
202
|
+
req.content_type = 'application/x-ssds+xml'
|
203
|
+
|
204
|
+
if(!version.nil?)
|
205
|
+
req['if-none-match'] = version;
|
206
|
+
end
|
207
|
+
|
208
|
+
req.basic_auth @username, @password
|
209
|
+
execute_request(req)
|
210
|
+
end
|
211
|
+
|
212
|
+
#sends an HTTP put request to SSDS
|
213
|
+
def put(url, xml, version = nil)
|
214
|
+
req = Net::HTTP::Put.new(url)
|
215
|
+
req.content_type = 'application/x-ssds+xml'
|
216
|
+
|
217
|
+
if(!version.nil?)
|
218
|
+
req['if-match'] = version;
|
219
|
+
end
|
220
|
+
|
221
|
+
req.content_length = xml.to_s.size.to_s
|
222
|
+
req.basic_auth @username, @password
|
223
|
+
req.body = xml.to_s
|
224
|
+
execute_request(req)
|
225
|
+
end
|
226
|
+
|
227
|
+
#determines the correct URL to use for a SSDS request
|
228
|
+
def get_request_url(container = nil, id = nil)
|
229
|
+
url = '/v1/'
|
230
|
+
|
231
|
+
#add the container to the url
|
232
|
+
if(!container.nil?)
|
233
|
+
url = url + container
|
234
|
+
end
|
235
|
+
|
236
|
+
#add the id to the end of the url if it is present
|
237
|
+
if(!id.nil?)
|
238
|
+
url = url + "/" + id.to_s
|
239
|
+
end
|
240
|
+
|
241
|
+
url
|
242
|
+
end
|
243
|
+
|
244
|
+
def create_post(xml, container=nil)
|
245
|
+
url = get_request_url(container)
|
246
|
+
req = Net::HTTP::Post.new(url)
|
247
|
+
req.content_type = 'application/x-ssds+xml'
|
248
|
+
req.content_length = xml.to_s.size.to_s
|
249
|
+
req.basic_auth @username, @password
|
250
|
+
req.body = xml.to_s
|
251
|
+
req
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
end
|