parliament-ruby 0.6.3 → 0.7.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 581a69e9850b75eef39d684fd40f5347ebcf8bb1
4
- data.tar.gz: f28f46585c4dc4cfd9f14735918804e184367d4f
3
+ metadata.gz: 1d6e3ce9cb153b579936aca384cbdb8f73d1c824
4
+ data.tar.gz: 8ab2872d2a93301be8420d3ba7815ef809a855c4
5
5
  SHA512:
6
- metadata.gz: 5e1f64b23a425ee4e1b9c4a816eeb1f583a7c84a382010b0da35c6ef2dfcb5fc5ea0fc5a4bb23764b8b50650edcb5985b718e918bca9b3192137543930d9217c
7
- data.tar.gz: '08882fbca6ac37527cd83420cb0a6d1a8bbf120db74e73ebdc8114548b40110d988948fdeaf37c97e803f5d791adf15d81d0cf8a7813080462cfe6b9d9c35cc8'
6
+ metadata.gz: a7ba819f59a91286db8a2dd132b1b61d590e057ba93347da04692c87d0d10da37f03b9beeeda90aed8b18adf19871ecae6052da1eec46b2696166fd989b5ca8f
7
+ data.tar.gz: 18aa6d056e56843c7d08456d6b3a3b78dcdeeeac8ab2aecd78ded20b5ae785d80095755c607daa110663db61a9e0bab81ae9e2b65a16bdbbe67d379484af3f60
data/Gemfile CHANGED
@@ -5,3 +5,6 @@ gemspec
5
5
 
6
6
  # Include coveralls for CI coverage reports
7
7
  gem 'coveralls', require: false
8
+
9
+ gem 'pry'
10
+ gem 'rb-readline'
@@ -0,0 +1,13 @@
1
+ module Parliament
2
+ module Builder
3
+ class BaseResponseBuilder
4
+ def initialize(response)
5
+ @response = response
6
+ end
7
+
8
+ def build
9
+ @response
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Parliament
2
+ module Builder
3
+ class NTripleResponseBuilder < Parliament::Builder::BaseResponseBuilder
4
+ def build
5
+ objects = Grom::Reader.new(@response.body).objects
6
+ objects.map { |object| assign_decorator(object) }
7
+
8
+ Parliament::Response.new(objects)
9
+ end
10
+
11
+ private
12
+
13
+ def assign_decorator(object)
14
+ return object unless object.respond_to?(:type)
15
+
16
+ object_type = Grom::Helper.get_id(object.type)
17
+
18
+ return object unless Parliament::Decorator.constants.include?(object_type.to_sym)
19
+
20
+ decorator_module = Object.const_get("Parliament::Decorator::#{object_type}")
21
+ object.extend(decorator_module)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ require 'feedjira'
2
+
3
+ module Parliament
4
+ module Builder
5
+ class OpenSearchResponseBuilder < Parliament::Builder::BaseResponseBuilder
6
+ OPEN_SEARCH_ELEMENTS = %w(totalResults Query startIndex itemsPerPage).freeze
7
+
8
+ def build
9
+ OPEN_SEARCH_ELEMENTS.each do |element|
10
+ Feedjira::Feed.add_common_feed_element(element)
11
+ end
12
+
13
+ Feedjira::Feed.parse(@response.body)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module Parliament
2
+ module Builder
3
+ Dir[File.join(File.dirname(__FILE__), '../parliament/builder', '*.rb')].each { |builder| require builder }
4
+ end
5
+ end
@@ -13,14 +13,14 @@ module Parliament
13
13
  #
14
14
  # @return [DateTime, nil] the start date of the Grom::Node or nil.
15
15
  def start_date
16
- respond_to?(:constituencyGroupStartDate) ? DateTime.parse(constituencyGroupStartDate) : nil
16
+ @start_date ||= respond_to?(:constituencyGroupStartDate) ? DateTime.parse(constituencyGroupStartDate) : nil
17
17
  end
18
18
 
19
19
  # Alias constituencyGroupEndDate with fallback.
20
20
  #
21
21
  # @return [DateTime, nil] the end date of the Grom::Node or nil.
22
22
  def end_date
23
- respond_to?(:constituencyGroupEndDate) ? DateTime.parse(constituencyGroupEndDate) : nil
23
+ @end_date ||= respond_to?(:constituencyGroupEndDate) ? DateTime.parse(constituencyGroupEndDate) : nil
24
24
  end
25
25
 
26
26
  # Alias constituencyGroupHasHouseSeat with fallback.
@@ -6,23 +6,21 @@ module Parliament
6
6
  #
7
7
  # @return [DateTime, nil] the start date of the Grom::Node or nil.
8
8
  def start_date
9
- respond_to?(:incumbencyStartDate) ? DateTime.parse(incumbencyStartDate) : nil
9
+ @start_date ||= respond_to?(:incumbencyStartDate) ? DateTime.parse(incumbencyStartDate) : nil
10
10
  end
11
11
 
12
12
  # Alias incumbencyEndDate with fallback.
13
13
  #
14
14
  # @return [DateTime, nil] the end date of the Grom::Node or nil.
15
15
  def end_date
16
- respond_to?(:incumbencyEndDate) ? DateTime.parse(incumbencyEndDate) : nil
16
+ @end_date ||= respond_to?(:incumbencyEndDate) ? DateTime.parse(incumbencyEndDate) : nil
17
17
  end
18
18
 
19
19
  # Checks if Grom::Node has an end date.
20
20
  #
21
21
  # @return [Boolean] a boolean depending on whether or not the Grom::Node has an end date.
22
22
  def current?
23
- has_end_date = respond_to?(:incumbencyEndDate)
24
-
25
- !has_end_date
23
+ end_date.nil?
26
24
  end
27
25
 
28
26
  # Alias houseIncumbencyHasHouse with fallback.
@@ -6,23 +6,21 @@ module Parliament
6
6
  #
7
7
  # @return [DateTime, nil] the start date of the Grom::Node or nil.
8
8
  def start_date
9
- respond_to?(:incumbencyStartDate) ? DateTime.parse(incumbencyStartDate) : nil
9
+ @start_date ||= respond_to?(:incumbencyStartDate) ? DateTime.parse(incumbencyStartDate) : nil
10
10
  end
11
11
 
12
12
  # Alias incumbencyEndDate with fallback.
13
13
  #
14
14
  # @return [DateTime, nil] the end date of the Grom::Node or nil.
15
15
  def end_date
16
- respond_to?(:incumbencyEndDate) ? DateTime.parse(incumbencyEndDate) : nil
16
+ @end_date ||= respond_to?(:incumbencyEndDate) ? DateTime.parse(incumbencyEndDate) : nil
17
17
  end
18
18
 
19
19
  # Checks if Grom::Node has an end date.
20
20
  #
21
21
  # @return [Boolean] a boolean depending on whether or not the Grom::Node has an end date.
22
22
  def current?
23
- has_end_date = respond_to?(:incumbencyEndDate)
24
-
25
- !has_end_date
23
+ end_date.nil?
26
24
  end
27
25
 
28
26
  # Alias incumbencyHasMember with fallback.
@@ -13,23 +13,21 @@ module Parliament
13
13
  #
14
14
  # @return [DateTime, nil] the start date of the Grom::Node or nil.
15
15
  def start_date
16
- respond_to?(:partyMembershipStartDate) ? DateTime.parse(partyMembershipStartDate) : nil
16
+ @start_date ||= respond_to?(:partyMembershipStartDate) ? DateTime.parse(partyMembershipStartDate) : nil
17
17
  end
18
18
 
19
19
  # Alias partyMembershipEndDate with fallback.
20
20
  #
21
21
  # @return [DateTime, nil] the end date of the Grom::Node or nil.
22
22
  def end_date
23
- respond_to?(:partyMembershipEndDate) ? DateTime.parse(partyMembershipEndDate) : nil
23
+ @end_date ||= respond_to?(:partyMembershipEndDate) ? DateTime.parse(partyMembershipEndDate) : nil
24
24
  end
25
25
 
26
26
  # Checks if Grom::Node has an end date.
27
27
  #
28
28
  # @return [Boolean] a boolean depending on whether or not the Grom::Node has an end date.
29
29
  def current?
30
- has_end_date = respond_to?(:partyMembershipEndDate)
31
-
32
- !has_end_date
30
+ end_date.nil?
33
31
  end
34
32
  end
35
33
  end
@@ -28,17 +28,20 @@ module Parliament
28
28
  #
29
29
  # @return [DateTime, nil] the date of birth of the Grom::Node or nil.
30
30
  def date_of_birth
31
- respond_to?(:personDateOfBirth) ? DateTime.parse(personDateOfBirth) : nil
31
+ @date_of_birth ||= respond_to?(:personDateOfBirth) ? DateTime.parse(personDateOfBirth) : nil
32
32
  end
33
33
 
34
34
  # Builds a full name using personGivenName and personFamilyName.
35
35
  #
36
36
  # @return [String, String] the full name of the Grom::Node or an empty string.
37
37
  def full_name
38
- full_name = ''
39
- full_name += respond_to?(:personGivenName) ? personGivenName + ' ' : ''
40
- full_name += respond_to?(:personFamilyName) ? personFamilyName : ''
41
- full_name.rstrip
38
+ return @full_name unless @full_name.nil?
39
+
40
+ full_name = []
41
+ full_name << personGivenName if respond_to?(:personGivenName)
42
+ full_name << personFamilyName if respond_to?(:personFamilyName)
43
+
44
+ @full_name = full_name.join(' ')
42
45
  end
43
46
 
44
47
  # Alias memberHasIncumbency with fallback.
@@ -52,68 +55,35 @@ module Parliament
52
55
  #
53
56
  # @return [Array, Array] the seat incumbencies of the Grom::Node or an empty array.
54
57
  def seat_incumbencies
55
- if respond_to?(:memberHasIncumbency)
56
- memberHasIncumbency.select { |inc| inc.type == 'http://id.ukpds.org/schema/SeatIncumbency' }
57
- else
58
- []
59
- end
58
+ @seat_incumbencies ||= incumbencies.select { |inc| inc.type == 'http://id.ukpds.org/schema/SeatIncumbency' }
60
59
  end
61
60
 
62
61
  # Alias memberHasIncumbency with fallback.
63
62
  #
64
63
  # @return [Array, Array] the house incumbencies of the Grom::Node or an empty array.
65
64
  def house_incumbencies
66
- if respond_to?(:memberHasIncumbency)
67
- memberHasIncumbency.select { |inc| inc.type == 'http://id.ukpds.org/schema/HouseIncumbency' }
68
- else
69
- []
70
- end
65
+ @house_incumbencies ||= incumbencies.select { |inc| inc.type == 'http://id.ukpds.org/schema/HouseIncumbency' }
71
66
  end
72
67
 
73
68
  # Alias seatIncumbencyHasHouseSeat with fallback.
74
69
  #
75
70
  # @return [Array, Array] the seats of the Grom::Node or an empty array.
76
71
  def seats
77
- return @seats unless @seats.nil?
78
-
79
- seats = []
80
- seat_incumbencies.each do |incumbency|
81
- seats << incumbency.seat if incumbency.respond_to?(:seat)
82
- end
83
-
84
- @seats = seats.flatten.uniq
72
+ @seats ||= seat_incumbencies.map(&:seat).flatten.uniq
85
73
  end
86
74
 
87
75
  # Alias houseSeatHasHouse with fallback.
88
76
  #
89
77
  # @return [Array, Array] the houses of the Grom::Node or an empty array.
90
78
  def houses
91
- return @houses unless @houses.nil?
92
-
93
- houses = []
94
- seats.each do |seat|
95
- houses << seat.house
96
- end
97
-
98
- house_incumbencies.each do |inc|
99
- houses << inc.house
100
- end
101
-
102
- @houses = houses.flatten.uniq
79
+ @houses ||= [seats.map(&:house), house_incumbencies.map(&:house)].flatten.uniq
103
80
  end
104
81
 
105
82
  # Alias houseSeatHasConstituencyGroup with fallback.
106
83
  #
107
84
  # @return [Array, Array] the constituencies of the Grom::Node or an empty array.
108
85
  def constituencies
109
- return @constituencies unless @constituencies.nil?
110
-
111
- constituencies = []
112
- seats.each do |seat|
113
- constituencies << seat.constituency
114
- end
115
-
116
- @constituencies = constituencies.flatten.uniq
86
+ @constituencies ||= seats.map(&:constituency).flatten.uniq
117
87
  end
118
88
 
119
89
  # Alias partyMemberHasPartyMembership with fallback.
@@ -127,14 +97,7 @@ module Parliament
127
97
  #
128
98
  # @return [Array, Array] the parties of the Grom::Node or an empty array.
129
99
  def parties
130
- return @parties unless @parties.nil?
131
-
132
- parties = []
133
- party_memberships.each do |party_membership|
134
- parties << party_membership.party
135
- end
136
-
137
- @parties = parties.flatten.uniq.compact
100
+ @parties ||= party_memberships.map(&:party).flatten.uniq.compact
138
101
  end
139
102
 
140
103
  # Alias personHasContactPoint with fallback.
@@ -203,6 +166,7 @@ module Parliament
203
166
  build_house_membership_status(no_current_seat_incumbency, no_current_house_incumbency, former_lord, former_mp)
204
167
  end
205
168
 
169
+ # TODO: Convert hard-coded strings to language file values
206
170
  def build_house_membership_status(no_current_seat_incumbency, no_current_house_incumbency, former_lord, former_mp)
207
171
  statuses = []
208
172
  statuses << 'Current MP' unless no_current_seat_incumbency
@@ -23,13 +23,18 @@ module Parliament
23
23
  respond_to?(:seatIncumbencyHasHouseSeat) ? seatIncumbencyHasHouseSeat.first : nil
24
24
  end
25
25
 
26
- # Checks if Grom::Node has an end date.
26
+ # Checks if Grom::Node has no end date.
27
27
  #
28
28
  # @return [Boolean] a boolean depending on whether or not the Grom::Node has an end date.
29
29
  def current?
30
- has_end_date = respond_to?(:incumbencyEndDate)
30
+ !former?
31
+ end
31
32
 
32
- !has_end_date
33
+ # Checks if Grom::Node has an end date.
34
+ #
35
+ # @return [Boolean] a boolean depending on whether or not the Grom::Node has an end date.
36
+ def former?
37
+ respond_to?(:incumbencyEndDate)
33
38
  end
34
39
 
35
40
  # Alias houseSeatHasHouse with fallback.
@@ -0,0 +1,136 @@
1
+ module Parliament
2
+ module Request
3
+ class BaseRequest
4
+ attr_reader :base_url, :headers
5
+ # Creates a new instance of Parliament::Request.
6
+ #
7
+ # An interesting note for #initialize is that setting base_url on the class, or using the environment variable
8
+ # PARLIAMENT_BASE_URL means you don't need to pass in a base_url. You can pass one anyway to override the
9
+ # environment variable or class parameter. Similarly, headers can be set by either settings the headers on the class, or passing headers in.
10
+ #
11
+ # @example Setting the base_url on the class
12
+ # Parliament::Request.base_url = 'http://example.com'
13
+ #
14
+ # Parliament::Request.new.base_url #=> 'http://example.com'
15
+ #
16
+ # @example Setting the base_url via environment variable
17
+ # ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'
18
+ #
19
+ # Parliament::Request.new.base_url #=> 'http://test.com'
20
+ #
21
+ # @example Setting the base_url via a parameter
22
+ # Parliament::Request.base_url #=> nil
23
+ # ENV['PARLIAMENT_BASE_URL'] #=> nil
24
+ #
25
+ # Parliament::Request.new(base_url: 'http://example.com').base_url #=> 'http://example.com'
26
+ #
27
+ # @example Overriding the base_url via a parameter
28
+ # ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'
29
+ #
30
+ # Parliament::Request.new(base_url: 'http://example.com').base_url #=> 'http://example.com'
31
+ #
32
+ # @example Setting the headers on the class
33
+ # Parliament::Request.headers = { 'Accept' => 'Test' }
34
+ #
35
+ # Parliament::Request.new.headers #=> '{ 'Accept' => 'Test' }
36
+ #
37
+ # @example Setting the headers via a parameter
38
+ # Parliament::Request.headers #=> nil
39
+ #
40
+ # Parliament::Request.new(headers: '{ 'Accept' => 'Test' }).headers #=> { 'Accept' => 'Test' }
41
+ #
42
+ # @example Overriding the headers via a parameter
43
+ # Parliament::Request.headers = { 'Accept' => 'Test' }
44
+ #
45
+ # Parliament::Request.new(headers: '{ 'Accept' => 'Test2' }).headers #=> { 'Accept' => 'Test2' }
46
+ #
47
+ # @param [String] base_url the base url of our api. (expected: http://example.com - without the trailing slash).
48
+ # @param [Hash] headers the headers being sent in the request.
49
+ def initialize(base_url: nil, headers: nil, builder: nil)
50
+ @base_url = base_url || self.class.base_url
51
+ @headers = headers || self.class.headers || {}
52
+ @builder = builder || Parliament::Builder::BaseResponseBuilder
53
+ end
54
+
55
+ # Using our url built via #method_missing, make a HTTP GET request and process results into a response.
56
+ #
57
+ # @example HTTP GET request
58
+ # request = Parliament::Request.new(base_url: 'http://example.com')
59
+ #
60
+ # # url: http://example.com/people/123456
61
+ # response = request.people('123456').get #=> #<Parliament::Response ...>
62
+ #
63
+ # @example HTTP GET request with URI encoded form values
64
+ # request = Parliament::Request.new(base_url: 'http://example.com')
65
+ #
66
+ # # url: http://example.com/people/current?limit=10&page=4&lang=en-gb
67
+ # response = request.people.current.get({ limit: 10, page: 4, lang: 'en-gb' }) #=> #<Parliament::Response ...>
68
+ #
69
+ # @raise [Parliament::ServerError] when the server responds with a 5xx status code.
70
+ # @raise [Parliament::ClientError] when the server responds with a 4xx status code.
71
+ # @raise [Parliament::NoContentResponseError] when the server responds with a 204 status code.
72
+ #
73
+ # @param [Hash] params (optional) additional URI encoded form values to be added to the URI.
74
+ #
75
+ # @return [Parliament::Response] a Parliament::Response object containing all of the nodes returned from the URL.
76
+ def get(params: nil)
77
+ endpoint_uri = URI.parse(query_url)
78
+ endpoint_uri.query = URI.encode_www_form(params.to_a) unless params.nil?
79
+
80
+ http = Net::HTTP.new(endpoint_uri.host, endpoint_uri.port)
81
+ http.use_ssl = true if endpoint_uri.scheme == 'https'
82
+
83
+ net_response = http.start do |h|
84
+ api_request = Net::HTTP::Get.new(endpoint_uri.request_uri)
85
+ add_headers(api_request)
86
+
87
+ h.request api_request
88
+ end
89
+
90
+ handle_errors(net_response)
91
+
92
+ build_response(net_response)
93
+ end
94
+
95
+ private
96
+
97
+ # @attr [String] base_url the base url of our api. (expected: http://example.com - without the trailing slash).
98
+ # @attr [Hash] headers the headers being sent in the request.
99
+ class << self
100
+ attr_accessor :base_url, :headers
101
+ end
102
+
103
+ def build_response(net_response)
104
+ @builder.new(net_response).build
105
+ end
106
+
107
+ def query_url
108
+ @base_url
109
+ end
110
+
111
+ def default_headers
112
+ { 'Accept' => 'application/n-triples' }
113
+ end
114
+
115
+ def add_headers(request)
116
+ headers = default_headers.merge(@headers)
117
+ headers.each do |key, value|
118
+ request.add_field(key, value)
119
+ end
120
+ end
121
+
122
+ def handle_errors(response)
123
+ case response
124
+ when Net::HTTPSuccess # 2xx Status
125
+ exception_class = Parliament::NoContentResponseError if response.code == '204'
126
+ when Net::HTTPClientError # 4xx Status
127
+ exception_class = Parliament::ClientError
128
+ when Net::HTTPServerError # 5xx Status
129
+ exception_class = Parliament::ServerError
130
+ end
131
+
132
+ raise exception_class.new(query_url, response) if exception_class
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,73 @@
1
+ module Parliament
2
+ module Request
3
+ class OpenSearchRequest < Parliament::Request::BaseRequest
4
+ OPEN_SEARCH_PARAMETERS = {
5
+ count: 10,
6
+ start_index: 1,
7
+ start_page: 1,
8
+ language: '*',
9
+ output_encoding: 'UTF-8',
10
+ input_encoding: 'UTF-8'
11
+ }.freeze
12
+
13
+ def initialize(base_url: nil, headers: nil, builder: nil)
14
+ @base_url = Parliament::Request::OpenSearchRequest.get_description(base_url) || self.class.base_url || ENV['OPENSEARCH_DESCRIPTION_URL']
15
+ @open_search_parameters = self.class.open_search_parameters
16
+
17
+ super(base_url: @base_url, headers: headers, builder: builder)
18
+ end
19
+
20
+ def get(search_params, params: nil)
21
+ setup_query_url(search_params)
22
+
23
+ super(params: params)
24
+ end
25
+
26
+ private
27
+
28
+ class << self
29
+ attr_reader :base_url, :open_search_parameters
30
+
31
+ def base_url=(base_url)
32
+ @base_url = get_description(base_url)
33
+ end
34
+
35
+ def open_search_parameters
36
+ OPEN_SEARCH_PARAMETERS.dup
37
+ end
38
+
39
+ def get_description(url)
40
+ return if url.nil?
41
+
42
+ request = Parliament::Request::BaseRequest.new(base_url: url,
43
+ headers: { 'Accept' => 'application/opensearchdescription+xml' })
44
+ xml_response = request.get
45
+
46
+ xml_root = REXML::Document.new(xml_response.body).root
47
+ xml_root.elements['Url'].attributes['template']
48
+ end
49
+ end
50
+
51
+ def query_url
52
+ @query_url
53
+ end
54
+
55
+ def setup_query_url(search_params)
56
+ search_terms = search_params[:query]
57
+ query_url = @base_url.dup
58
+ query_url.gsub!('{searchTerms}', search_terms)
59
+
60
+ @open_search_parameters.each do |key, value|
61
+ camel_case_key = ActiveSupport::Inflector.camelize(key.to_s, false)
62
+ if search_params.keys.include?(key)
63
+ query_url.gsub!("{#{camel_case_key}?}", search_params[key].to_s)
64
+ else
65
+ query_url.gsub!("{#{camel_case_key}?}", value.to_s)
66
+ end
67
+ end
68
+
69
+ @query_url = query_url
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,60 @@
1
+ module Parliament
2
+ module Request
3
+ class UrlRequest < Parliament::Request::BaseRequest
4
+ def initialize(base_url: nil, headers: nil, builder: nil)
5
+ @endpoint_parts = []
6
+ base_url ||= ENV['PARLIAMENT_BASE_URL']
7
+
8
+ super
9
+ end
10
+
11
+ # Overrides ruby's method_missing to allow creation of URLs through method calls.
12
+ #
13
+ # @example Adding a simple URL part
14
+ # request = Parliament::Request.new(base_url: 'http://example.com')
15
+ #
16
+ # # url: http://example.com/people
17
+ # request.people
18
+ #
19
+ # @example Adding a simple URL part with parameters
20
+ # request = Parliament::Request.new(base_url: 'http://example.com')
21
+ #
22
+ # # url: http://example.com/people/123456
23
+ # request.people('123456')
24
+ #
25
+ # @example Chaining URL parts and using hyphens
26
+ # request = Parliament::Request.new(base_url: 'http://example.com')
27
+ #
28
+ # # url: http://example.com/people/123456/foo/bar/hello-world/7890
29
+ # request.people('123456').foo.bar('hello-world', '7890')
30
+ #
31
+ # @param [Symbol] method the 'method' (url part) we are processing.
32
+ # @param [Array<Object>] params parameters passed to the specified method (url part).
33
+ # @param [Block] block additional block (kept for compatibility with method_missing API).
34
+ #
35
+ # @return [Parliament::Request] self.
36
+ def method_missing(method, *params, &block)
37
+ @endpoint_parts << method.to_s
38
+ @endpoint_parts << params
39
+ @endpoint_parts = @endpoint_parts.flatten!
40
+
41
+ block&.call
42
+
43
+ self || super
44
+ end
45
+
46
+ # This class always responds to method calls, even those missing. Therefore, respond_to_missing? always returns true.
47
+ #
48
+ # @return [Boolean] always returns true.
49
+ def respond_to_missing?(_, _ = false)
50
+ true # responds to everything, always
51
+ end
52
+
53
+ private
54
+
55
+ def query_url
56
+ [@base_url, @endpoint_parts].join('/')
57
+ end
58
+ end
59
+ end
60
+ end
@@ -6,193 +6,7 @@ module Parliament
6
6
  #
7
7
  # @attr_reader [String] base_url the base url of our api. (expected: http://example.com - without the trailing slash).
8
8
  # @attr_reader [Hash] headers the headers being sent in the request.
9
- class Request
10
- attr_reader :base_url, :headers
11
-
12
- # Creates a new instance of Parliament::Request.
13
- #
14
- # An interesting note for #initialize is that setting base_url on the class, or using the environment variable
15
- # PARLIAMENT_BASE_URL means you don't need to pass in a base_url. You can pass one anyway to override the
16
- # environment variable or class parameter. Similarly, headers can be set by either settings the headers on the class, or passing headers in.
17
- #
18
- # @example Setting the base_url on the class
19
- # Parliament::Request.base_url = 'http://example.com'
20
- #
21
- # Parliament::Request.new.base_url #=> 'http://example.com'
22
- #
23
- # @example Setting the base_url via environment variable
24
- # ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'
25
- #
26
- # Parliament::Request.new.base_url #=> 'http://test.com'
27
- #
28
- # @example Setting the base_url via a parameter
29
- # Parliament::Request.base_url #=> nil
30
- # ENV['PARLIAMENT_BASE_URL'] #=> nil
31
- #
32
- # Parliament::Request.new(base_url: 'http://example.com').base_url #=> 'http://example.com'
33
- #
34
- # @example Overriding the base_url via a parameter
35
- # ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'
36
- #
37
- # Parliament::Request.new(base_url: 'http://example.com').base_url #=> 'http://example.com'
38
- #
39
- # @example Setting the headers on the class
40
- # Parliament::Request.headers = { 'Accept' => 'Test' }
41
- #
42
- # Parliament::Request.new.headers #=> '{ 'Accept' => 'Test' }
43
- #
44
- # @example Setting the headers via a parameter
45
- # Parliament::Request.headers #=> nil
46
- #
47
- # Parliament::Request.new(headers: '{ 'Accept' => 'Test' }).headers #=> { 'Accept' => 'Test' }
48
- #
49
- # @example Overriding the headers via a parameter
50
- # Parliament::Request.headers = { 'Accept' => 'Test' }
51
- #
52
- # Parliament::Request.new(headers: '{ 'Accept' => 'Test2' }).headers #=> { 'Accept' => 'Test2' }
53
- #
54
- # @param [String] base_url the base url of our api. (expected: http://example.com - without the trailing slash).
55
- # @param [Hash] headers the headers being sent in the request.
56
- def initialize(base_url: nil, headers: nil)
57
- @endpoint_parts = []
58
- @base_url = base_url || self.class.base_url || ENV['PARLIAMENT_BASE_URL']
59
- @headers = headers || self.class.headers || {}
60
- end
61
-
62
- # Overrides ruby's method_missing to allow creation of URLs through method calls.
63
- #
64
- # @example Adding a simple URL part
65
- # request = Parliament::Request.new(base_url: 'http://example.com')
66
- #
67
- # # url: http://example.com/people
68
- # request.people
69
- #
70
- # @example Adding a simple URL part with parameters
71
- # request = Parliament::Request.new(base_url: 'http://example.com')
72
- #
73
- # # url: http://example.com/people/123456
74
- # request.people('123456')
75
- #
76
- # @example Chaining URL parts and using hyphens
77
- # request = Parliament::Request.new(base_url: 'http://example.com')
78
- #
79
- # # url: http://example.com/people/123456/foo/bar/hello-world/7890
80
- # request.people('123456').foo.bar('hello-world', '7890')
81
- #
82
- # @param [Symbol] method the 'method' (url part) we are processing.
83
- # @param [Array<Object>] params parameters passed to the specified method (url part).
84
- # @param [Block] block additional block (kept for compatibility with method_missing API).
85
- #
86
- # @return [Parliament::Request] self.
87
- def method_missing(method, *params, &block)
88
- @endpoint_parts << method.to_s
89
- @endpoint_parts << params
90
- @endpoint_parts = @endpoint_parts.flatten!
91
-
92
- block&.call
93
-
94
- self || super
95
- end
96
-
97
- # This class always responds to method calls, even those missing. Therefore, respond_to_missing? always returns true.
98
- #
99
- # @return [Boolean] always returns true.
100
- def respond_to_missing?(_, _ = false)
101
- true # responds to everything, always
102
- end
103
-
104
- # Using our url built via #method_missing, make a HTTP GET request and process results into a response.
105
- #
106
- # @example HTTP GET request
107
- # request = Parliament::Request.new(base_url: 'http://example.com')
108
- #
109
- # # url: http://example.com/people/123456
110
- # response = request.people('123456').get #=> #<Parliament::Response ...>
111
- #
112
- # @example HTTP GET request with URI encoded form values
113
- # request = Parliament::Request.new(base_url: 'http://example.com')
114
- #
115
- # # url: http://example.com/people/current?limit=10&page=4&lang=en-gb
116
- # response = request.people.current.get({ limit: 10, page: 4, lang: 'en-gb' }) #=> #<Parliament::Response ...>
117
- #
118
- # @raise [Parliament::ServerError] when the server responds with a 5xx status code.
119
- # @raise [Parliament::ClientError] when the server responds with a 4xx status code.
120
- # @raise [Parliament::NoContentResponseError] when the server responds with a 204 status code.
121
- #
122
- # @param [Hash] params (optional) additional URI encoded form values to be added to the URI.
123
- #
124
- # @return [Parliament::Response] a Parliament::Response object containing all of the nodes returned from the URL.
125
- def get(params: nil)
126
- endpoint_uri = URI.parse(api_endpoint)
127
- endpoint_uri.query = URI.encode_www_form(params.to_a) unless params.nil?
128
-
129
- http = Net::HTTP.new(endpoint_uri.host, endpoint_uri.port)
130
- http.use_ssl = true if endpoint_uri.scheme == 'https'
131
-
132
- net_response = http.start do |h|
133
- api_request = Net::HTTP::Get.new(endpoint_uri.request_uri)
134
- add_headers(api_request)
135
-
136
- h.request api_request
137
- end
138
-
139
- handle_errors(net_response)
140
-
141
- build_parliament_response(net_response)
142
- end
143
-
144
- private
145
-
146
- # @attr [String] base_url the base url of our api. (expected: http://example.com - without the trailing slash).
147
- # @attr [Hash] headers the headers being sent in the request.
148
- class << self
149
- attr_accessor :base_url, :headers
150
- end
151
-
152
- def default_headers
153
- { 'Accept' => 'application/n-triples' }
154
- end
155
-
156
- def add_headers(request)
157
- headers = default_headers.merge(@headers)
158
- headers.each do |key, value|
159
- request.add_field(key, value)
160
- end
161
- end
162
-
163
- def api_endpoint
164
- [@base_url, @endpoint_parts].join('/')
165
- end
166
-
167
- def handle_errors(response)
168
- case response
169
- when Net::HTTPSuccess # 2xx Status
170
- exception_class = Parliament::NoContentResponseError if response.code == '204'
171
- when Net::HTTPClientError # 4xx Status
172
- exception_class = Parliament::ClientError
173
- when Net::HTTPServerError # 5xx Status
174
- exception_class = Parliament::ServerError
175
- end
176
-
177
- raise exception_class.new(api_endpoint, response) if exception_class
178
- end
179
-
180
- def build_parliament_response(response)
181
- objects = Grom::Reader.new(response.body).objects
182
- objects.map { |object| assign_decorator(object) }
183
-
184
- Parliament::Response.new(objects)
185
- end
186
-
187
- def assign_decorator(object)
188
- return object unless object.respond_to?(:type)
189
-
190
- object_type = Grom::Helper.get_id(object.type)
191
-
192
- return object unless Parliament::Decorator.constants.include?(object_type.to_sym)
193
-
194
- decorator_module = Object.const_get("Parliament::Decorator::#{object_type}")
195
- object.extend(decorator_module)
196
- end
9
+ module Request
10
+ Dir[File.join(File.dirname(__FILE__), '../parliament/request', '*.rb')].each { |request| require request }
197
11
  end
198
12
  end
@@ -1,3 +1,3 @@
1
1
  module Parliament
2
- VERSION = '0.6.3'.freeze
2
+ VERSION = '0.7.0.pre'.freeze
3
3
  end
data/lib/parliament.rb CHANGED
@@ -6,6 +6,7 @@ require 'parliament/request'
6
6
  require 'parliament/response'
7
7
  require 'parliament/utils'
8
8
  require 'parliament/decorator'
9
+ require 'parliament/builder'
9
10
 
10
11
  require 'parliament/network_error'
11
12
  require 'parliament/client_error'
@@ -13,7 +13,6 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'http://github.com/ukparliament/parliament_ruby'
14
14
  spec.license = 'Nonstandard'
15
15
 
16
-
17
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
17
  f.match(%r{^(test|spec|features)/})
19
18
  end
@@ -21,6 +20,7 @@ Gem::Specification.new do |spec|
21
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
21
  spec.require_paths = ['lib']
23
22
 
23
+ spec.add_dependency 'feedjira', '~> 2.1.2'
24
24
  spec.add_dependency 'grom', '~> 0.3.6'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 1.13'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parliament-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Rayner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-31 00:00:00.000000000 Z
11
+ date: 2017-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: feedjira
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.1.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: grom
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -144,6 +158,10 @@ files:
144
158
  - bin/console
145
159
  - bin/setup
146
160
  - lib/parliament.rb
161
+ - lib/parliament/builder.rb
162
+ - lib/parliament/builder/base_response_builder.rb
163
+ - lib/parliament/builder/ntriple_response_builder.rb
164
+ - lib/parliament/builder/open_search_response_builder.rb
147
165
  - lib/parliament/client_error.rb
148
166
  - lib/parliament/decorator.rb
149
167
  - lib/parliament/decorator/constituency_area.rb
@@ -163,6 +181,9 @@ files:
163
181
  - lib/parliament/network_error.rb
164
182
  - lib/parliament/no_content_response_error.rb
165
183
  - lib/parliament/request.rb
184
+ - lib/parliament/request/base_request.rb
185
+ - lib/parliament/request/open_search_request.rb
186
+ - lib/parliament/request/url_request.rb
166
187
  - lib/parliament/response.rb
167
188
  - lib/parliament/server_error.rb
168
189
  - lib/parliament/utils.rb
@@ -183,12 +204,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
204
  version: '0'
184
205
  required_rubygems_version: !ruby/object:Gem::Requirement
185
206
  requirements:
186
- - - ">="
207
+ - - ">"
187
208
  - !ruby/object:Gem::Version
188
- version: '0'
209
+ version: 1.3.1
189
210
  requirements: []
190
211
  rubyforge_project:
191
- rubygems_version: 2.6.6
212
+ rubygems_version: 2.6.10
192
213
  signing_key:
193
214
  specification_version: 4
194
215
  summary: Internal parliamentary API wrapper