guardian_searcher 0.1.2 → 0.1.3

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: bbf80793abdcb30ddb0acb6ff62cc97bf5d2e230881d2057e391f61c3490fa4e
4
- data.tar.gz: c6df4f2b8cd92f9ba2ae7fa29ae57eb3e4ad3d2a7637176e0c1a8ec53b7f654e
3
+ metadata.gz: dd89428bf856036e8d19111810e1a8b0bab64c545db11b6b0779b1f7c7654016
4
+ data.tar.gz: f485ddd884db4a21c9f75a0961640f46143014cbb392ac7de6e894726964cbce
5
5
  SHA512:
6
- metadata.gz: 6d5779ce66ac3507594a07a52db236e1c581729e8b2b05d27ff11287ef8e9dce7eb69b54a9f80298a0fc2d096d3b952f1eb8fc64d3b389713fbedfd0a8e70720
7
- data.tar.gz: de83958f007a38e71bfe15d4637aa645feb2d88e370582cef5de3c4fc67a9daf720fae26bd4062e7a32ce7c6a5921aa42d8d5b57be8af8f51514ec2cd8e3fda9
6
+ metadata.gz: d67c795dca8079a6768b8ab9bfd44335fde907c110dac3a4fbd3be20cab9da5e0f2ebf125f41003c936b8d13bc486ce33eae3c0e1232f3bfd6b9cd66229ead45
7
+ data.tar.gz: 4868618271ecc78d2cfc66c1389bba17504072755a06dbdd563cfa5023450ad0bc5674f09416ca728e915c46f931a65c04a912577c84f4e80035f9a899293943
data/.gitignore CHANGED
@@ -11,4 +11,5 @@
11
11
  # rspec failure tracking
12
12
  Gemfile.lock
13
13
  .rspec_status
14
+ .byebug_history
14
15
  .DS_Store
data/CHANGELOG.md CHANGED
@@ -1,5 +1,6 @@
1
1
  ## [Unreleased]
2
2
 
3
+
3
4
  ## [0.1.0] - 2022-10-01
4
5
 
5
6
  - Initial release
@@ -7,3 +8,15 @@
7
8
  ## [0.1.1] - 2022-10-01
8
9
 
9
10
  - Fix dependency warnings
11
+
12
+ ## [0.1.2] - 2022-10-04
13
+
14
+ - Moved options parse in their Options class
15
+ - Updated readme
16
+
17
+ ## [0.1.3] - 2022-10-23
18
+
19
+ - Added Content class
20
+ - Added Helpers classes ( Generator & Util)
21
+ - Added some additional methods to Base class - search tags and editons endpoints
22
+ - Improved code coverage (Happy Paths only for now)
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # GuardianSearcher
2
2
 
3
- This is a work in progress, and its status is currently not even an alpha version. Tests needs to be implemented and the code is not optimal.
3
+
4
+ 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.
4
5
  The goal of this project is to provide a Ruby wrapper to query the Guardian Api and to experiment with some programming techniques.
5
6
 
7
+ Documentation of TheGuardian API is [Here](https://open-platform.theguardian.com/documentation/)
8
+
6
9
  If you wanna try it you need to have an API key and use it as an environment variable.
7
10
 
8
11
  ```bash
@@ -57,6 +60,77 @@ results = searcher.search('your keyword', { from_date: '2022-10-01', page_size:
57
60
 
58
61
  If you add something unsupported it will throw an `OptionsNotSupportedError`
59
62
 
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
+
65
+ ```ruby
66
+ response_body = searcher.search('your keyword', { from_date: '2022-10-01', page_size: 10 }).body
67
+ results = GuardianSearcher::SearchResult.parse_results(body: response_body)
68
+ ```
69
+ This will return a `SearchResult` object which the following attributes:
70
+
71
+ ```ruby
72
+ @current_page
73
+ @results # an array with all the search results
74
+ @page_size # paging size
75
+ @pages # number of pages
76
+ @start # starting page
77
+ ```
78
+
79
+ Of interest the structure of a single element of the results array, which is an Hash array similar to this
80
+
81
+ ```ruby
82
+ {"id"=>"football/2022/sep/23/player-mutiny-exposes-deeper-issues-within-spanish-womens-football",
83
+ "type"=>"article",
84
+ "sectionId"=>"football",
85
+ "sectionName"=>"Football",
86
+ "webPublicationDate"=>"2022-09-23T19:20:09Z",
87
+ "webTitle"=>"Player mutiny exposes deeper issues within Spanish women’s football | Sid Lowe",
88
+ "webUrl"=>"https://www.theguardian.com/football/2022/sep/23/player-mutiny-exposes-deeper-issues-within-spanish-womens-football",
89
+ "apiUrl"=>"https://content.guardianapis.com/football/2022/sep/23/player-mutiny-exposes-deeper-issues-within-spanish-womens-football",
90
+ "isHosted"=>false,
91
+ "pillarId"=>"pillar/sport",
92
+ "pillarName"=>"Sport"}
93
+ ```
94
+ At this point you can use the `SearchResult` object as it is or you could convert it to an Array of `Content` objects in the following way:
95
+ ```ruby
96
+ generator = GuardianSearcher::Helpers::Generator.new
97
+ # results is the SearchResult object created before which has an attribute
98
+ # called results. Not a great name choice but sorry about that
99
+ contents = generator.generate(results.results, "GuardianSearcher::Content")
100
+ ```
101
+
102
+ Each element of the `contents` Array will be an instance of the `Content` class, with a number of attributes that depends on the returned results i.e. that
103
+ if an element of the results attribute is something like:
104
+ ```ruby
105
+ {"id"=>"football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus",
106
+ "type"=>"article",
107
+ "sectionId"=>"football",
108
+ "sectionName"=>"Football",
109
+ "webPublicationDate"=>"2022-06-27T08:42:20Z",
110
+ "webTitle"=>"Football transfer rumours: Chelsea to sign Matthijs de Ligt from Juventus? ",
111
+ "webUrl"=>"https://www.theguardian.com/football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus",
112
+ "apiUrl"=>"https://content.guardianapis.com/football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus",
113
+ "isHosted"=>false,
114
+ "pillarId"=>"pillar/sport",
115
+ "pillarName"=>"Sport"}
116
+ ```
117
+ One element of the `contents` array will be something like:
118
+
119
+ ```ruby
120
+ <GuardianSearcher::Content:0x0000000150b7fe70
121
+ @api_url="https://content.guardianapis.com/football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus",
122
+ @id="football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus",
123
+ @is_hosted=false,
124
+ @pillar_id="pillar/sport",
125
+ @pillar_name="Sport",
126
+ @section_id="football",
127
+ @section_name="Football",
128
+ @type="article",
129
+ @web_publication_date="2022-06-27T08:42:20Z",
130
+ @web_title="Football transfer rumours: Chelsea to sign Matthijs de Ligt from Juventus? ",
131
+ @web_url="https://www.theguardian.com/football/2022/jun/27/football-transfer-rumours-chelsea-to-sign-matthijs-de-ligt-from-juventus">
132
+ ```
133
+
60
134
  ## Development
61
135
 
62
136
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -8,7 +8,10 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = "Alain Mauri"
9
9
  spec.email = "wildeng@hotmail.com"
10
10
 
11
- spec.summary = "A wrapper to search articles from The Guardian"
11
+ spec.summary = "A wrapper to search articles from The Guardian, using its open API.
12
+ You need to register and get your api key to properly use this gem.
13
+ It uses Faraday to make the API calls and has some classes that should help in formatting
14
+ the results as easy to manage Ruby object."
12
15
  spec.homepage = "https://alainmauri.eu"
13
16
  spec.license = "MIT"
14
17
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
@@ -30,6 +33,7 @@ Gem::Specification.new do |spec|
30
33
  # spec.add_dependency "example-gem", "~> 1.0"
31
34
  spec.add_dependency "faraday", "~> 2.2"
32
35
 
36
+ spec.add_development_dependency "byebug", "~> 11"
33
37
  spec.add_development_dependency "guard", "~> 2.18"
34
38
  spec.add_development_dependency "guard-bundler", "~> 3.0"
35
39
  spec.add_development_dependency "guard-rspec", "~> 4.7"
@@ -1,36 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
+ # Class that handles the basic functionality for the Guardian Reader gem
4
5
  class Base
5
6
  include Faraday
6
7
 
7
8
  attr_reader :api_key
8
- attr_accessor :base_uri
9
9
 
10
10
  def initialize(api_key: nil)
11
- @base_uri = "https://content.guardianapis.com"
12
-
13
11
  raise GuardianApyKeyError unless api_key
14
12
 
15
13
  @api_key = api_key
16
14
  end
17
15
 
18
16
  # Options needs to be passed following Guardian API docs
19
- def search(q, options = {})
20
- opt = build_options(options)
17
+ def search(query, options = {})
18
+ url = search_uri + query_string(query, options)
19
+ Faraday.get(url)
20
+ end
21
21
 
22
- url = @base_uri + "/search?q=#{q}&#{opt}&api-key=#{@api_key}"
22
+ def search_sections(query, options = {})
23
+ url = sections_uri + query_string(query, options)
23
24
  Faraday.get(url)
24
25
  end
25
26
 
26
- def search_sections(q, options = {})
27
- opt = build_options(options)
28
- url = @base_uri + "/sections?q=#{q}&#{opt}&api-key=#{@api_key}"
27
+ def search_tags(query, options = {})
28
+ url = tags_uri + query_string(query, options)
29
+ Faraday.get(url)
30
+ end
31
+
32
+ def search_editions(query, options = {})
33
+ url = editions_uri + query_string(query, options)
29
34
  Faraday.get(url)
30
35
  end
31
36
 
32
37
  private
33
38
 
39
+ def base_uri
40
+ "https://content.guardianapis.com"
41
+ end
42
+
43
+ def sections_uri
44
+ "#{base_uri}/sections"
45
+ end
46
+
47
+ def search_uri
48
+ "#{base_uri}/search"
49
+ end
50
+
51
+ def tags_uri
52
+ "#{base_uri}/tags"
53
+ end
54
+
55
+ def editions_uri
56
+ "#{base_uri}/editions"
57
+ end
58
+
59
+ def query_string(q, options = {})
60
+ opt = build_options(options)
61
+ "?q=#{q}&#{opt}&api-key=#{@api_key}"
62
+ end
63
+
34
64
  def build_options(options)
35
65
  Options.new(options).build_options
36
66
  end
@@ -1,6 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
- class Content < GuardianSearcher::Base
4
+ class Content
5
+ include GuardianSearcher::Helpers::Util
6
+ def initialize(attributes)
7
+ attributes.each do |key, attribute_value|
8
+ attr_name = key
9
+ attr_name = snakecase(key) unless key.is_a? Symbol
10
+ self.class.send(:define_method, "#{attr_name}=".to_sym) do |value|
11
+ instance_variable_set("@#{attr_name}", value)
12
+ end
13
+
14
+ self.class.send(:define_method, attr_name.to_sym) do
15
+ instance_variable_get("@#{attr_name}")
16
+ end
17
+
18
+ send("#{attr_name}=".to_sym, attribute_value)
19
+ end
20
+ end
5
21
  end
6
22
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GuardianSearcher
4
+ module Helpers
5
+ # The class helps generating an array of object from the passed parameters
6
+ # It can be used to generate e.g. an array of Content objects, each one
7
+ # initialised with the data of a single results Hash coming from the Guardian
8
+ # API response
9
+ class Generator
10
+ def generate(results, klass)
11
+ content = []
12
+ results.each do |result|
13
+ content << Object.const_get(klass).new(result)
14
+ end
15
+ content
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GuardianSearcher
4
+ module Helpers
5
+ module Util
6
+ # this method comes from the facets library
7
+ # I took it from there because it was easier for
8
+ # what I have in mind
9
+ #
10
+ # original here https://github.com/rubyworks/facets
11
+ # docs here https://www.rubydoc.info/github/rubyworks/facets/String:snakecase
12
+ def snakecase(key)
13
+ return unless key.is_a? String
14
+
15
+ key.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
16
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
17
+ .tr("-", "_")
18
+ .gsub(/\s/, "_")
19
+ .gsub(/__+/, "_")
20
+ .downcase
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
- class OptionsNotHashError < StandardError; end
5
- class OptionsNotSupportedError < StandardError; end
6
-
7
4
  class Options < Hash
8
5
  private attr_accessor :options
9
6
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GuardianSearcher
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.3"
5
5
  end
@@ -3,6 +3,9 @@
3
3
  require_relative "guardian_searcher/version"
4
4
  require "faraday"
5
5
  require_relative "guardian_searcher/base"
6
+ require_relative "guardian_searcher/helpers/util"
7
+ require_relative "guardian_searcher/helpers/generator"
8
+ require_relative "guardian_searcher/content"
6
9
  require_relative "guardian_searcher/search"
7
10
  require_relative "guardian_searcher/search_result"
8
11
  require_relative "guardian_searcher/section_result"
@@ -11,4 +14,6 @@ require_relative "guardian_searcher/options"
11
14
  module GuardianSearcher
12
15
  class Error < StandardError; end
13
16
  class GuardianApyKeyError < StandardError; end
17
+ class OptionsNotHashError < StandardError; end
18
+ class OptionsNotSupportedError < StandardError; end
14
19
  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.2
4
+ version: 0.1.3
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-04 00:00:00.000000000 Z
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '11'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: guard
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +131,8 @@ files:
117
131
  - lib/guardian_searcher.rb
118
132
  - lib/guardian_searcher/base.rb
119
133
  - lib/guardian_searcher/content.rb
134
+ - lib/guardian_searcher/helpers/generator.rb
135
+ - lib/guardian_searcher/helpers/util.rb
120
136
  - lib/guardian_searcher/options.rb
121
137
  - lib/guardian_searcher/search.rb
122
138
  - lib/guardian_searcher/search_result.rb
@@ -147,5 +163,8 @@ requirements: []
147
163
  rubygems_version: 3.2.15
148
164
  signing_key:
149
165
  specification_version: 4
150
- summary: A wrapper to search articles from The Guardian
166
+ summary: A wrapper to search articles from The Guardian, using its open API. You need
167
+ to register and get your api key to properly use this gem. It uses Faraday to make
168
+ the API calls and has some classes that should help in formatting the results as
169
+ easy to manage Ruby object.
151
170
  test_files: []