salsalabs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +1 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +9 -0
  6. data/Gemfile +2 -0
  7. data/README.md +27 -0
  8. data/Rakefile +49 -0
  9. data/lib/salsa_labs/api_response.rb +55 -0
  10. data/lib/salsa_labs/authentication_response.rb +44 -0
  11. data/lib/salsa_labs/configuration.rb +11 -0
  12. data/lib/salsa_labs/connection.rb +91 -0
  13. data/lib/salsa_labs/objects/distributed_event.rb +6 -0
  14. data/lib/salsa_labs/objects/donation.rb +6 -0
  15. data/lib/salsa_labs/objects/event.rb +6 -0
  16. data/lib/salsa_labs/objects/groups.rb +6 -0
  17. data/lib/salsa_labs/objects/supporter.rb +6 -0
  18. data/lib/salsa_labs/objects/supporter_action.rb +6 -0
  19. data/lib/salsa_labs/objects/supporter_action_comment.rb +6 -0
  20. data/lib/salsa_labs/objects/supporter_action_content.rb +6 -0
  21. data/lib/salsa_labs/objects/supporter_action_target.rb +6 -0
  22. data/lib/salsa_labs/objects/supporter_event.rb +6 -0
  23. data/lib/salsa_labs/objects/supporter_groups.rb +6 -0
  24. data/lib/salsa_labs/salsa_object.rb +74 -0
  25. data/lib/salsa_labs/salsa_request_overwrite.rb +30 -0
  26. data/lib/salsa_labs/save_response.rb +29 -0
  27. data/lib/salsa_labs/version.rb +3 -0
  28. data/lib/salsa_labs.rb +75 -0
  29. data/salsalabs.gemspec +28 -0
  30. data/spec/fixtures/auth_error.txt +14 -0
  31. data/spec/fixtures/auth_success.txt +18 -0
  32. data/spec/fixtures/expired_session.txt +12 -0
  33. data/spec/fixtures/malformed_response.txt +11 -0
  34. data/spec/fixtures/supporter/supporter_all.xml +135 -0
  35. data/spec/fixtures/supporter/supporter_count.xml +8 -0
  36. data/spec/fixtures/supporter/supporter_create.xml +1 -0
  37. data/spec/fixtures/supporter/supporter_get.xml +68 -0
  38. data/spec/fixtures/supporter/supporter_update.xml +1 -0
  39. data/spec/fixtures/supporters.txt +346 -0
  40. data/spec/integration/create_supporter_spec.rb +16 -0
  41. data/spec/integration/get_supporter_spec.rb +14 -0
  42. data/spec/spec_helper.rb +30 -0
  43. data/spec/support/fixtures.rb +7 -0
  44. data/spec/support/silence_warnings.rb +9 -0
  45. data/spec/unit/salsa_labs/api_response_spec.rb +82 -0
  46. data/spec/unit/salsa_labs/authentication_response_spec.rb +53 -0
  47. data/spec/unit/salsa_labs/configuration_spec.rb +33 -0
  48. data/spec/unit/salsa_labs/connection_spec.rb +84 -0
  49. data/spec/unit/salsa_labs/objects/supporter_spec.rb +62 -0
  50. data/spec/unit/salsa_labs/salsa_object_spec.rb +11 -0
  51. data/spec/unit/salsa_labs_spec.rb +36 -0
  52. metadata +283 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .yardoc
3
+ Gemfile.lock
4
+ doc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ salsa_labs
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p545
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ env:
5
+ global:
6
+ - secure: PEgtKoeN3s+ovOFmPfLrYXgY3N1S1UFYuFvSVwXRsjNJtYv0+gHBLRMGBregMbcx6fyfiuR6nUykJHVzhBXncvRXjJe/ClTuWJCubvEEAiFg1IU1Z/692KS79EPTKhJoWW/Pqp6lmUN9Xpf/LtngciiFAoF3qHyGXgxU/NOKZwI=
7
+ - secure: m9PNJdttvjaOzgp7LYrLGwhNuO0kDtaV/Md0EFMwsckCqPZq3549hs4JLH2RZV+oKyKO7nuWBCu670txrskFxPWa4grF/H6q1eUoFcuqgk0iR179mfO20cXU3jTfGzmPseFlpMpSM65dNtH4bdx53tsflfSnG0fCKQJ1FpY1ZsU=
8
+ script:
9
+ - bundle exec rake spec:ci
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ [![Code Climate](https://codeclimate.com/github/marclove/salsa_labs.png)](https://codeclimate.com/github/marclove/salsa_labs)
2
+ [![Build Status](https://travis-ci.org/marclove/salsalabs.svg?branch=master)](https://travis-ci.org/marclove/salsalabs)
3
+
4
+ # SalsaLabs
5
+ A Ruby Gem for consuming the [Salsa Labs API](http://wfc2.wiredforchange.com/o/8001/p/salsa/website/public2/commons/dev/docs/).
6
+
7
+ ##Usage
8
+ **This gem is still in a very alpha state and should not be used in production environments. The gem has purposely not been built or deployed to RubyGems. It will not be published until it is in a somewhat usable state.**
9
+
10
+ Configure the gem with your Salsa Labs login credentials:
11
+
12
+ ```ruby
13
+ SalsaLabs.configure do |c|
14
+ c.email = 'myemail@example.com'
15
+ c.password = 'mypassword'
16
+ end
17
+ ```
18
+
19
+ Make your requests:
20
+
21
+ ```ruby
22
+ SalsaLabs::Supporter.get('12345')
23
+ #=> { "supporter_KEY" => "12345", "First_Name" => "Jane", "Last_Name" => "Doe", ... }
24
+
25
+ SalsaLabs::Supporter.all
26
+ #=> [{ "supporter_KEY" => "12345", "First_Name" => "Jane", "Last_Name" => "Doe", ... }, { "supporter_KEY" => "12346", "First_Name" => "John", "Last_Name" => "Doe", ... }]
27
+ ```
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'rake'
5
+ require 'rspec/core/rake_task'
6
+ require 'yard'
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
9
+ require 'salsa_labs/version'
10
+
11
+ task :gem => :build
12
+ task :build do
13
+ system 'gem build salsalabs.gemspec'
14
+ end
15
+
16
+ task :install => :build do
17
+ system "gem install salsalabs-#{SalsaLabs::VERSION}.gem"
18
+ end
19
+
20
+ task :release => :build do
21
+ system "git tag -a v#{SalsaLabs::VERSION} -m 'Tagging #{SalsaLabs::VERSION}"
22
+ system "git push --tags"
23
+ system "gem push salsalabs-#{SalsaLabs::VERSION}.gem"
24
+ end
25
+
26
+ namespace :spec do
27
+ RSpec::Core::RakeTask.new(:unit) do |t|
28
+ t.verbose = false
29
+ t.pattern = './spec/unit{,/*/**}/*_spec.rb'
30
+ t.ruby_opts = "-w -I ./spec -rspec_helper"
31
+ end
32
+
33
+ RSpec::Core::RakeTask.new(:integration) do |t|
34
+ t.verbose = false
35
+ t.pattern = './spec/integration{,/*/**}/*_spec.rb'
36
+ t.ruby_opts = "-w -I ./spec -rspec_helper"
37
+ end
38
+
39
+ task :ci => ['spec:unit','spec:integration']
40
+ end
41
+
42
+ task :spec => ['spec:unit']
43
+
44
+ YARD::Rake::YardocTask.new(:doc) do |t|
45
+ t.files = ['lib/**/*.rb']
46
+ t.options = ['--embed-mixins', '--protected', '--private', '--readme', 'README.md']
47
+ end
48
+
49
+ task :default => :spec
@@ -0,0 +1,55 @@
1
+ module SalsaLabs
2
+ class ApiResponse
3
+
4
+ # @param [Faraday::Response] faraday_response
5
+ def initialize(faraday_response)
6
+ @response = faraday_response
7
+ end
8
+
9
+ # @return [Boolean] true if response was properly formed and
10
+ # no error message was returned
11
+ def successful?
12
+ data && !error_message
13
+ end
14
+
15
+ # @return [Boolean] true if an error message is returned that
16
+ # indicates the current session has expired
17
+ def needs_reauthentication?
18
+ return false unless error
19
+ error =~ /Please authenticate in order to continue./
20
+ end
21
+
22
+ # @return [Nokogiri::XML] the full xml returned by the API,
23
+ # parsed by +Nokogiri+ (memoized)
24
+ def body
25
+ @body ||= Nokogiri::XML(@response.body)
26
+ end
27
+
28
+ # @return [String] the error message returned by the API
29
+ # @return [nil] if there was no error message returned by the API
30
+ def error_message
31
+ if data.nil?
32
+ 'The response was not formatted as expected.'
33
+ elsif error
34
+ error
35
+ else
36
+ nil
37
+ end
38
+ end
39
+
40
+ # @return [String] the xml fragment contained in the
41
+ # +<data></data>+ element of the API response
42
+ # @return [nil] if there was no data returned by the API
43
+ def data
44
+ data = body.xpath('//data')
45
+ data.children.length == 0 ? nil : data.children.to_s
46
+ end
47
+
48
+ # @return [String] the error message returned by the API
49
+ # @return [nil] if there was no error message returned by the API
50
+ def error
51
+ err = body.xpath('//data/error').text
52
+ err == '' ? nil : err
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,44 @@
1
+ require 'nokogiri'
2
+
3
+ module SalsaLabs
4
+ class AuthenticationResponse
5
+
6
+ # @param [Faraday::Response] faraday_response
7
+ def initialize(faraday_response)
8
+ @response = faraday_response
9
+ end
10
+
11
+ # @return [String]
12
+ def session_cookies
13
+ returned_cookies if successful?
14
+ end
15
+
16
+ # @return [Boolean] true if no error message was returned
17
+ def successful?
18
+ !error_message && session_cookie_exists?
19
+ end
20
+
21
+ # @return [Nokogiri::XML] the full xml returned by the API,
22
+ # parsed by +Nokogiri+ (memoized)
23
+ def body
24
+ @body ||= ::Nokogiri::XML(@response.body)
25
+ end
26
+
27
+ # @return [String] the error message returned by the API
28
+ # @return [nil] if there was no error message returned by the API
29
+ def error_message
30
+ err = body.xpath('//data/error').text
31
+ err == '' ? nil : err
32
+ end
33
+
34
+ private
35
+
36
+ def session_cookie_exists?
37
+ returned_cookies =~ /JSESSION/
38
+ end
39
+
40
+ def returned_cookies
41
+ @response.headers['set-cookie']
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ module SalsaLabs
2
+ class Configuration
3
+ attr_accessor :email, :password
4
+
5
+ # @return [Boolean]
6
+ # true if {#email} and {#password} are both not +nil+
7
+ def valid?
8
+ !email.nil? && !password.nil?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,91 @@
1
+ require 'net/http'
2
+ require 'cgi'
3
+ require 'faraday'
4
+ require 'salsa_labs/salsa_request_overwrite'
5
+
6
+ module SalsaLabs
7
+ class APIResponseError < StandardError; end
8
+ class AuthenticationError < StandardError; end
9
+ class AuthenticationLoopError < StandardError; end
10
+
11
+ class Connection
12
+
13
+ # @param [String] email
14
+ # from your Salsa Labs login
15
+ # @param [String] password
16
+ # from your Salsa Labs login
17
+ def initialize(email, password)
18
+ @email, @password = email, password
19
+ @authentication_headers = nil
20
+ end
21
+
22
+ # @param [String] path
23
+ # the url fragment that follows "+sandbox.salsalabs.com/+"
24
+ # in the endpoint uri you are making a request to
25
+ # @param [Hash] query
26
+ # a hash representing the url query string parameters
27
+ # @param [Boolean] recursive_call
28
+ # whether this method was called by itself
29
+ # @yield
30
+ # the code to execute if the response is successful
31
+ # @yieldparam [String] response
32
+ # the xml fragment contained in the +<data></data>+ element of the API response
33
+ # @raise [AuthenticationLoopError]
34
+ # if the request is caught in an infinite authentication loop
35
+ # @raise [APIResponseError]
36
+ # if the API response returned an error or was malformed
37
+ def request(path, query={}, recursive_call = false, &block)
38
+ authenticate unless authenticated?
39
+
40
+ execute_request(path, query) do |response|
41
+ if response.successful?
42
+ block.call(response.data)
43
+ elsif response.needs_reauthentication?
44
+ raise AuthenticationLoopError.new if recursive_call
45
+ authenticate
46
+ request(path, query, true, &block)
47
+ else
48
+ raise APIResponseError, response.error_message
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # @return [Faraday]
56
+ def api
57
+ @api ||= ::Faraday.new url: 'https://sandbox.salsalabs.com/' do |conn|
58
+ conn.use :salsa
59
+ conn.adapter :net_http
60
+ end
61
+ end
62
+
63
+ # @yieldparam [ApiResponse] response
64
+ def execute_request(path, query={})
65
+ yield ApiResponse.new(api.get(path, query, @authentication_headers))
66
+ end
67
+
68
+ # Makes an authentication call to the Salsa Labs API using the credentials
69
+ # set in the {SalsaLabs.configure} method.
70
+ #
71
+ # @raise [AuthenticationError] if the response returned an error or is malformed
72
+ def authenticate
73
+ email, password = CGI.escape(@email), CGI.escape(@password)
74
+ auth_path = "api/authenticate.sjs?email=#{email}&password=#{password}"
75
+ response = AuthenticationResponse.new(api.get(auth_path))
76
+ if response.successful?
77
+ @authentication_headers = { 'Cookie' => response.session_cookies }
78
+ else
79
+ @authentication_headers = nil
80
+ raise AuthenticationError, response.error_message
81
+ end
82
+ end
83
+
84
+ # Returns +true+ if the session cookie has been set.
85
+ #
86
+ # @return [Boolean]
87
+ def authenticated?
88
+ !!@authentication_headers
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class DistributedEvent
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class Donation
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class Event
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class Groups
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class Supporter
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterAction
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterActionComment
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterActionContent
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterActionTarget
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterEvent
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SalsaLabs
2
+ class SupporterGroups
3
+ include SalsaObject
4
+ # @!parse extend SalsaObject::ClassMethods
5
+ end
6
+ end
@@ -0,0 +1,74 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module SalsaLabs
4
+ module SalsaObject
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ # @param [String] key of the object being requested
11
+ # @return [Hash] a hash representing the requested object
12
+ def get(key)
13
+ SalsaLabs.request('api/getObject.sjs', {object: object_name, key: key}) do |response|
14
+ Hash.from_xml(response).
15
+ try(:[], object_name).
16
+ try(:[], 'item')
17
+ end
18
+ end
19
+
20
+ # @return [Integer] the number of total objects
21
+ def count
22
+ SalsaLabs.request('api/getCounts.sjs', {object: object_name}) do |response|
23
+ Hash.from_xml(response).
24
+ try(:[], object_name).
25
+ try(:[], 'count').
26
+ try(:[], 'count').
27
+ try(:to_i)
28
+ end
29
+ end
30
+
31
+ # @return [Array<Hash>] an array of all the objects
32
+ def all
33
+ SalsaLabs.request('api/getObjects.sjs', {object: object_name}) do |response|
34
+ Hash.from_xml(response).
35
+ try(:[], object_name).
36
+ try(:[], 'item')
37
+ end
38
+ end
39
+
40
+ # @return [String] the newly created object's key
41
+ # @raise [APIResponseError]
42
+ # if the request to create the object failed
43
+ def create(attributes)
44
+ attributes.merge!({ object: object_name, key: '0' })
45
+ SalsaLabs.request('save', attributes) do |response|
46
+ SalsaLabs::SaveResponse.new(response).key
47
+ end
48
+ end
49
+
50
+ # @return [Boolean] true if request was successful
51
+ # @raise [APIResponseError]
52
+ # if the request to update the object failed
53
+ def update(key, attributes)
54
+ attributes.merge!({ object: object_name, key: key.to_s })
55
+ SalsaLabs.request('save', attributes) do |response|
56
+ SalsaLabs::SaveResponse.new(response).successful?
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # @return [String] the name of this class in lowercase and underscored format
63
+ # @example
64
+ # class MySpecialClass
65
+ # include SalsaObject
66
+ # end
67
+ #
68
+ # MySpecialClass.object_name #=> 'my_special_class'
69
+ def object_name
70
+ self.to_s.split('::').last.gsub(/(?:([A-Za-z])|^)(?=[^a-z])/) { "#{$1}#{$1 && '_'}" }.downcase
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class SalsaRequestOverwrite < Faraday::Middleware
5
+ def initialize(app)
6
+ super(app)
7
+ end
8
+
9
+ def call(env)
10
+ url = env[:url].to_s
11
+ rewrite_request(env) if rewrite_request?(url)
12
+ @app.call(env)
13
+ end
14
+
15
+ def rewrite_request?(url)
16
+ url =~ /https:\/\/.*\.salsalabs\.com\/save/
17
+ end
18
+
19
+ def rewrite_request(env)
20
+ url = env[:url].to_s
21
+ env[:url] = URI(url.sub(/\/save\?/,'/save?xml&'))
22
+ end
23
+ end
24
+ end
25
+
26
+ if Faraday.respond_to?(:register_middleware)
27
+ Faraday.register_middleware salsa: Faraday::SalsaRequestOverwrite
28
+ elsif Faraday::Middleware.respond_to?(:register_middleware)
29
+ Faraday::Middleware.register_middleware salsa: Faraday::SalsaRequestOverwrite
30
+ end
@@ -0,0 +1,29 @@
1
+ module SalsaLabs
2
+ class SaveResponse
3
+ # @param [String] an xml string of the response body
4
+ def initialize(xml)
5
+ @doc = Nokogiri::XML(xml)
6
+ raise APIResponseError, 'Save request failed' unless successful?
7
+ end
8
+
9
+ # @return [Boolean] true if request was successful
10
+ def successful?
11
+ success_object? && key_returned?
12
+ end
13
+
14
+ # @return [String] the key of the object that was saved
15
+ def key
16
+ @doc.xpath('/success').attr('key').to_s
17
+ end
18
+
19
+ private
20
+
21
+ def success_object?
22
+ @doc.xpath('/success').length > 0
23
+ end
24
+
25
+ def key_returned?
26
+ !key.blank?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module SalsaLabs
2
+ VERSION = '0.1.0'
3
+ end
data/lib/salsa_labs.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'salsa_labs/configuration'
2
+ require 'salsa_labs/connection'
3
+ require 'salsa_labs/authentication_response'
4
+ require 'salsa_labs/api_response'
5
+ require 'salsa_labs/save_response'
6
+ require 'salsa_labs/salsa_object'
7
+ require 'salsa_labs/objects/distributed_event'
8
+ require 'salsa_labs/objects/donation'
9
+ require 'salsa_labs/objects/event'
10
+ require 'salsa_labs/objects/groups'
11
+ require 'salsa_labs/objects/supporter_action_comment'
12
+ require 'salsa_labs/objects/supporter_action_content'
13
+ require 'salsa_labs/objects/supporter_action_target'
14
+ require 'salsa_labs/objects/supporter_action'
15
+ require 'salsa_labs/objects/supporter_event'
16
+ require 'salsa_labs/objects/supporter_groups'
17
+ require 'salsa_labs/objects/supporter'
18
+
19
+ module SalsaLabs
20
+ class ConfigurationError < StandardError
21
+ # @!attribute [r] message
22
+ # @return [String]
23
+ # the error message
24
+ def message
25
+ 'You have not properly configured SalsaLabs with your email and password'
26
+ end
27
+ end
28
+
29
+ # Configures the gem with your Salsa Labs credentials
30
+ # @note Configuration is required for the gem to function.
31
+ # @yieldparam [SalsaLabs::Configuration] config
32
+ # yields gem's current +Configuration+ object within the block
33
+ # @example
34
+ # SalsaLabs.configure do |c|
35
+ # c.email = 'myemail@example.com'
36
+ # c.password = 'mypassword'
37
+ # end
38
+ # @return [SalsaLabs]
39
+ # @see SalsaLabs::Configuration
40
+ def self.configure
41
+ yield configuration
42
+ end
43
+
44
+ # Makes a request to the specified SalsaLabs API endpoint.
45
+ # @param [String] path
46
+ # the url fragment that follows "+sandbox.salsalabs.com/api/+"
47
+ # in the endpoint uri you are making a request to
48
+ # @param [Hash] query
49
+ # a hash representing the url query string parameters
50
+ # @yieldreturn [SalsaLabs::ApiResponse]
51
+ # the response object for the executed request
52
+ # @return [SalsaLabs]
53
+ def self.request(path, query={}, &block)
54
+ connection.request(path, query, &block)
55
+ end
56
+
57
+ private
58
+
59
+ # @return [SalsaLabs::Configuration]
60
+ def self.configuration
61
+ @configuration ||= Configuration.new
62
+ end
63
+
64
+ # @return [SalsaLabs::Connection]
65
+ def self.connection
66
+ @connection ||= establish_connection
67
+ end
68
+
69
+ # @return [SalsaLabs::Connection]
70
+ # @raise [ConfigurationError] if the gem has not been configured properly
71
+ def self.establish_connection
72
+ raise ConfigurationError.new unless configuration.valid?
73
+ Connection.new(configuration.email, configuration.password)
74
+ end
75
+ end
data/salsalabs.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'salsa_labs/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'salsalabs'
8
+ s.version = SalsaLabs::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['Marc Love']
11
+ s.email = ['marcslove@gmail.com']
12
+ s.homepage = 'https://github.com/marcslove/salsa_labs'
13
+ s.summary = 'Salsa Labs API client library'
14
+ s.licenses = ['MIT']
15
+ s.required_rubygems_version = '>= 1.3.6'
16
+ s.add_dependency 'activesupport', '4.0.4'
17
+ s.add_dependency 'nokogiri'
18
+ s.add_dependency 'faraday', '>= 0.9.0.rc'
19
+ s.add_development_dependency 'rake'
20
+ s.add_development_dependency 'yard'
21
+ s.add_development_dependency 'redcarpet'
22
+ s.add_development_dependency 'bundler', '>= 1.0'
23
+ s.add_development_dependency 'rspec', '>= 2.11'
24
+ s.add_development_dependency 'webmock', '>= 1.13.0'
25
+ s.add_development_dependency 'pry-debugger'
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- spec/*`.split("\n")
28
+ end
@@ -0,0 +1,14 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/1.0.0
3
+ Date: Tue, 30 Jul 2013 08:32:07 GMT
4
+ Content-Type: text/xml;charset=UTF-8
5
+ Connection: close
6
+ RequestURI: /api/authenticate.sjs?email=marcslove@gmail.com&password=marclove
7
+ Set-Cookie: JSESSIONID=863F72A0F2BBAA941D2D214DEC9DBE4F-n4; Path=/; Secure; HttpOnly, hqtab_2=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, READONLY_Short_Name=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, SRV=sandbox; path=/
8
+ Cache-Control: private
9
+ Transfer-Encoding: Identity
10
+
11
+ <?xml version="1.0"?>
12
+ <data>
13
+ <error>Invalid login, please try again.</error>
14
+ </data>