sunspot4r 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Josh Dennis
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ == Sunspot4R
2
+
3
+ You should document your project here.
data/README.markdown ADDED
@@ -0,0 +1,21 @@
1
+ # Daxko_Connect
2
+
3
+ Ruby wrapper for [DAXKO Connect](http://www.daxko.com/connect).
4
+
5
+ Based on the original Sunspot4R written by Tony Summerville's (tony.summerville@daxko.com).
6
+
7
+ ## Installation
8
+
9
+ sudo gem install daxko_connect
10
+
11
+ ## Usage
12
+
13
+ ### Authenticate
14
+
15
+ ### Examples
16
+
17
+ ## TODO
18
+
19
+ ## Copyright
20
+
21
+ Copyright (c) 2010 [Josh Dennis](http://joshdennis.net). See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "sunspot4r"
8
+ gem.summary = %Q{Ruby wrapper for DAXKO Sunspot}
9
+ gem.description = %Q{Ruby wrapper for DAXKO Sunspot}
10
+ gem.email = "dennijo@gmail.com"
11
+ gem.homepage = "http://github.com/dennijo/sunspot4R"
12
+ gem.authors = ['Tony Summerville', 'Josh Dennis']
13
+ gem.files = FileList["[A-Z]*", "{lib,test}/**/*"]
14
+ gem.add_dependency('savon', '>= 0.7.8')
15
+ gem.add_dependency('shoulda')
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'test'
25
+ test.ruby_opts << '-rubygems'
26
+ test.pattern = 'test/**/*_test.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+ task :test => :check_dependencies
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "daxko_connect #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/Sunspot4R.gemspec ADDED
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{sunspot4r}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tony Summerville", "Josh Dennis"]
12
+ s.date = %q{2010-08-04}
13
+ s.description = %q{Ruby wrapper for DAXKO Sunspot}
14
+ s.email = %q{dennijo@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README",
18
+ "README.markdown"
19
+ ]
20
+ s.files = [
21
+ "LICENSE",
22
+ "README",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "Sunspot4R.gemspec",
26
+ "VERSION",
27
+ "lib/ext/savon/request.rb",
28
+ "lib/sunspot4r.rb",
29
+ "lib/sunspot4r/base_sunspot_service_client.rb",
30
+ "lib/sunspot4r/object_service_client.rb",
31
+ "lib/sunspot4r/security_service_client.rb",
32
+ "lib/sunspot4r/system_service_client.rb",
33
+ "test/config.yml",
34
+ "test/object_service_client_test.rb",
35
+ "test/security_service_client_test.rb",
36
+ "test/system_service_client_test.rb",
37
+ "test/test_helper.rb",
38
+ "test/test_suite.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/dennijo/sunspot4R}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.6}
44
+ s.summary = %q{Ruby wrapper for DAXKO Sunspot}
45
+ s.test_files = [
46
+ "test/object_service_client_test.rb",
47
+ "test/security_service_client_test.rb",
48
+ "test/system_service_client_test.rb",
49
+ "test/test_helper.rb",
50
+ "test/test_suite.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<savon>, [">= 0.7.8"])
59
+ s.add_runtime_dependency(%q<shoulda>, [">= 0"])
60
+ else
61
+ s.add_dependency(%q<savon>, [">= 0.7.8"])
62
+ s.add_dependency(%q<shoulda>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<savon>, [">= 0.7.8"])
66
+ s.add_dependency(%q<shoulda>, [">= 0"])
67
+ end
68
+ end
69
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,27 @@
1
+ module Savon
2
+ class Request
3
+
4
+ # FIXME
5
+ # Must add a double quote (") to the soap action for Sunspot to recognize it properly
6
+ def soap_headers
7
+ { "Content-Type" => ContentType[@soap.version], "SOAPAction" => "\"#{@soap.action}\"" }
8
+ end
9
+
10
+ # Returns the Net::HTTP object.
11
+ #
12
+ # Changed the verify mode to "VERIFY_NONE" to get rid of "warning: peer certificate
13
+ # won't be verified in this SSL session" before each request.
14
+ def http
15
+ unless @http
16
+ @http = Net::HTTP::Proxy(@proxy.host, @proxy.port).new @endpoint.host, @endpoint.port
17
+ @http.read_timeout = 300
18
+ @http.ssl_client_auth(:verify_mode => OpenSSL::SSL::VERIFY_NONE)
19
+ end
20
+ @http
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ # Turning off logging improves performance
27
+ Savon::Request.log = false
data/lib/sunspot4r.rb ADDED
@@ -0,0 +1,23 @@
1
+ # The main Sunspot4R module, serving as a namespace for all Sunspot services.
2
+
3
+ module Sunspot4R
4
+
5
+ NAME = 'SUNSPOT4R'
6
+ VERSION = '0.1'
7
+ USER_AGENT = "%s %s" % [NAME, VERSION]
8
+
9
+ end
10
+
11
+ # Gem dependencies.
12
+ require 'rubygems'
13
+ require 'savon'
14
+ require 'nokogiri'
15
+ require 'shoulda'
16
+
17
+ # Extensions & overrides.
18
+ require 'ext/savon/request'
19
+
20
+ # Core files.
21
+ require 'sunspot4r/system_service_client'
22
+ require 'sunspot4r/security_service_client'
23
+ require 'sunspot4r/object_service_client'
@@ -0,0 +1,77 @@
1
+ module Sunspot4R
2
+
3
+ # = Sunspot4R::BaseSunspotServiceClient
4
+ #
5
+ # Sunspot4R::BaseSunspotServiceClient is service class client that all other
6
+ # Sunspot services extend.
7
+ class BaseSunspotServiceClient < Savon::Client
8
+
9
+ # Name of the Sunspot service. Used to build SOAPAction URLs dynamically.
10
+ def service_name
11
+ '<add service_name>'
12
+ end
13
+
14
+ attr_accessor :base_uri
15
+
16
+ # Optionally pass in the session_guid which will then be placed in the soap
17
+ # package header for each request.
18
+ def initialize(base_url, options = {})
19
+ @session_guid = options.delete(:session_guid)
20
+ endpoint = "#{base_url}/Partner/#{service_name}"
21
+
22
+ super endpoint, options
23
+ #super endpoint, :proxy => 'http://127.0.0.1:8888'
24
+ end
25
+
26
+ private
27
+
28
+ # Same as +super+ but also conveniently enhances a few things:
29
+ # * Capitalizes & adds a base URL to the action
30
+ # * Capitalizes the input
31
+ # * Adds the +xmlns:wsdl+ namespace
32
+ # * Adds SessionIdentifier+ if the +session_guid+ is not nil
33
+ # * Adds the +xmlns:imp+ "Import" namespace
34
+ def setup_objects(action, input, &block)
35
+ super add_base_url_to_action(action), capitalize_first_letter(input), &block
36
+ add_namespace
37
+ add_imports_namespace
38
+ add_session_identifier
39
+ end
40
+
41
+ # Adds the needed base url to the action & captializes the action name so
42
+ # Sunspot will recognize it properly.
43
+ def add_base_url_to_action(action)
44
+ "http://sunspot.arcsolutionsinc.com/Services/I#{service_name}/#{capitalize_first_letter(action)}"
45
+ end
46
+
47
+ # Capitalizes the first letter of a string but leaves everything else the same,
48
+ # unlike string.capitalize which lowercases the rest of the letters in a word.
49
+ # Needed because SOAP actions & inputs CamelCase.
50
+ def capitalize_first_letter(str)
51
+ str.gsub(/^[a-z]/) { |a| a.upcase }
52
+ end
53
+
54
+ # Adds the basic namespace to the SOAP request if one has not already been set.
55
+ def add_namespace
56
+ unless @soap.namespaces.include?("xmlns:wsdl")
57
+ @soap.namespace = 'http://sunspot.arcsolutionsinc.com/Services'
58
+ end
59
+ end
60
+
61
+ # Adds the +xmlns:imp+ to the soap request if the +session_guid+ is not nil.
62
+ def add_imports_namespace
63
+ unless @session_guid.nil? || @soap.nil?
64
+ @soap.namespaces["xmlns:imp"] = "http://sunspot.arcsolutionsinc.com/Services/Imports"
65
+ end
66
+ end
67
+
68
+ # Adds the +imp:SessionIdentifier+ to the soap request if the +session_guid+
69
+ # is not nil.
70
+ def add_session_identifier
71
+ unless @session_guid.nil? || @soap.nil?
72
+ @soap.header = "<imp:SessionIdentifier Id=\"#{@session_guid}\" />"
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,145 @@
1
+ require 'sunspot4r/base_sunspot_service_client'
2
+
3
+ module Sunspot4R
4
+
5
+ # == Sunspot::ObjectServiceClient
6
+ #
7
+ # TODO - Description
8
+ class ObjectServiceClient < BaseSunspotServiceClient
9
+
10
+ # Name of the Sunspot service. Used to build SOAPAction URLs dynamically.
11
+ def service_name
12
+ 'ObjectService'
13
+ end
14
+
15
+ # Returns a list of all Polaris objects accessible to the current user.
16
+ #
17
+ # Response body XML (abbreviated):
18
+ #
19
+ # <GetAvailableObjectsResponse xmlns="http://sunspot.arcsolutionsinc.com/Services">
20
+ # <GetAvailableObjectsResult xmlns:a="http://ARC.Polaris.Sunspot.Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
21
+ # <ApiFaults xmlns="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.API.Results" xmlns:b="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.API"/>
22
+ # <Errors xmlns="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.API.Results" xmlns:b="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.Types"/>
23
+ # <Exception i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.API.Results" xmlns:b="http://schemas.datacontract.org/2004/07/System"/>
24
+ # <Success xmlns="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.API.Results">true</Success>
25
+ # <a:Objects xmlns:b="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.Types">
26
+ # <b:NameValuePair>
27
+ # <b:Name>Advertising Rate</b:Name>
28
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">AdvertisingRate</b:Value>
29
+ # </b:NameValuePair>
30
+ # <b:NameValuePair>
31
+ # <b:Name>Career Center Bundle Product</b:Name>
32
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">CareerCenterBundleProduct</b:Value>
33
+ # </b:NameValuePair>
34
+ # <b:NameValuePair>
35
+ # <b:Name>Career Center Coupon</b:Name>
36
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">CareerCenterCoupon</b:Value>
37
+ # </b:NameValuePair>
38
+ # <b:NameValuePair>
39
+ # <b:Name>Tax Product</b:Name>
40
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">TaxProduct</b:Value>
41
+ # </b:NameValuePair>
42
+ # </a:Objects>
43
+ # <a:_objects xmlns:b="http://schemas.datacontract.org/2004/07/ARC.Polaris.Common.Types">
44
+ # <b:NameValuePair>
45
+ # <b:Name>Advertising Rate</b:Name>
46
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">AdvertisingRate</b:Value>
47
+ # </b:NameValuePair>
48
+ # <b:NameValuePair>
49
+ # <b:Name>Career Center Bundle Product</b:Name>
50
+ # <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">CareerCenterBundleProduct</b:Value>
51
+ # </b:NameValuePair>
52
+ # </a:_objects>
53
+ # </GetAvailableObjectsResult>
54
+ # </GetAvailableObjectsResponse>
55
+ def available_objects(association_guid, base_object)
56
+ response = call :get_available_objects! do |soap|
57
+ soap.body = {
58
+ "wsdl:associationGuid" => association_guid,
59
+ "wsdl:baseObject" => base_object,
60
+ :order! => ["wsdl:associationGuid", "wsdl:baseObject"]
61
+ }
62
+ end
63
+ response.to_hash[:get_available_objects_response][:get_available_objects_result]
64
+ end
65
+
66
+ # Loads an object from the system by its GUID.
67
+ #
68
+ # This operation will return either a single object or a null value back.
69
+ # Note that the security placed upon the logged in user is enforced through
70
+ # this operation – if you query an object that your logged in Sunspot
71
+ # account does not have access to, expect an API error to be returned.
72
+ #
73
+ # This operation will return a single PolarisObject that represents the
74
+ # object you are looking for, or null if non were found.
75
+ #
76
+ def query_by_guid(guid)
77
+ response = call :query_by_guid! do |soap|
78
+ soap.body = {
79
+ "wsdl:guid" => guid
80
+ }
81
+ end
82
+ response.to_hash[:query_by_guid_response][:query_by_guid_result]
83
+ end
84
+
85
+ # #Upsert #Saves an object into the system, inserting it if it does not
86
+ # exist and updating it if it does. #This is your general purpose
87
+ # SaveOrUpdate operation that determines whether or not the object #exists
88
+ # and updates it if it does, inserts it if it doesn’t. The system uses the
89
+ # read-only #RepositoryKey property of the PolarisObject to determine
90
+ # whether or not it exists in the system. #This operation will return an
91
+ # updated version of the object that was saved. If the object was new, #then
92
+ # this updated version will contain the generated GUID and any other
93
+ # automatically generated information.
94
+ def upsert
95
+
96
+ end
97
+
98
+ def describe_object(association_guid, base_object)
99
+ response = call :describe_p_object! do |soap|
100
+ soap.body = {
101
+ "wsdl:associationGuid" => association_guid,
102
+ "wsdl:objectName" => base_object,
103
+ :order! => ["wsdl:associationGuid", "wsdl:objectName"]
104
+ }
105
+ end
106
+ response.to_hash[:describe_p_object_response][:describe_p_object_result]
107
+ end
108
+
109
+ def get_all(association_guid, base_object)
110
+ response = call :get_all! do |soap|
111
+ soap.body = {
112
+ "wsdl:associationGuid" => association_guid,
113
+ "wsdl:objectName" => base_object,
114
+ :order! => ["wsdl:associationGuid", "wsdl:objectName"]
115
+ }
116
+ end
117
+ response.to_hash[:get_all_response][:get_all_result]
118
+ end
119
+
120
+ def query(association_guid, query, first = nil, max = nil)
121
+ unless first.nil? || max.nil?
122
+ response = call :query! do |soap|
123
+ soap.body = {
124
+ "wsdl:associationGuid" => association_guid,
125
+ "wsdl:query" => query,
126
+ "wsdl:firstResult" => first,
127
+ "wsdl:maxResults" => max,
128
+ :order! => ["wsdl:associationGuid", "wsdl:query", "wsdl:firstResult", "wsdl:maxResults"]
129
+ }
130
+ end
131
+ else
132
+ response = call :query! do |soap|
133
+ soap.body = {
134
+ "wsdl:associationGuid" => association_guid,
135
+ "wsdl:query" => query,
136
+ :order! => ["wsdl:associationGuid", "wsdl:query"]
137
+ }
138
+ end
139
+ end
140
+ response.to_hash[:query_response][:query_result]
141
+ #response.to_xml
142
+ end
143
+ end
144
+
145
+ end