guardian_searcher 0.1.3 → 0.1.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd89428bf856036e8d19111810e1a8b0bab64c545db11b6b0779b1f7c7654016
4
- data.tar.gz: f485ddd884db4a21c9f75a0961640f46143014cbb392ac7de6e894726964cbce
3
+ metadata.gz: e3df7ad5dba2bad5467f4f3b0b09dc360a7e8c2b097dfddbb6bbc126ba997af1
4
+ data.tar.gz: 700a5915369af7e4313b4e94601d5d68a3e83f164fd3e7f6ef702a26fae8f350
5
5
  SHA512:
6
- metadata.gz: d67c795dca8079a6768b8ab9bfd44335fde907c110dac3a4fbd3be20cab9da5e0f2ebf125f41003c936b8d13bc486ce33eae3c0e1232f3bfd6b9cd66229ead45
7
- data.tar.gz: 4868618271ecc78d2cfc66c1389bba17504072755a06dbdd563cfa5023450ad0bc5674f09416ca728e915c46f931a65c04a912577c84f4e80035f9a899293943
6
+ metadata.gz: 3f53981c222f1409b0541b555f07b59dd2aa64847d6680255008ac739f40e2a66669d6dc3be1fe6d012c86bac6fe15aef691577510715a3f573b3a5453bc1d67
7
+ data.tar.gz: 295dfad1a4a45d31543c264f24a0c76c4e0354fc0b666293b9f810e9727e0b5ea7c5fc4e909e22f8de89ac5e4749fa6d8316e6999d8d4cc082b12b948a0447f5
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: Guardian Searcher gem test suite
3
+ run-name: ${{ github.actor }} is running the test suite
4
+ on:
5
+ push:
6
+ branches: [develop]
7
+ pull_request:
8
+ branches: [main]
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby-version: ['2.7', '3.0', '3.1', '3.3']
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+ - name: Install Ruby ${{ matrix.ruby-version }}
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby-version }}
22
+ bundler-cache: true
23
+ - name: Install dependencies
24
+ run: bundle install
25
+ - name: Run tests
26
+ run: bundle exec rake spec
27
+
28
+
data/.gitignore CHANGED
@@ -13,3 +13,4 @@ Gemfile.lock
13
13
  .rspec_status
14
14
  .byebug_history
15
15
  .DS_Store
16
+ project_context.txt
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## [Unreleased]
2
+ - Parse results and return an exception based on the Guardian API response
2
3
 
4
+ ## [0.1.4] - 2026-06-28
5
+ - Moved API key from URL query string to request header to prevent leakage in logs
3
6
 
4
7
  ## [0.1.0] - 2022-10-01
5
8
 
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # GuardianSearcher
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/guardian_searcher.svg)](https://badge.fury.io/rb/guardian_searcher)
3
4
 
4
5
  This is a work in progress, and its status is currently an alpha version. Tests needs to be implemented and the code is not optimal.
5
6
  The goal of this project is to provide a Ruby wrapper to query the Guardian Api and to experiment with some programming techniques.
@@ -60,7 +61,7 @@ results = searcher.search('your keyword', { from_date: '2022-10-01', page_size:
60
61
 
61
62
  If you add something unsupported it will throw an `OptionsNotSupportedError`
62
63
 
63
- The results of the search can be used as they are, a Farady response object or you can parse them using `GuardianSearcher::SearchResult` in the following way:
64
+ The results of the search can be used as they are, a Farady response object or you can parse - remember to check for the response code first - them using `GuardianSearcher::SearchResult` in the following way:
64
65
 
65
66
  ```ruby
66
67
  response_body = searcher.search('your keyword', { from_date: '2022-10-01', page_size: 10 }).body
@@ -76,6 +77,22 @@ This will return a `SearchResult` object which the following attributes:
76
77
  @start # starting page
77
78
  ```
78
79
 
80
+ However if you want the gem to take care of the response codes and use its built in errors just use
81
+
82
+ ```ruby
83
+ response = searcher.search('your keyword', { from_date: '2022-10-01', page_size: 10 })
84
+ results = GuardianSearcher::SearchResult.parse_with_codes(response)
85
+ ```
86
+
87
+ This will return a `SearchResult` object or one of the following errors
88
+
89
+ ```ruby
90
+ GuardianUnauthorizedError # when a 401 is returned
91
+ GuardianBadRequestError # when a 400 is returned
92
+ GuardianInternalServerError # when a 500 is returned
93
+ GuardianUnknownError # when an error code is not among the above ones
94
+ ```
95
+
79
96
  Of interest the structure of a single element of the results array, which is an Hash array similar to this
80
97
 
81
98
  ```ruby
@@ -16,22 +16,22 @@ module GuardianSearcher
16
16
  # Options needs to be passed following Guardian API docs
17
17
  def search(query, options = {})
18
18
  url = search_uri + query_string(query, options)
19
- Faraday.get(url)
19
+ Faraday.get(url, nil, headers)
20
20
  end
21
21
 
22
22
  def search_sections(query, options = {})
23
23
  url = sections_uri + query_string(query, options)
24
- Faraday.get(url)
24
+ Faraday.get(url, nil, headers)
25
25
  end
26
26
 
27
27
  def search_tags(query, options = {})
28
28
  url = tags_uri + query_string(query, options)
29
- Faraday.get(url)
29
+ Faraday.get(url, nil, headers)
30
30
  end
31
31
 
32
32
  def search_editions(query, options = {})
33
33
  url = editions_uri + query_string(query, options)
34
- Faraday.get(url)
34
+ Faraday.get(url, nil, headers)
35
35
  end
36
36
 
37
37
  private
@@ -58,11 +58,15 @@ module GuardianSearcher
58
58
 
59
59
  def query_string(q, options = {})
60
60
  opt = build_options(options)
61
- "?q=#{q}&#{opt}&api-key=#{@api_key}"
61
+ "?q=#{q}&#{opt}"
62
62
  end
63
63
 
64
64
  def build_options(options)
65
65
  Options.new(options).build_options
66
66
  end
67
+
68
+ def headers
69
+ { "api-key" => @api_key }
70
+ end
67
71
  end
68
72
  end
@@ -7,11 +7,11 @@ module GuardianSearcher
7
7
  attributes.each do |key, attribute_value|
8
8
  attr_name = key
9
9
  attr_name = snakecase(key) unless key.is_a? Symbol
10
- self.class.send(:define_method, "#{attr_name}=".to_sym) do |value|
10
+ define_singleton_method("#{attr_name}=".to_sym) do |value|
11
11
  instance_variable_set("@#{attr_name}", value)
12
12
  end
13
13
 
14
- self.class.send(:define_method, attr_name.to_sym) do
14
+ define_singleton_method(attr_name.to_sym) do
15
15
  instance_variable_get("@#{attr_name}")
16
16
  end
17
17
 
@@ -1,16 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
+ # the class maps the options passed to the ones needed
5
+ # by the Guardian API for searching
4
6
  class Options < Hash
5
- private attr_accessor :options
6
-
7
7
  def method_missing(method_name, *args, &blk)
8
8
  return options.[](method_name, &blk) if @options.key?(method_name)
9
9
 
10
10
  super(method_name, *args, &blk)
11
11
  end
12
12
 
13
+ def respond_to_missing?(method_name, *args)
14
+ @options.key?(method_name) || super(method_name, *args)
15
+ end
16
+
13
17
  def initialize(options)
18
+ super
14
19
  raise OptionsNotHashError unless options.is_a?(Hash)
15
20
 
16
21
  @options = options
@@ -24,6 +29,7 @@ module GuardianSearcher
24
29
  valid_option?(key)
25
30
  opt += "&#{map_option(key)}=#{value}"
26
31
  end
32
+ return opt
27
33
  end
28
34
 
29
35
  def valid_option?(option)
@@ -38,5 +44,9 @@ module GuardianSearcher
38
44
  page: "page"
39
45
  }[key]
40
46
  end
47
+
48
+ private
49
+
50
+ attr_accessor :options
41
51
  end
42
52
  end
@@ -4,24 +4,45 @@ require "json"
4
4
 
5
5
  module GuardianSearcher
6
6
  class SearchResult
7
- attr_reader :results, :start, :page_size, :pages, :current_page
7
+ attr_reader :results, :start, :page_size, :pages, :current_page, :editions
8
8
 
9
9
  def initialize(
10
10
  current_page: nil,
11
11
  results: nil,
12
12
  page_size: nil,
13
13
  pages: nil,
14
- start: nil
14
+ start: nil,
15
+ editions: nil
15
16
  )
16
-
17
17
  @current_page = current_page
18
18
  @results = results
19
19
  @page_size = page_size
20
20
  @pages = pages
21
21
  @start = start
22
+ @editions = editions
23
+ end
24
+
25
+ def self.parse_with_codes(response: nil)
26
+ raise GuardianSearcher::GuardianSearcherUndefinedResponse unless response
27
+
28
+ case response.status
29
+ when 200
30
+ parse_results(body: response.body)
31
+ when 400
32
+ message = JSON.parse(response.body)["message"]
33
+ raise GuardianSearcher::GuardianBadRequestError, message
34
+ when 401
35
+ message = JSON.parse(response.body)["message"]
36
+ raise GuardianSearcher::GuardianUnauthorizedError, message
37
+ when 500
38
+ message = JSON.parse(response.body)["message"]
39
+ raise GuardianSearcher::GuardianInternalServerError, message
40
+ else
41
+ raise GuardianSearcher::GuardianUnknownError, "Unknown error, check Faraday response"
42
+ end
22
43
  end
23
44
 
24
- def self.parse_results(body: nil)
45
+ def self.parse_results(body:)
25
46
  return unless body
26
47
 
27
48
  body = JSON.parse(body)
@@ -3,18 +3,9 @@
3
3
  require "json"
4
4
 
5
5
  module GuardianSearcher
6
+ # The class parses the search results and creates a new
7
+ # SearchResults object with an editions variable
6
8
  class SectionResult
7
- attr_reader :results, :editions
8
-
9
- def initialize(
10
- results: nil,
11
- editions: nil
12
- )
13
-
14
- @results = results
15
- @editions = editions
16
- end
17
-
18
9
  def self.parse_results(body: nil)
19
10
  return unless body
20
11
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
@@ -14,6 +14,11 @@ require_relative "guardian_searcher/options"
14
14
  module GuardianSearcher
15
15
  class Error < StandardError; end
16
16
  class GuardianApyKeyError < StandardError; end
17
+ class GuardianUnauthorizedError < StandardError; end
18
+ class GuardianBadRequestError < StandardError; end
19
+ class GuardianInternalServerError < StandardError; end
20
+ class GuardianUnknownError < StandardError; end
21
+ class GuardianSearcherUndefinedResponse < StandardError; end
17
22
  class OptionsNotHashError < StandardError; end
18
23
  class OptionsNotSupportedError < StandardError; end
19
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guardian_searcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alain Mauri
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-23 00:00:00.000000000 Z
11
+ date: 2026-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -114,9 +114,11 @@ executables: []
114
114
  extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
+ - ".github/workflows/gem-test.yml"
117
118
  - ".gitignore"
118
119
  - ".rspec"
119
120
  - ".rubocop.yml"
121
+ - ".ruby-version"
120
122
  - CHANGELOG.md
121
123
  - CODE_OF_CONDUCT.md
122
124
  - Gemfile
@@ -160,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
162
  - !ruby/object:Gem::Version
161
163
  version: '0'
162
164
  requirements: []
163
- rubygems_version: 3.2.15
165
+ rubygems_version: 3.5.23
164
166
  signing_key:
165
167
  specification_version: 4
166
168
  summary: A wrapper to search articles from The Guardian, using its open API. You need