open-companies-house 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ .gitignore
1
2
  .rvmrc
2
3
  .DS_Store
3
4
  Gemfile.lock
5
+ *.gem
data/README.md CHANGED
@@ -6,14 +6,31 @@ Simple ruby wrapper around Companies House Open API
6
6
  Usage:
7
7
  =====
8
8
 
9
- company = CompaniesHouse.lookup "07495895"
10
- => #<CompaniesHouse:0x00000100932870 @registration_number="07495895"... >
9
+ ```ruby
10
+ company = CompaniesHouse.lookup "07495895"
11
+ => #<CompaniesHouse:0x00000100932870 @registration_number="07495895"... >
11
12
 
12
- company["CompanyName"]
13
- => "GOCARDLESS LTD"
13
+ company["CompanyName"]
14
+ => "GOCARDLESS LTD"
14
15
 
15
- company.sic_code # convenience method
16
- => "62090"
16
+ company.sic_code # convenience method
17
+ => "62090"
18
+ ```
19
+
20
+ Caching
21
+ =======
22
+
23
+ If you'd like to cache your requests, you can configure the gem:
24
+
25
+ ```ruby
26
+ # file config/initializers/companies_house.rb
27
+
28
+ # swap in your own cache here
29
+ CompaniesHouse.cache = Rails.cache
30
+
31
+ # Optional
32
+ CompaniesHouse.cache_args = { expires_in: 10.minutes }
33
+ ```
17
34
 
18
35
  Specs
19
36
  =====
@@ -30,54 +47,57 @@ The following data is currently available on the `company` object returned by
30
47
 
31
48
  Call it like this:
32
49
 
33
- company["RegAddress"]["AddressLine1"]
34
- => "22-25 FINSBURY SQUARE"
50
+ ```ruby
51
+ company["RegAddress"]["AddressLine1"]
52
+ => "22-25 FINSBURY SQUARE"
53
+ ```
35
54
 
36
55
  All data:
37
56
 
38
- {
39
- "CompanyName" : "GOCARDLESS LTD",
40
- "CompanyNumber" : "07495895",
41
- "RegAddress" : {
42
- "AddressLine1" : "22-25 FINSBURY SQUARE",
43
- "PostTown" : "LONDON",
44
- "Country" : "UNITED KINGDOM",
45
- "Postcode" : "EC2A 1DX"
46
- },
47
- "CompanyCategory" : "Private Limited Company",
48
- "CompanyStatus" : "Active",
49
- "CountryOfOrigin" : "United Kingdom",
50
- "IncorporationDate" : "17/01/2011",
51
- "PreviousNames" : [
52
- {
53
- "CONDate" : "25/08/2011",
54
- "CompanyName" : "GROUPAY LIMITED"
55
- }
56
- ],
57
- "Accounts" : {
58
- "AccountRefDay" : "31",
59
- "AccountRefMonth" : "01",
60
- "NextDueDate" : "31/10/2013",
61
- "LastMadeUpDate" : "31/01/2012",
62
- "AccountCategory" : "TOTAL EXEMPTION SMALL"
63
- },
64
- "Returns" : {
65
- "NextDueDate" : "14/02/2013",
66
- "LastMadeUpDate" : "17/01/2012"
67
- },
68
- "Mortgages" : {
69
- "NumMortCharges" : "1",
70
- "NumMortOutstanding" : "1",
71
- "NumMortPartSatisfied" : "0",
72
- "NumMortSatisfied" : "0"
73
- },
74
- "SICCodes" : {
75
- "SicText" : [
76
- "62090 - Other information technology service activities"
77
- ]
78
- }
79
- }
80
-
57
+ ```json
58
+ {
59
+ "CompanyName" : "GOCARDLESS LTD",
60
+ "CompanyNumber" : "07495895",
61
+ "RegAddress" : {
62
+ "AddressLine1" : "22-25 FINSBURY SQUARE",
63
+ "PostTown" : "LONDON",
64
+ "Country" : "UNITED KINGDOM",
65
+ "Postcode" : "EC2A 1DX"
66
+ },
67
+ "CompanyCategory" : "Private Limited Company",
68
+ "CompanyStatus" : "Active",
69
+ "CountryOfOrigin" : "United Kingdom",
70
+ "IncorporationDate" : "17/01/2011",
71
+ "PreviousNames" : [
72
+ {
73
+ "CONDate" : "25/08/2011",
74
+ "CompanyName" : "GROUPAY LIMITED"
75
+ }
76
+ ],
77
+ "Accounts" : {
78
+ "AccountRefDay" : "31",
79
+ "AccountRefMonth" : "01",
80
+ "NextDueDate" : "31/10/2013",
81
+ "LastMadeUpDate" : "31/01/2012",
82
+ "AccountCategory" : "TOTAL EXEMPTION SMALL"
83
+ },
84
+ "Returns" : {
85
+ "NextDueDate" : "14/02/2013",
86
+ "LastMadeUpDate" : "17/01/2012"
87
+ },
88
+ "Mortgages" : {
89
+ "NumMortCharges" : "1",
90
+ "NumMortOutstanding" : "1",
91
+ "NumMortPartSatisfied" : "0",
92
+ "NumMortSatisfied" : "0"
93
+ },
94
+ "SICCodes" : {
95
+ "SicText" : [
96
+ "62090 - Other information technology service activities"
97
+ ]
98
+ }
99
+ }
100
+ ```
81
101
 
82
102
  TODO: Use some funky metaprogramming to make these available as human-readable
83
103
  method calls, eg `company.name` or `company.registered_address.line_1`.
@@ -1,4 +1,35 @@
1
- # require 'rubygems'
2
1
  require 'faraday'
3
2
  require 'json'
4
- require File.join(File.dirname(__FILE__), 'companies_house/companies_house')
3
+ require 'companies_house/request'
4
+ require 'companies_house/response'
5
+
6
+ module CompaniesHouse
7
+
8
+ class CompanyNotFound < StandardError
9
+ end
10
+
11
+ class InvalidRegistration < StandardError
12
+ end
13
+
14
+ class ServerError < StandardError
15
+ end
16
+
17
+ class << self
18
+
19
+ # Public API
20
+ #
21
+ # Usage:
22
+ # company = CompaniesHouse.lookup "07495895"
23
+ # => #<CompaniesHouse:0x00000100932870 @registration_number="07495895"... >
24
+ #
25
+ # company["CompanyName"]
26
+ # => "GOCARDLESS LTD"
27
+ #
28
+ def lookup(registration_number)
29
+ Request.new(registration_number).perform
30
+ end
31
+
32
+ attr_accessor :cache, :cache_args
33
+ end
34
+
35
+ end
@@ -0,0 +1,39 @@
1
+ module CompaniesHouse
2
+
3
+ class Request
4
+
5
+ BASE_URI = 'http://data.companieshouse.gov.uk/doc/company/'
6
+
7
+ # Don't call this directly. Instead, use CompaniesHouse.lookup "01234567"
8
+ def initialize(registration_number)
9
+ @registration_number = validate(registration_number)
10
+ @attributes = {}
11
+ end
12
+
13
+ def perform
14
+ url = BASE_URI + @registration_number + ".json"
15
+ response = with_caching { Faraday.get(url) }
16
+ Response.new(response)
17
+ end
18
+
19
+ private
20
+
21
+ # Use cache if configured
22
+ def with_caching(&block)
23
+ args = CompaniesHouse.cache_args || {}
24
+ cache = CompaniesHouse.cache
25
+ cache ? cache.fetch(@registration_number, args, &block) : yield
26
+ end
27
+
28
+ def validate(number)
29
+ number = number.to_s.strip # remove whitespace
30
+
31
+ number = "0" + number if number.length == 7 # 0-pad for luck
32
+
33
+ msg = "#{number} is not a valid UK company registration number"
34
+ raise InvalidRegistration.new(msg) unless number =~ /\A[0-9]{8}\z/
35
+
36
+ number
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,47 @@
1
+ module CompaniesHouse
2
+
3
+ class Response
4
+
5
+ def initialize(response)
6
+ check_for_errors(response)
7
+ parse_response(response)
8
+ end
9
+
10
+ # Return a SIC code from the ugly hash
11
+ #
12
+ # company.sic_code
13
+ # => "62090"
14
+ #
15
+ def sic_code
16
+ if self["SICCodes"] && self["SICCodes"]["SicText"]
17
+ self["SICCodes"]["SicText"].first.split[0]
18
+ end
19
+ end
20
+
21
+ # So that you can call attributes on the companies house object:
22
+ # company["CompanyName"]
23
+ def [](key)
24
+ @attributes[key]
25
+ end
26
+
27
+ private
28
+
29
+ def check_for_errors(response)
30
+ if response.status == 404
31
+ msg = "Company not found with registration #{@registration_number}"
32
+ raise CompanyNotFound.new(msg)
33
+ end
34
+
35
+ unless response.status == 200
36
+ msg = "Companies House Responded with status #{response.status}"
37
+ raise ServerError.new(msg)
38
+ end
39
+ end
40
+
41
+ def parse_response(response)
42
+ body = response.body.encode("UTF-8", "ISO-8859-1")
43
+ data = JSON.parse(body)
44
+ @attributes = data["primaryTopic"]
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
- class CompaniesHouse
2
- VERSION = '0.1.1'.freeze
1
+ module CompaniesHouse
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -5,88 +5,16 @@ describe CompaniesHouse do
5
5
  let(:subject) { CompaniesHouse }
6
6
 
7
7
  describe ".lookup" do
8
-
9
- context "throws an exception" do
10
- it "with a number that's too short" do
11
- expect {
12
- subject.lookup "123456"
13
- }.to raise_exception CompaniesHouse::InvalidRegistration
14
- end
15
-
16
- it "that's too long" do
17
- expect {
18
- subject.lookup "123456789"
19
- }.to raise_exception CompaniesHouse::InvalidRegistration
20
- end
21
-
22
- it "that's not numeric" do
23
- expect {
24
- subject.lookup "abcdefgh"
25
- }.to raise_exception CompaniesHouse::InvalidRegistration
26
- end
27
-
28
- it "that's nil" do
29
- expect {
30
- subject.lookup nil
31
- }.to raise_exception CompaniesHouse::InvalidRegistration
32
- end
8
+ it "initializes a request" do
9
+ CompaniesHouse::Request.expects(:new).with("12345678").
10
+ returns(stub(perform: true))
11
+ subject.lookup "12345678"
33
12
  end
34
13
 
35
- context "with a valid request" do
36
- before do
37
- url = "http://data.companieshouse.gov.uk/doc/company/07495895.json"
38
- stub_request(:get, url).to_return(
39
- :body => load_fixture("gocardless.json"),
40
- :status => 200
41
- )
42
- end
43
-
44
- it "0-pads 7 digit registration numbers" do
45
- company = subject.lookup "7495895"
46
- company.registration_number.should == "07495895"
47
- end
48
-
49
- it "loads attributes into the object body" do
50
- company = subject.lookup "07495895"
51
- company["CompanyName"].should == "GOCARDLESS LTD"
52
- end
53
-
54
- it "makes SIC code available as a convenience method" do
55
- company = subject.lookup "07495895"
56
- company.sic_code.should == "62090"
57
- end
58
- end
59
-
60
- context "with a company that doesn't exist" do
61
- before do
62
- url = "http://data.companieshouse.gov.uk/doc/company/12345678.json"
63
- stub_request(:get, url).to_return(
64
- :body => "Some bullshit HTML response :-(",
65
- :status => 404
66
- )
67
- end
68
-
69
- it "raises an exception" do
70
- expect {
71
- company = subject.lookup "12345678"
72
- }.to raise_exception CompaniesHouse::CompanyNotFound
73
- end
74
- end
75
-
76
- context "when the server is down" do
77
- before do
78
- url = "http://data.companieshouse.gov.uk/doc/company/12345678.json"
79
- stub_request(:get, url).to_return(
80
- :body => "Oh noes",
81
- :status => 500
82
- )
83
- end
84
-
85
- it "raises an exception" do
86
- expect {
87
- company = subject.lookup "12345678"
88
- }.to raise_exception CompaniesHouse::ServerError
89
- end
14
+ it "calls perform on the request and returns the response" do
15
+ CompaniesHouse::Request.stubs(:new).with("12345678").
16
+ returns(mock(perform: true))
17
+ subject.lookup "12345678"
90
18
  end
91
19
  end
92
20
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe CompaniesHouse::Request do
4
+
5
+ let(:subject) { CompaniesHouse::Request }
6
+
7
+ describe "#new" do
8
+ context "throws an exception" do
9
+ it "with a number that's too short" do
10
+ expect {
11
+ subject.new "123456"
12
+ }.to raise_exception CompaniesHouse::InvalidRegistration
13
+ end
14
+
15
+ it "that's too long" do
16
+ expect {
17
+ subject.new "123456789"
18
+ }.to raise_exception CompaniesHouse::InvalidRegistration
19
+ end
20
+
21
+ it "that's not numeric" do
22
+ expect {
23
+ subject.new "abcdefgh"
24
+ }.to raise_exception CompaniesHouse::InvalidRegistration
25
+ end
26
+
27
+ it "that's nil" do
28
+ expect {
29
+ subject.new nil
30
+ }.to raise_exception CompaniesHouse::InvalidRegistration
31
+ end
32
+ end
33
+
34
+ it "0-pads 7 digit registration numbers" do
35
+ company = subject.new "7495895"
36
+ company.instance_variable_get(:@registration_number).
37
+ should == "07495895"
38
+ end
39
+ end
40
+
41
+
42
+ describe "perform" do
43
+
44
+ before { @request = subject.new("7495895") }
45
+
46
+ it "makes an http request" do
47
+ CompaniesHouse::Response.stubs(:new)
48
+ Faraday.expects(:get).with("http://data.companieshouse.gov.uk/doc/company/07495895.json")
49
+ @request.perform
50
+ end
51
+
52
+ it "passes the response to a Response object" do
53
+ stub_response = stub
54
+ CompaniesHouse::Response.expects(:new).with(stub_response)
55
+ Faraday.stubs(:get).returns(stub_response)
56
+ @request.perform
57
+ end
58
+
59
+ it "caches the request (if enabled)" do
60
+ cached_response = stub
61
+ cache_stub = stub(fetch: cached_response)
62
+ CompaniesHouse.cache = cache_stub # configure
63
+ CompaniesHouse::Response.expects(:new).with(cached_response)
64
+ @request.perform
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe CompaniesHouse::Response do
4
+
5
+ let(:subject) { CompaniesHouse::Response }
6
+
7
+ context "with a successful http response" do
8
+ before do
9
+ url = "http://data.companieshouse.gov.uk/doc/company/07495895.json"
10
+ stub_request(:get, url).to_return(
11
+ :body => load_fixture("gocardless.json"),
12
+ :status => 200
13
+ )
14
+ @response = subject.new(Faraday.get(url))
15
+ end
16
+
17
+ it "loads attributes into the object body" do
18
+ @response["CompanyName"].should == "GOCARDLESS LTD"
19
+ end
20
+
21
+ it "makes SIC code available as a convenience method" do
22
+ @response.sic_code.should == "62090"
23
+ end
24
+ end
25
+
26
+ context "with a company that doesn't exist" do
27
+ before do
28
+ @url = "http://data.companieshouse.gov.uk/doc/company/12345678.json"
29
+ stub_request(:get, @url).to_return(
30
+ :body => "Some bullshit HTML response :-(",
31
+ :status => 404
32
+ )
33
+ end
34
+
35
+ it "raises an exception" do
36
+ expect {
37
+ subject.new(Faraday.get(@url))
38
+ }.to raise_exception CompaniesHouse::CompanyNotFound
39
+ end
40
+ end
41
+
42
+ context "when the server is down" do
43
+ before do
44
+ @url = "http://data.companieshouse.gov.uk/doc/company/12345678.json"
45
+ stub_request(:get, @url).to_return(
46
+ :body => "Oh noes",
47
+ :status => 500
48
+ )
49
+ end
50
+
51
+ it "raises an exception" do
52
+ expect {
53
+ subject.new(Faraday.get(@url))
54
+ }.to raise_exception CompaniesHouse::ServerError
55
+ end
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open-companies-house
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -104,10 +104,13 @@ files:
104
104
  - README.md
105
105
  - Rakefile
106
106
  - lib/companies_house.rb
107
- - lib/companies_house/companies_house.rb
107
+ - lib/companies_house/request.rb
108
+ - lib/companies_house/response.rb
108
109
  - lib/companies_house/version.rb
109
110
  - open_companies_house.gemspec
110
111
  - spec/companies_house/companies_house_spec.rb
112
+ - spec/companies_house/request_spec.rb
113
+ - spec/companies_house/response_spec.rb
111
114
  - spec/data/gocardless.json
112
115
  - spec/spec_helper.rb
113
116
  homepage: https://github.com/gocardless/open-companies-house
@@ -136,5 +139,7 @@ specification_version: 3
136
139
  summary: A wrapper around Companies House Open API
137
140
  test_files:
138
141
  - spec/companies_house/companies_house_spec.rb
142
+ - spec/companies_house/request_spec.rb
143
+ - spec/companies_house/response_spec.rb
139
144
  - spec/data/gocardless.json
140
145
  - spec/spec_helper.rb
@@ -1,95 +0,0 @@
1
- class CompaniesHouse
2
-
3
- class CompanyNotFound < StandardError
4
- end
5
-
6
- class InvalidRegistration < StandardError
7
- end
8
-
9
- class ServerError < StandardError
10
- end
11
-
12
- BASE_URI = 'http://data.companieshouse.gov.uk/doc/company/'
13
-
14
- # Public API
15
- #
16
- # Usage:
17
- # company = CompaniesHouse.lookup "07495895"
18
- # => #<CompaniesHouse:0x00000100932870 @registration_number="07495895"... >
19
- #
20
- # company["CompanyName"]
21
- # => "GOCARDLESS LTD"
22
- #
23
- def self.lookup(registration_number)
24
- obj = self.new(registration_number)
25
- obj.lookup
26
- obj
27
- end
28
-
29
- # Return a SIC code from the ugly hash
30
- #
31
- # company.sic_code
32
- # => "62090"
33
- #
34
- def sic_code
35
- if self["SICCodes"] && self["SICCodes"]["SicText"]
36
- self["SICCodes"]["SicText"].first.split[0]
37
- end
38
- end
39
-
40
- # So that you can call attributes on the companies house object:
41
- # company["CompanyName"]
42
- def [](key)
43
- @attributes[key]
44
- end
45
-
46
- attr_accessor :registration_number
47
-
48
- # Don't call this directly. Instead, use CompaniesHouse.lookup "01234567"
49
- def initialize(registration_number)
50
- @registration_number = check_registration(registration_number)
51
- @attributes = {}
52
- end
53
-
54
- # perform the HTTP request
55
- def lookup
56
- url = BASE_URI + @registration_number + ".json"
57
- response = Faraday.get(url)
58
- check_for_errors(response)
59
- parse_response(response)
60
- end
61
-
62
- private
63
-
64
- def check_registration(number)
65
- number = number.to_s.strip # remove whitespace
66
-
67
- number = "0" + number if number.length == 7 # 0-pad for luck
68
-
69
- msg = "#{number} is not a valid UK company registration number"
70
- raise InvalidRegistration.new(msg) unless number =~ /\A[0-9]{8}\z/
71
-
72
- number
73
- end
74
-
75
- def check_for_errors(response)
76
- if response.status == 404
77
- msg = "Company not found with registration #{@registration_number}"
78
- raise CompanyNotFound.new(msg)
79
- end
80
-
81
- unless response.status == 200
82
- msg = "Companies House Responded with status #{response.status}"
83
- raise ServerError.new(msg)
84
- end
85
- end
86
-
87
- def parse_response(response)
88
- # The response uses HTTP default Latin-1 encoding. Convert it to
89
- # valid UTF8 as storing this in Mongo (for example) can cause
90
- # problems.
91
- body = response.body.encode("UTF-8", "ISO-8859-1")
92
- data = JSON.parse(body)
93
- @attributes = data["primaryTopic"]
94
- end
95
- end