guardian_searcher 0.1.2 → 0.1.3

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
  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: []