startupstats 0.0.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.
Files changed (38) hide show
  1. data/.gitignore +7 -0
  2. data/.rvmrc +48 -0
  3. data/Gemfile +4 -0
  4. data/README.md +24 -0
  5. data/Rakefile +1 -0
  6. data/lib/startupstats-client.rb +31 -0
  7. data/lib/startupstats/configurable.rb +61 -0
  8. data/lib/startupstats/core_ext/hash.rb +18 -0
  9. data/lib/startupstats/default.rb +78 -0
  10. data/lib/startupstats/error.rb +31 -0
  11. data/lib/startupstats/error/bad_gateway.rb +11 -0
  12. data/lib/startupstats/error/bad_request.rb +10 -0
  13. data/lib/startupstats/error/client_error.rb +35 -0
  14. data/lib/startupstats/error/decode_error.rb +9 -0
  15. data/lib/startupstats/error/forbidden.rb +10 -0
  16. data/lib/startupstats/error/gateway_timeout.rb +11 -0
  17. data/lib/startupstats/error/internal_server_error.rb +11 -0
  18. data/lib/startupstats/error/not_acceptable.rb +10 -0
  19. data/lib/startupstats/error/not_found.rb +10 -0
  20. data/lib/startupstats/error/server_error.rb +28 -0
  21. data/lib/startupstats/error/unauthorized.rb +10 -0
  22. data/lib/startupstats/formd/client.rb +25 -0
  23. data/lib/startupstats/formd/filings.rb +55 -0
  24. data/lib/startupstats/formd/models/filing.rb +19 -0
  25. data/lib/startupstats/requestable.rb +56 -0
  26. data/lib/startupstats/response/parse_json.rb +25 -0
  27. data/lib/startupstats/response/raise_error.rb +31 -0
  28. data/lib/startupstats/version.rb +3 -0
  29. data/spec/factories.rb +105 -0
  30. data/spec/formd/client_spec.rb +8 -0
  31. data/spec/formd/filings_spec.rb +19 -0
  32. data/spec/formd/formd_spec.rb +37 -0
  33. data/spec/spec_helper.rb +19 -0
  34. data/spec/support/vcr_support.rb +11 -0
  35. data/spec/unit/error_spec.rb +20 -0
  36. data/spec/unit/requestable_spec.rb +37 -0
  37. data/startupstats-client.gemspec +30 -0
  38. metadata +203 -0
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage/*
6
+ .idea
7
+ .DS_Store
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p194@startupstats-client"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.14.12 ()" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
35
+
36
+ # If you use bundler, this might be useful to you:
37
+ # if [[ -s Gemfile ]] && {
38
+ # ! builtin command -v bundle >/dev/null ||
39
+ # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
40
+ # }
41
+ # then
42
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
+ # gem install bundler
44
+ # fi
45
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
+ # then
47
+ # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
48
+ # fi
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in startupstats-client.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # The StartupStats Client Ruby Gem
2
+
3
+ ## Installation
4
+ ```sh
5
+ gem install startupstats
6
+ ```
7
+
8
+ ## Documentation
9
+ Coming soon!
10
+
11
+ ## Configuration
12
+ Given that this is a library of multiple API clients, you must configure each client that you have been granted access to individually. This is straight-forward. Here is an example of configuring the Formd API for usage:
13
+
14
+ ```ruby
15
+ StartupStats::Formd.configure do |config|
16
+ config.access_token = "2f309awf30a9wf3jaw39faaf903ja3"
17
+ config.endpoint = "http://formd.startupstats.com/"
18
+ end
19
+ ```
20
+
21
+ After configuration, you can make calls directly to the API that you have setup. Here's an example:
22
+ ```ruby
23
+ @filings = StartupStats::Formd.filings( start = 0 , limit = 5 )
24
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,31 @@
1
+ require "startupstats/version"
2
+ require "startupstats/configurable"
3
+ require "startupstats/formd/client"
4
+ #Dir[File.dirname(__FILE__) + '/startupstats/formd/*'].each {|file| require file }
5
+
6
+ module StartupStats
7
+ # TODO: figure out way to automaticaly generate the following code for each new module/API Client
8
+ module Formd
9
+ class << self
10
+ include StartupStats::Configurable
11
+
12
+ # Delegate to a StartupStats::Formd::Client
13
+ #
14
+ # @return [StartupStats::Formd::Client]
15
+ def client
16
+ @client = StartupStats::Formd::Client.new(options) unless defined?(@client) && @client.cache_key == options.hash
17
+ @client
18
+ end
19
+
20
+ def respond_to_missing?(method_name, include_private=false); client.respond_to?(method_name, include_private); end if RUBY_VERSION >= "1.9"
21
+ def respond_to?(method_name, include_private=false); client.respond_to?(method_name, include_private) || super; end if RUBY_VERSION < "1.9"
22
+
23
+ private
24
+ def method_missing(method_name, *args, &block)
25
+ return super unless client.respond_to?(method_name)
26
+ client.send(method_name, *args, &block)
27
+ end
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,61 @@
1
+ require 'startupstats/default'
2
+ module StartupStats
3
+ module Configurable
4
+ attr_writer :access_token, :access_token_key
5
+ attr_accessor :endpoint, :connection_options, :middleware
6
+
7
+ class << self
8
+
9
+ def keys
10
+ @keys ||= [
11
+ :access_token,
12
+ :access_token_key,
13
+ :endpoint,
14
+ :connection_options,
15
+ :middleware,
16
+ ]
17
+ end
18
+
19
+ end
20
+
21
+ # Convenience method to allow configuration options to be set in a block
22
+ def configure
23
+ yield self
24
+ self
25
+ end
26
+
27
+ # @return [Boolean]
28
+ def credentials?
29
+ credentials.values.all?
30
+ end
31
+
32
+ # @return [Fixnum]
33
+ def cache_key
34
+ options.hash
35
+ end
36
+
37
+ def reset!
38
+ StartupStats::Configurable.keys.each do |key|
39
+ instance_variable_set(:"@#{key}", StartupStats::Default.options[key])
40
+ end
41
+ self
42
+ end
43
+ alias setup reset!
44
+
45
+ private
46
+
47
+ # @return [Hash]
48
+ def credentials
49
+ {
50
+ :access_token_key => @access_token_key,
51
+ :access_token => @access_token,
52
+ }
53
+ end
54
+
55
+ # @return [Hash]
56
+ def options
57
+ Hash[StartupStats::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ class Hash
2
+
3
+ # Merges self with another hash, recursively
4
+ #
5
+ # @param hash [Hash] The hash to merge
6
+ # @return [Hash]
7
+ def deep_merge(hash)
8
+ target = self.dup
9
+ hash.keys.each do |key|
10
+ if hash[key].is_a?(Hash) && self[key].is_a?(Hash)
11
+ target[key] = target[key].deep_merge(hash[key])
12
+ next
13
+ end
14
+ target[key] = hash[key]
15
+ end
16
+ target
17
+ end
18
+ end
@@ -0,0 +1,78 @@
1
+ require 'faraday'
2
+ require 'startupstats/configurable'
3
+ require 'startupstats/error/client_error'
4
+ require 'startupstats/error/server_error'
5
+ require 'startupstats/response/parse_json'
6
+ require 'startupstats/response/raise_error'
7
+ require 'startupstats/version'
8
+
9
+ module StartupStats
10
+ module Default
11
+ ENDPOINT = 'https://api.startupstats.com' unless defined? StartupStats::Default::ENDPOINT
12
+
13
+ CONNECTION_OPTIONS = {
14
+ :headers => {
15
+ :accept => 'application/json',
16
+ :user_agent => "StartupStats Ruby Gem #{StartupStats::VERSION}"
17
+ },
18
+ :open_timeout => 5,
19
+ :raw => true,
20
+ :ssl => {:verify => false},
21
+ :timeout => 10,
22
+ } unless defined? StartupStats::Default::CONNECTION_OPTIONS
23
+
24
+ MIDDLEWARE = Faraday::Builder.new do |builder|
25
+ # Convert request params to "www-form-urlencoded"
26
+ builder.use Faraday::Request::UrlEncoded
27
+ # Handle 4xx server responses
28
+ builder.use StartupStats::Response::RaiseError, StartupStats::Error::ClientError
29
+ # Parse JSON response bodies using MultiJson
30
+ builder.use StartupStats::Response::ParseJson
31
+ # Handle 5xx server responses
32
+ builder.use StartupStats::Response::RaiseError, StartupStats::Error::ServerError
33
+ # Set Faraday's HTTP adapter
34
+ builder.adapter Faraday.default_adapter #:typhoeus
35
+ end unless defined? StartupStats::Default::MIDDLEWARE
36
+
37
+ class << self
38
+
39
+ # @return [Hash]
40
+ def options
41
+ Hash[StartupStats::Configurable.keys.map{|key| [key, send(key)]}]
42
+ end
43
+
44
+ # @return [String]
45
+ def access_token
46
+ ENV['FORMD_ACCESS_TOKEN'] || "access_token"
47
+ end
48
+
49
+ # @return [String]
50
+ def access_token_key
51
+ ENV['FORMD_ACCESS_TOKEN_KEY']
52
+ end
53
+
54
+ # @note This is configurable in case you want to use a Twitter-compatible endpoint.
55
+ # @see http://status.net/wiki/Twitter-compatible_API
56
+ # @see http://en.blog.wordpress.com/2009/12/12/twitter-api/
57
+ # @see http://staff.tumblr.com/post/287703110/api
58
+ # @see http://developer.typepad.com/typepad-twitter-api/twitter-api.html
59
+ # @return [String]
60
+ def endpoint
61
+ ENDPOINT
62
+ end
63
+
64
+ def connection_options
65
+ CONNECTION_OPTIONS
66
+ end
67
+
68
+ # @note Faraday's middleware stack implementation is comparable to that of Rack middleware. The order of middleware is important: the first middleware on the list wraps all others, while the last middleware is the innermost one.
69
+ # @see https://github.com/technoweenie/faraday#advanced-middleware-usage
70
+ # @see http://mislav.uniqpath.com/2011/07/faraday-advanced-http/
71
+ # @return [Faraday::Builder]
72
+ def middleware
73
+ MIDDLEWARE
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,31 @@
1
+ module StartupStats
2
+ # Custom error class for rescuing from all StartupStats errors
3
+ class Error < StandardError
4
+ attr_reader :wrapped_exception
5
+
6
+ # @return [Hash]
7
+ def self.errors
8
+ @errors ||= Hash[descendants.map{|klass| [klass.const_get(:HTTP_STATUS_CODE), klass]}]
9
+ end
10
+
11
+ # @return [Array]
12
+ def self.descendants
13
+ ObjectSpace.each_object(::Class).select{|klass| klass < self}
14
+ end
15
+
16
+ # Initializes a new Error object
17
+ #
18
+ # @param exception [Exception, String]
19
+ # @param response_headers [Hash]
20
+ # @return [StartupStats::Error]
21
+ def initialize(exception=$!, response_headers={})
22
+ @wrapped_exception = exception
23
+ exception.respond_to?(:backtrace) ? super(exception.message) : super(exception.to_s)
24
+ end
25
+
26
+ def backtrace
27
+ @wrapped_exception.respond_to?(:backtrace) ? @wrapped_exception.backtrace : super
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ require 'startupstats/error/server_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 502
6
+ class BadGateway < StartupStats::Error::ServerError
7
+ HTTP_STATUS_CODE = 502
8
+ MESSAGE = "The StartupStats API you are requesting is down or being upgraded."
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require 'startupstats/error/client_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 400
6
+ class BadRequest < StartupStats::Error::ClientError
7
+ HTTP_STATUS_CODE = 400
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ require 'startupstats/error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns a 4xx HTTP status code or there's an error in Faraday
6
+ class ClientError < StartupStats::Error
7
+
8
+ # Create a new error from an HTTP environment
9
+ #
10
+ # @param response [Hash]
11
+ # @return [StartupStats::Error]
12
+ def self.from_response(response={})
13
+ new(parse_error(response[:body]), response[:response_headers])
14
+ end
15
+
16
+ private
17
+
18
+ def self.parse_error(body)
19
+ if body.nil?
20
+ ''
21
+ elsif body[:error]
22
+ body[:error]
23
+ elsif body[:errors]
24
+ first = Array(body[:errors]).first
25
+ if first.kind_of?(Hash)
26
+ first[:message].chomp
27
+ else
28
+ first.chomp
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ require 'startupstats/error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when JSON parsing fails
6
+ class DecodeError < StartupStats::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'startupstats/error/client_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 403
6
+ class Forbidden < StartupStats::Error::ClientError
7
+ HTTP_STATUS_CODE = 403
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ require 'startupstats/error/server_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 504
6
+ class GatewayTimeout < StartupStats::Error::ServerError
7
+ HTTP_STATUS_CODE = 504
8
+ MESSAGE = "The StartupStats servers are up, but the request couldn't be serviced due to some failure within our stack. Try again later."
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'startupstats/error/server_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 500
6
+ class InternalServerError < StartupStats::Error::ServerError
7
+ HTTP_STATUS_CODE = 500
8
+ MESSAGE = "Something is technically wrong."
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require 'startupstats/error/client_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 406
6
+ class NotAcceptable < StartupStats::Error::ClientError
7
+ HTTP_STATUS_CODE = 406
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'startupstats/error/client_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 404
6
+ class NotFound < StartupStats::Error::ClientError
7
+ HTTP_STATUS_CODE = 404
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,28 @@
1
+ require 'startupstats/error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns a 5xx HTTP status code
6
+ class ServerError < StartupStats::Error
7
+ MESSAGE = "Server Error"
8
+
9
+ # Create a new error from an HTTP environment
10
+ #
11
+ # @param response [Hash]
12
+ # @return [StartupStats::Error]
13
+ def self.from_response(response={})
14
+ new(nil, response[:response_headers])
15
+ end
16
+
17
+ # Initializes a new ServerError object
18
+ #
19
+ # @param message [String]
20
+ # @param response_headers [Hash]
21
+ # @return [StartupStats::Error::ServerError]
22
+ def initialize(message=nil, response_headers={})
23
+ super((message || self.class.const_get(:MESSAGE)), response_headers)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,10 @@
1
+ require 'startupstats/error/client_error'
2
+
3
+ module StartupStats
4
+ class Error
5
+ # Raised when a StartupStats API returns the HTTP status code 401
6
+ class Unauthorized < StartupStats::Error::ClientError
7
+ HTTP_STATUS_CODE = 401
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ require 'startupstats/configurable'
2
+ require 'startupstats/requestable'
3
+ require 'startupstats/formd/filings'
4
+ require 'startupstats/error/client_error'
5
+ require 'startupstats/error/decode_error'
6
+
7
+ module StartupStats
8
+ module Formd
9
+ class Client #< StartupStats::Client
10
+ # StartupStats client modules
11
+ include StartupStats::Configurable
12
+ include StartupStats::Requestable
13
+
14
+ # Formd modules
15
+ include StartupStats::Formd::Filings
16
+
17
+ def initialize( options = {} )
18
+ setup
19
+ StartupStats::Configurable.keys.each do |key|
20
+ instance_variable_set(:"@#{key}", options[key] || instance_variable_get(:"@#{key}"))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ require 'startupstats/formd/models/filing'
2
+ module StartupStats
3
+ module Formd
4
+ module Filings
5
+
6
+ # Returns filings
7
+ #
8
+ # @authentication_required This is a protected API call
9
+ # @raise [StartupStats::Error::Unauthorized] Error raised when supplied
10
+ # @return [Array<StartupStats::Filing>] The requested Filings.
11
+ # @param start [Integer] default is 0
12
+ # @param limit [Integer] default is 100
13
+ # @param industry [String] not required
14
+ def filings( start , limit , industry )
15
+ begin
16
+ parse_filings_from_response(:get , "filings", {start: start , limit: limit , industry: industry} )
17
+ rescue StartupStats::Error::Unauthorized => error
18
+ raise
19
+ end
20
+ end
21
+
22
+ =begin (Comes later)
23
+ def create_filing
24
+ end
25
+
26
+ def update_filing
27
+ end
28
+
29
+ def edit_filing
30
+ end
31
+
32
+ def destroy_filing
33
+ end
34
+
35
+ def show_filing
36
+ end
37
+ =end
38
+ private
39
+ # Parses an array of filings
40
+ #
41
+ # @param method [Symbol]
42
+ # @param path [String]
43
+ # @param params [Array]
44
+ # @return [Array<StartupStats::Filing>]
45
+ def parse_filings_from_response(method , path , params )
46
+ response = send(method.to_sym, path, params)
47
+ filings = []
48
+ response[:body].each{|filing|
49
+ filings.push( StartupStats::Formd::Filing.new filing )
50
+ }
51
+ filings
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,19 @@
1
+ module StartupStats
2
+ module Formd
3
+ class Filing
4
+ attr_accessor :filing_url_html , :filing_url_xml , :filing_id, :filing_type
5
+ attr_accessor :company_id, :filing_num, :filing_date, :industry_group, :long_offering, :business_combo, :processed,
6
+ :min_investment, :offering_amount, :offering_sold, :num_investors, :sales_commission, :finders_fee, :use_of_proceeds, :security_type
7
+ attr_accessor :company #this will store all details
8
+ def initialize response = {}
9
+ response.each do |k, v|
10
+ instance_variable_set("@#{k}",v) unless v.nil?
11
+ end
12
+ end
13
+
14
+ def id
15
+ @filing_id
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,56 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'multi_json'
4
+ #require 'startupstats/error/error'
5
+ #require 'startupstats/core_ext/hash'
6
+
7
+ module StartupStats
8
+ # Defines HTTP request methods
9
+ module Requestable
10
+ # Perform an HTTP DELETE request
11
+ def delete(path, params={})
12
+ request(:delete, path, params)
13
+ end
14
+
15
+ # Perform an HTTP GET request
16
+ def get(path, params={})
17
+ request(:get, path, params)
18
+ end
19
+
20
+ # Perform an HTTP POST request
21
+ def post(path, params={})
22
+ request(:post, path, params)
23
+ end
24
+
25
+ # Perform an HTTP PUT request
26
+ def put(path, params={})
27
+ request(:put, path, params)
28
+ end
29
+
30
+ private
31
+
32
+ def request(method, path, params={})
33
+ params[@access_token_key] = @access_token
34
+ connection.send(method.to_sym, path, params) do |request|
35
+ case method.to_sym
36
+ when :delete, :get
37
+ request.url(path, params)
38
+ when :post
39
+ request.path = path
40
+ request.body = params unless params.empty?
41
+ end
42
+ end.env
43
+ rescue Faraday::Error::ClientError
44
+ raise StartupStats::Error::ClientError
45
+ rescue MultiJson::DecodeError
46
+ raise StartupStats::Error::DecodeError
47
+ end
48
+
49
+ # Returns a Faraday::Connection object
50
+ #
51
+ # @return [Faraday::Connection]
52
+ def connection
53
+ @connection ||= Faraday.new(@endpoint, @connection_options.merge(:builder => @middleware))
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,25 @@
1
+ require 'faraday'
2
+ require 'multi_json'
3
+
4
+ module StartupStats
5
+ module Response
6
+ class ParseJson < Faraday::Response::Middleware
7
+
8
+ def parse(body)
9
+ case body
10
+ when /\A^\s*$\z/, nil
11
+ nil
12
+ else
13
+ MultiJson.load(body, :symbolize_keys => true)
14
+ end
15
+ end
16
+
17
+ def on_complete(env)
18
+ if respond_to?(:parse)
19
+ env[:body] = parse(env[:body]) unless [204, 301, 302, 304].include?(env[:status])
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ require 'faraday'
2
+ require 'startupstats/error/bad_gateway'
3
+ require 'startupstats/error/bad_request'
4
+ require 'startupstats/error/forbidden'
5
+ require 'startupstats/error/gateway_timeout'
6
+ require 'startupstats/error/internal_server_error'
7
+ require 'startupstats/error/not_acceptable'
8
+ require 'startupstats/error/not_found'
9
+ #require 'startupstats/error/service_unavailable'
10
+ #require 'startupstats/error/too_many_requests'
11
+ require 'startupstats/error/unauthorized'
12
+ #require 'startupstats/error/unprocessable_entity'
13
+
14
+ module StartupStats
15
+ module Response
16
+ class RaiseError < Faraday::Response::Middleware
17
+
18
+ def on_complete(env)
19
+ status_code = env[:status].to_i
20
+ error_class = @klass.errors[status_code]
21
+ raise error_class.from_response(env) if error_class
22
+ end
23
+
24
+ def initialize(app, klass)
25
+ @klass = klass
26
+ super(app)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module StartupStats
2
+ VERSION = '0.0.1'
3
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,105 @@
1
+ module StartupStats
2
+ module Formd
3
+ FactoryGirl.define do
4
+
5
+ factory :filing do
6
+ filing_url_html "http://www.sec.gov/Archives/edgar/data/1525533/000152553312000003/xslFormDX01/primary_doc.xml"
7
+ filing_url_xml "http://www.sec.gov/Archives/edgar/data/1525533/000152553312000003/primary_doc.xml"
8
+ filing_id "000152553312000003"
9
+ #filing_date Date.current
10
+ filing_type "D/A"
11
+ processed false
12
+
13
+ factory :filing_complete do
14
+ company
15
+ filing_num "3"
16
+ processed true
17
+ industry_group "Other Technology"
18
+ long_offering false
19
+ business_combo false
20
+ min_investment 0
21
+ offering_amount 1000000
22
+ offering_sold 400000
23
+ num_investors 4
24
+ sales_commission 0
25
+ finders_fee 0
26
+ use_of_proceeds 0
27
+
28
+ after(:create) do |filing|
29
+ filing.securities << FactoryGirl.build(:security)
30
+ end
31
+
32
+ factory :filing_with_people do
33
+ ignore do
34
+ people_count 1
35
+ end
36
+
37
+ after(:create) do |filing , evaluator|
38
+ FactoryGirl.create_list( :person , evaluator.people_count , filing: filing )
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+
45
+ factory :company do
46
+ # based on this: http://www.sec.gov/Archives/edgar/data/1562176/000156217612000001/xslFormDX01/primary_doc.xml
47
+ sec_id "0001562176"
48
+ name "Interesante, Inc."
49
+ entity_type "Corporation"
50
+ inc_state "DELEWARE"
51
+ address_street1 "2499 ALPINE ROAD"
52
+ address_street2 ""
53
+ address_city "MENLO PARK"
54
+ address_spc "CALIFORNIA"
55
+ address_zip "94025"
56
+ phone "650-799-1592"
57
+
58
+ factory :company_with_filings do
59
+ ignore do
60
+ filings_count 1
61
+ end
62
+
63
+ after(:create) do |company , evaluator|
64
+ FactoryGirl.create_list( :filing , evaluator.filings_count , company: company )
65
+ end
66
+ end
67
+
68
+ factory :company_with_prior_names do
69
+ ignore do
70
+ priornames_count 1
71
+ end
72
+
73
+ after(:create) do | company , evaluator |
74
+ FactoryGirl.create_list( :prior_name , evaluator.priornames_count , company: company )
75
+ end
76
+ end
77
+ end
78
+
79
+ factory :prior_name do
80
+ company
81
+ name "Purple Company"
82
+ end
83
+
84
+ factory :person do
85
+ filing
86
+ first_name "Christopher"
87
+ middle_name ""
88
+ last_name "Smart"
89
+ address_street1 "24 Fendon Road"
90
+ address_street2 ""
91
+ address_city "Cambridge"
92
+ address_spc "UNITED KINGDOM"
93
+ address_zip "CB1 7RT"
94
+ executive false
95
+ director true
96
+ promoter false
97
+ end
98
+
99
+ factory :security do
100
+ name "Equity"
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ module StartupStats
3
+ module Formd
4
+ describe Client do
5
+
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'vcr'
3
+ describe StartupStats::Formd::Filings do
4
+ use_vcr_cassette 'filings' , :record => :new_episodes
5
+ let(:client){ StartupStats::Formd::Client.new( {
6
+ :access_token => ENV['FORMD_TOKEN'] ,
7
+ :access_token_key => "access_token" ,
8
+ :endpoint => ENV['FORMD_ENDPOINT'] ,
9
+ } ) }
10
+
11
+ it "gets filings in batch" do
12
+ #VCR.use_cassette('filings' , :record => :new_episodes ) do
13
+ filings = client.filings( start = 0 , limit = 5 , industry = nil )
14
+ expect(filings).to be_an Array
15
+ expect(filings.first).to be_a StartupStats::Formd::Filing
16
+ filings.first.company_id.should eq 3
17
+ #end
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ describe StartupStats::Formd do
3
+ describe ".configure" do
4
+ StartupStats::Configurable.keys.each do |key|
5
+ it "sets the #{key.to_s.gsub('_', ' ')}" do
6
+ StartupStats::Formd.configure do |config|
7
+ config.send("#{key}=", key)
8
+ end
9
+ expect(StartupStats::Formd.instance_variable_get(:"@#{key}")).to eq key
10
+ end
11
+ end
12
+ end
13
+
14
+ describe ".client" do
15
+ it "returns a StartupStats::Formd::Client" do
16
+ expect(StartupStats::Formd.client).to be_a StartupStats::Formd::Client
17
+ end
18
+
19
+ context "when the options don't change" do
20
+ it "caches the client" do
21
+ expect(StartupStats::Formd.client).to eq StartupStats::Formd.client
22
+ end
23
+ end
24
+
25
+ context "when the options change" do
26
+ it "busts the cache" do
27
+ client1 = StartupStats::Formd.client
28
+ StartupStats::Formd.configure do |config|
29
+ config.access_token = 'abc'
30
+ config.access_token_key = '123'
31
+ end
32
+ client2 = StartupStats::Formd.client
33
+ expect(client1).not_to eq client2
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require 'rspec'
5
+ require 'startupstats-client'
6
+ require 'factory_girl'
7
+ require 'factories'
8
+ require 'vcr'
9
+
10
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
11
+
12
+ RSpec.configure do |config|
13
+ config.include FactoryGirl::Syntax::Methods
14
+
15
+ config.mock_with :rspec
16
+
17
+ config.run_all_when_everything_filtered = true
18
+ config.color_enabled = true
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |c|
4
+ c.cassette_library_dir = 'spec/vcr'
5
+ c.hook_into :faraday
6
+ #c.default_cassette_options = { :record => :once }
7
+ end
8
+
9
+ RSpec.configure do |c|
10
+ c.extend VCR::RSpec::Macros
11
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe StartupStats::Error do
4
+
5
+ describe "#initialize" do
6
+ it "wraps another error class" do
7
+ begin
8
+ raise Faraday::Error::ClientError.new("Oops")
9
+ rescue Faraday::Error::ClientError
10
+ begin
11
+ raise StartupStats::Error
12
+ rescue StartupStats::Error => error
13
+ expect(error.message).to eq "Oops"
14
+ expect(error.wrapped_exception.class).to eq Faraday::Error::ClientError
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe StartupStats::Requestable do
4
+ class DummyRequest; include StartupStats::Requestable; end
5
+
6
+ let(:dummy) { DummyRequest.new }
7
+ let(:sample_path) { "/index" }
8
+ let(:sample_params) { { :sample => "param" } }
9
+
10
+ describe "#get" do
11
+ it "calls request with the passed params" do
12
+ dummy.should_receive(:request).with(:get, sample_path, sample_params).and_return("result")
13
+ dummy.get(sample_path, sample_params).should == "result"
14
+ end
15
+ end
16
+
17
+ describe "#post" do
18
+ it "calls request with the passed params" do
19
+ dummy.should_receive(:request).with(:post, sample_path, sample_params).and_return("result")
20
+ dummy.post(sample_path, sample_params).should == "result"
21
+ end
22
+ end
23
+
24
+ describe "#delete" do
25
+ it "calls request with the passed params" do
26
+ dummy.should_receive(:request).with(:delete, sample_path, sample_params).and_return("result")
27
+ dummy.delete(sample_path, sample_params).should == "result"
28
+ end
29
+ end
30
+
31
+ describe "#put" do
32
+ it "calls request with the passed params" do
33
+ dummy.should_receive(:request).with(:put, sample_path, sample_params).and_return("result")
34
+ dummy.put(sample_path, sample_params).should == "result"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "startupstats/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "startupstats"
7
+ s.version = StartupStats::VERSION
8
+ s.authors = ["Nick O'Neill"]
9
+ s.email = ["mr.nick.oneill@gmail.com"]
10
+ s.homepage = "https://github.com/Holler/startupstats-client"
11
+ s.description = %q{A Ruby interface to the network of StartupStats APIs.}
12
+ s.summary = s.description
13
+
14
+ #s.rubyforge_project = "startupstats-client"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_development_dependency "factory_girl"
24
+ s.add_development_dependency "vcr"
25
+ s.add_development_dependency "yard", "~> 0.7.3"
26
+ s.add_development_dependency "simplecov"
27
+
28
+ s.add_dependency "faraday"
29
+ s.add_dependency "faraday_middleware"
30
+ end
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: startupstats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nick O'Neill
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: factory_girl
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: vcr
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: yard
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.7.3
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.7.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: simplecov
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: faraday
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: faraday_middleware
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: A Ruby interface to the network of StartupStats APIs.
127
+ email:
128
+ - mr.nick.oneill@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .rvmrc
135
+ - Gemfile
136
+ - README.md
137
+ - Rakefile
138
+ - lib/startupstats-client.rb
139
+ - lib/startupstats/configurable.rb
140
+ - lib/startupstats/core_ext/hash.rb
141
+ - lib/startupstats/default.rb
142
+ - lib/startupstats/error.rb
143
+ - lib/startupstats/error/bad_gateway.rb
144
+ - lib/startupstats/error/bad_request.rb
145
+ - lib/startupstats/error/client_error.rb
146
+ - lib/startupstats/error/decode_error.rb
147
+ - lib/startupstats/error/forbidden.rb
148
+ - lib/startupstats/error/gateway_timeout.rb
149
+ - lib/startupstats/error/internal_server_error.rb
150
+ - lib/startupstats/error/not_acceptable.rb
151
+ - lib/startupstats/error/not_found.rb
152
+ - lib/startupstats/error/server_error.rb
153
+ - lib/startupstats/error/unauthorized.rb
154
+ - lib/startupstats/formd/client.rb
155
+ - lib/startupstats/formd/filings.rb
156
+ - lib/startupstats/formd/models/filing.rb
157
+ - lib/startupstats/requestable.rb
158
+ - lib/startupstats/response/parse_json.rb
159
+ - lib/startupstats/response/raise_error.rb
160
+ - lib/startupstats/version.rb
161
+ - spec/factories.rb
162
+ - spec/formd/client_spec.rb
163
+ - spec/formd/filings_spec.rb
164
+ - spec/formd/formd_spec.rb
165
+ - spec/spec_helper.rb
166
+ - spec/support/vcr_support.rb
167
+ - spec/unit/error_spec.rb
168
+ - spec/unit/requestable_spec.rb
169
+ - startupstats-client.gemspec
170
+ homepage: https://github.com/Holler/startupstats-client
171
+ licenses: []
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ none: false
184
+ requirements:
185
+ - - ! '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubyforge_project:
190
+ rubygems_version: 1.8.24
191
+ signing_key:
192
+ specification_version: 3
193
+ summary: A Ruby interface to the network of StartupStats APIs.
194
+ test_files:
195
+ - spec/factories.rb
196
+ - spec/formd/client_spec.rb
197
+ - spec/formd/filings_spec.rb
198
+ - spec/formd/formd_spec.rb
199
+ - spec/spec_helper.rb
200
+ - spec/support/vcr_support.rb
201
+ - spec/unit/error_spec.rb
202
+ - spec/unit/requestable_spec.rb
203
+ has_rdoc: