guardian-content 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/LICENSE +1 -0
- data/README.rdoc +64 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/guardian-content.gemspec +68 -0
- data/lib/guardian-content.rb +32 -0
- data/lib/guardian-content/content.rb +107 -0
- data/lib/guardian-content/contributor.rb +26 -0
- data/lib/guardian-content/extensions.rb +57 -0
- data/lib/guardian-content/keyword.rb +26 -0
- data/lib/guardian-content/section.rb +66 -0
- data/lib/guardian-content/tag.rb +72 -0
- data/test/helper.rb +12 -0
- data/test/test_guardian-content.rb +87 -0
- data/test/test_search_content.rb +70 -0
- data/test/test_section.rb +39 -0
- data/test/test_tag_search.rb +43 -0
- metadata +111 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Some kind of licence should go here.
|
data/README.rdoc
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= guardian-content
|
2
|
+
|
3
|
+
This gem allows you to interface with the Guardian-Content-API[http://www.guardian.co.uk/open-platform] via Ruby.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Installation is as simple as typing the following text into a command prompt (such as Terminal):
|
8
|
+
|
9
|
+
gem install guardian-content
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
To use the library within a project, simply include the line <code>require 'guardian-content'</code> - you can then use any of the methods listed below.
|
14
|
+
|
15
|
+
Whilst the Guardian Content API doesn't require an API key for basic usage, for increased rate limits, and the ability to retrieve full text content, it is recommended that you register for an API key at http://guardian.mashery.com/. Once authorised, you can use the key via either declaring a <code>GUARDIAN_CONTENT_API_KEY</code> constant, or via the <code>key</code> param when initialising the class.
|
16
|
+
|
17
|
+
=== Basic searching
|
18
|
+
|
19
|
+
To do a basic free text search of Guardian documents, simply use the following command:
|
20
|
+
|
21
|
+
articles = GuardianContent::Content.search("your search term")
|
22
|
+
|
23
|
+
If successful, this will the return an array of results, which you can loop through and access via some standard attributes:
|
24
|
+
|
25
|
+
articles.each do |article|
|
26
|
+
puts article.title
|
27
|
+
puts article.url
|
28
|
+
end
|
29
|
+
|
30
|
+
To include additional meta-data in the results, use the <code>:select</code> parameter. There are two types of data you can request, tags and fields. To select all of both, use <code>:select => {:tags => :all, :fields => :all}</code>. You can then access the tags and keywords via attributes:
|
31
|
+
|
32
|
+
articles = GuardianContent::Content.search("your search term", :select => {:tags => :all, :fields => :all})
|
33
|
+
|
34
|
+
articles.first.tags.each do |tag|
|
35
|
+
puts tag[:id]
|
36
|
+
puts tag[:title]
|
37
|
+
end
|
38
|
+
|
39
|
+
puts articles.first.fields[:standfirst]
|
40
|
+
puts articles.first.fields[:headline]
|
41
|
+
|
42
|
+
=== Retrieving an article based on id
|
43
|
+
|
44
|
+
Each article or content item has a unique id. This can be accessed either via the #id attribute on a returned search result, or you can determine it from the Guardian website itself - the id is simply everything in an article's URL after the host name - eg for http://www.guardian.co.uk/world/2010/may/17/iran-nuclear-uranium-swap-turkey the id is <code>world/2010/may/17/iran-nuclear-uranium-swap-turkey</code>.
|
45
|
+
|
46
|
+
To retrieve an article based on its id, use the #find_by_id method:
|
47
|
+
|
48
|
+
article = GuardianContent::Content.find_by_id("world/2010/may/17/iran-nuclear-uranium-swap-turkey")
|
49
|
+
|
50
|
+
The article's content and meta-data can then be accessed in the same way as for search results.
|
51
|
+
|
52
|
+
== Note on Patches/Pull Requests
|
53
|
+
|
54
|
+
* Fork the project.
|
55
|
+
* Make your feature addition or bug fix.
|
56
|
+
* Add tests for it. This is important so I don't break it in a
|
57
|
+
future version unintentionally.
|
58
|
+
* Commit, do not mess with rakefile, version, or history.
|
59
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
60
|
+
* Send me a pull request. Bonus points for topic branches.
|
61
|
+
|
62
|
+
== Copyright
|
63
|
+
|
64
|
+
Copyright (c) 2010 frankieroberto. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "guardian-content"
|
8
|
+
gem.summary = %Q{Queries the Guardian Content API}
|
9
|
+
gem.description = %Q{A library for the Guardian Content API}
|
10
|
+
gem.email = "frankie@frankieroberto.com"
|
11
|
+
gem.homepage = "http://github.com/frankieroberto/guardian-content"
|
12
|
+
gem.authors = ["frankieroberto"]
|
13
|
+
gem.add_development_dependency "shoulda", ">= 2.10.3"
|
14
|
+
gem.add_dependency('httparty', '>= 0.5.2')
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/test_*.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "guardian-content #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{guardian-content}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["frankieroberto"]
|
12
|
+
s.date = %q{2010-05-19}
|
13
|
+
s.description = %q{A library for the Guardian Content API}
|
14
|
+
s.email = %q{frankie@frankieroberto.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"guardian-content.gemspec",
|
26
|
+
"lib/guardian-content.rb",
|
27
|
+
"lib/guardian-content/content.rb",
|
28
|
+
"lib/guardian-content/contributor.rb",
|
29
|
+
"lib/guardian-content/extensions.rb",
|
30
|
+
"lib/guardian-content/keyword.rb",
|
31
|
+
"lib/guardian-content/section.rb",
|
32
|
+
"lib/guardian-content/tag.rb",
|
33
|
+
"test/helper.rb",
|
34
|
+
"test/test_guardian-content.rb",
|
35
|
+
"test/test_search_content.rb",
|
36
|
+
"test/test_section.rb",
|
37
|
+
"test/test_tag_search.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/frankieroberto/guardian-content}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.6}
|
43
|
+
s.summary = %q{Queries the Guardian Content API}
|
44
|
+
s.test_files = [
|
45
|
+
"test/helper.rb",
|
46
|
+
"test/test_guardian-content.rb",
|
47
|
+
"test/test_search_content.rb",
|
48
|
+
"test/test_section.rb",
|
49
|
+
"test/test_tag_search.rb"
|
50
|
+
]
|
51
|
+
|
52
|
+
if s.respond_to? :specification_version then
|
53
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
54
|
+
s.specification_version = 3
|
55
|
+
|
56
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
57
|
+
s.add_development_dependency(%q<shoulda>, [">= 2.10.3"])
|
58
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0.5.2"])
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
61
|
+
s.add_dependency(%q<httparty>, [">= 0.5.2"])
|
62
|
+
end
|
63
|
+
else
|
64
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
65
|
+
s.add_dependency(%q<httparty>, [">= 0.5.2"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GuardianContent
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
|
6
|
+
def self.new(*params)
|
7
|
+
GuardianContent::Base.new(*params)
|
8
|
+
end
|
9
|
+
|
10
|
+
class Base
|
11
|
+
include HTTParty
|
12
|
+
base_uri 'http://content.guardianapis.com/'
|
13
|
+
|
14
|
+
def initialize(key = nil)
|
15
|
+
if defined?(GUARDIAN_CONTENT_API_KEY)
|
16
|
+
key = GUARDIAN_CONTENT_API_KEY
|
17
|
+
end
|
18
|
+
self.class.default_params "api-key" => key, "format" => "json"
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload(options = nil)
|
22
|
+
@attributes.update(self.class.find_by_id(self.id, options).instance_variable_get('@attributes'))
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
%w(extensions content section tag keyword contributor).each do |file|
|
31
|
+
require File.join(File.dirname(__FILE__), 'guardian-content', file)
|
32
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
class GuardianContent::Content < GuardianContent::Base
|
2
|
+
|
3
|
+
attr_reader :title, :id, :url, :publication_date, :section_id, :body, :keywords, :fields, :headline, :tags, :attributes
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@attributes = attributes
|
7
|
+
@id = attributes[:id]
|
8
|
+
@title = attributes[:webTitle]
|
9
|
+
@url = attributes[:webUrl]
|
10
|
+
@section_id = attributes[:sectionId]
|
11
|
+
@publication_date = DateTime.parse(attributes[:webPublicationDate]) if attributes && attributes[:webPublicationDate]
|
12
|
+
@body = attributes[:body]
|
13
|
+
|
14
|
+
if attributes[:tags]
|
15
|
+
@tags = []
|
16
|
+
attributes[:tags].each do |tag|
|
17
|
+
@tags << tag
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@fields = attributes[:fields].nested_symbolize_keys! if attributes[:fields]
|
22
|
+
|
23
|
+
if attributes[:fields]
|
24
|
+
@headline = attributes[:fields][:headline]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
"#<Article id: \"" + self.id.to_s + "\" title: \"" + self.title.to_s + "\" + url: \"" + self.url.to_s + "\">"
|
30
|
+
end
|
31
|
+
|
32
|
+
def section
|
33
|
+
return GuardianContent::Section.find_by_id(self.section_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Does a text search for content, with various options.
|
37
|
+
# === Parameters
|
38
|
+
# * <tt>:conditions</tt> - A hash which can accept <tt>:tag</tt>, <tt>:section</tt>, <tt>:from</tt> and <tt>:to</tt>, eg: <code>:conditions => {:tag => "poltiics/gordon-brown", :from => Date.yesterday}</code>
|
39
|
+
# * <tt>:limit</tt> - An integer determining the maximum number of results to return (max: 50).
|
40
|
+
# * <tt>:order</tt> - The order of the results. Can be <tt>:relevance</tt>, <tt>:oldest</tt> or <tt>:newest</tt>
|
41
|
+
# === Examples
|
42
|
+
# * GuardianContent::Content.search("election")
|
43
|
+
# * GuardianContent::Content.search("election", :conditions => {:section => "politics"})
|
44
|
+
def self.search(q, options = {})
|
45
|
+
|
46
|
+
query = {}
|
47
|
+
query["page-size"] = options[:limit] if options[:limit]
|
48
|
+
query["order-by"] = options[:order] if options[:order]
|
49
|
+
|
50
|
+
if options[:select]
|
51
|
+
if options[:select][:tags]
|
52
|
+
query["show-tags"] = options[:select][:tags]
|
53
|
+
end
|
54
|
+
if options[:select][:fields]
|
55
|
+
query["show-fields"] = options[:select][:fields]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if options[:conditions]
|
60
|
+
conditions = options[:conditions]
|
61
|
+
|
62
|
+
query[:tag] = conditions[:tag] if conditions[:tag]
|
63
|
+
query[:section] = conditions[:section] if conditions[:section]
|
64
|
+
|
65
|
+
query["from-date"] = Date.parse(conditions[:from]).to_s if conditions[:from]
|
66
|
+
query["to-date"] = Date.parse(conditions[:to]).to_s if conditions[:to]
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
query[:format] = "json"
|
72
|
+
|
73
|
+
query[:q] = q
|
74
|
+
|
75
|
+
opts = {:query => query}
|
76
|
+
|
77
|
+
response = self.get("/search", opts).nested_symbolize_keys![:response]
|
78
|
+
|
79
|
+
results = recursively_symbolize_keys!(response[:results])
|
80
|
+
content = []
|
81
|
+
|
82
|
+
results.each do |result|
|
83
|
+
content << GuardianContent::Content.new(recursively_symbolize_keys!(result))
|
84
|
+
end
|
85
|
+
return content
|
86
|
+
end
|
87
|
+
|
88
|
+
# Fetch a Content item using its id. IDs are usually in the form of <tt>section/YYYY/month/DD/name-of-article</tt>.
|
89
|
+
def self.find_by_id(id, options = {})
|
90
|
+
|
91
|
+
query = {}
|
92
|
+
query["show-fields"] = "all"
|
93
|
+
query["show-tags"] = "all"
|
94
|
+
query[:format] = "json"
|
95
|
+
opts = {:query => query}
|
96
|
+
|
97
|
+
attributes = {}
|
98
|
+
|
99
|
+
response = recursively_symbolize_keys!self.get("/#{id}", opts).nested_symbolize_keys![:response]
|
100
|
+
|
101
|
+
content = response[:content]
|
102
|
+
|
103
|
+
return GuardianContent::Content.new(recursively_symbolize_keys!(content))
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class GuardianContent::Contributor < GuardianContent::Tag
|
2
|
+
|
3
|
+
attr_reader :title, :id, :url
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@id = attributes[:id] || nil
|
7
|
+
@title = attributes[:web_title] || nil
|
8
|
+
@url = attributes[:web_url] || nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
"#<Contributor id:" + self.id.to_s + " title:\"" + self.title.to_s + "\">"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_by_id(id)
|
16
|
+
|
17
|
+
query = {}
|
18
|
+
query["show-fields"] = "all"
|
19
|
+
query[:format] = "json"
|
20
|
+
opts = {:query => query}
|
21
|
+
|
22
|
+
return GuardianContent::Contributor.new(self.get("/#{id}").nested_symbolize_keys![:response][:tag])
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Hash
|
2
|
+
# File merb/core_ext/hash.rb, line 166
|
3
|
+
def nested_symbolize_keys!
|
4
|
+
each do |k,v|
|
5
|
+
sym = k.respond_to?(:to_sym) ? k.to_sym : k
|
6
|
+
self[sym] = Hash === v ? v.nested_symbolize_keys! : v
|
7
|
+
delete(k) unless k == sym
|
8
|
+
end
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def nested_stringify_keys!
|
13
|
+
each do |k,v|
|
14
|
+
s = k.respond_to?(:to_s) ? k.to_s : k
|
15
|
+
self[s] = Hash === v ? v.nested_stringify_keys! : v
|
16
|
+
delete(k) unless k == s
|
17
|
+
end
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
# This version works with both hashes and arrays
|
24
|
+
def recursively_symbolize_keys!(obj)
|
25
|
+
case obj
|
26
|
+
when Array
|
27
|
+
obj.inject([]){|res, val|
|
28
|
+
res << case val
|
29
|
+
when Hash, Array
|
30
|
+
recursively_symbolize_keys!(val)
|
31
|
+
else
|
32
|
+
val
|
33
|
+
end
|
34
|
+
res
|
35
|
+
}
|
36
|
+
when Hash
|
37
|
+
obj.inject({}){|res, (key, val)|
|
38
|
+
nkey = case key
|
39
|
+
when String
|
40
|
+
key.to_sym
|
41
|
+
else
|
42
|
+
key
|
43
|
+
end
|
44
|
+
nval = case val
|
45
|
+
when Hash, Array
|
46
|
+
recursively_symbolize_keys!(val)
|
47
|
+
else
|
48
|
+
val
|
49
|
+
end
|
50
|
+
res[nkey] = nval
|
51
|
+
res
|
52
|
+
}
|
53
|
+
else
|
54
|
+
obj
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class GuardianContent::Keyword < GuardianContent::Tag
|
2
|
+
|
3
|
+
attr_reader :title, :id, :url
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@id = attributes[:id] || nil
|
7
|
+
@title = attributes[:web_title] || nil
|
8
|
+
@url = attributes[:web_url] || nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
"#<Keyword id:" + self.id.to_s + " title:\"" + self.title.to_s + "\">"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_by_id(id)
|
16
|
+
|
17
|
+
query = {}
|
18
|
+
query["show-fields"] = "all"
|
19
|
+
query[:format] = "json"
|
20
|
+
opts = {:query => query}
|
21
|
+
|
22
|
+
return GuardianContent::Keyword.new(self.get("/#{id}").nested_symbolize_keys![:response][:tag])
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class GuardianContent::Section < GuardianContent::Base
|
2
|
+
|
3
|
+
attr_reader :title, :id, :url
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@@attributes = attributes
|
7
|
+
@id = attributes[:id] || nil
|
8
|
+
@title = attributes[:webTitle] || nil
|
9
|
+
@url = attributes[:webUrl] || nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"#<Section id: \"" + self.id.to_s + "\" title: \"" + self.title.to_s + "\" url:\"" + self.url + "\">"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.search(q, options = {})
|
17
|
+
|
18
|
+
query = {}
|
19
|
+
|
20
|
+
query[:q] = q
|
21
|
+
query[:format] = "json"
|
22
|
+
opts = {:query => query}
|
23
|
+
|
24
|
+
response = self.get("/sections", opts).nested_symbolize_keys![:response]
|
25
|
+
|
26
|
+
results = recursively_symbolize_keys!(response[:results])
|
27
|
+
content = []
|
28
|
+
|
29
|
+
results.each do |result|
|
30
|
+
content << GuardianContent::Section.new(recursively_symbolize_keys!(result))
|
31
|
+
end
|
32
|
+
return content
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.find_by_id(id)
|
36
|
+
|
37
|
+
query = {}
|
38
|
+
query["show-fields"] = "all"
|
39
|
+
query[:format] = "json"
|
40
|
+
opts = {:query => query}
|
41
|
+
|
42
|
+
response = recursively_symbolize_keys!self.get("/#{id}", opts).nested_symbolize_keys![:response]
|
43
|
+
|
44
|
+
content = response[:section]
|
45
|
+
|
46
|
+
return GuardianContent::Section.new(recursively_symbolize_keys!(content))
|
47
|
+
end
|
48
|
+
|
49
|
+
def content(options = {})
|
50
|
+
GuardianContent::Content.search("", options.merge!(:conditions => {:section => self.id}))
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.all(options = {})
|
54
|
+
|
55
|
+
response = self.get("/sections", {:query => {:format => "json"}}).nested_symbolize_keys![:response]
|
56
|
+
|
57
|
+
results = recursively_symbolize_keys!(response[:results])
|
58
|
+
content = []
|
59
|
+
|
60
|
+
results.each do |result|
|
61
|
+
content << GuardianContent::Section.new(recursively_symbolize_keys!(result))
|
62
|
+
end
|
63
|
+
return content
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class GuardianContent::Tag < GuardianContent::Base
|
2
|
+
|
3
|
+
attr_reader :title, :id, :url, :type, :section_id, :section_name
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
@id = attributes[:id] || nil
|
7
|
+
@title = attributes[:webTitle] || nil
|
8
|
+
@url = attributes[:webUrl] || nil
|
9
|
+
@type = attributes[:type] || nil
|
10
|
+
@section_id = attributes[:sectionId] || nil
|
11
|
+
@section_name = attributes[:sectionName] || nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
"#<Tag id: \"" + self.id + "\" type: \"" + self.type + "\" title: \"" + self.title.to_s + "\" url: \"" + self.url.to_s + "\">"
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Performs a text search for a tag.
|
20
|
+
# === Parameters
|
21
|
+
# * <tt>:conditions</tt> -
|
22
|
+
def self.search(q, options = {})
|
23
|
+
|
24
|
+
query = {}
|
25
|
+
|
26
|
+
query[:q] = q
|
27
|
+
query[:format] = "json"
|
28
|
+
|
29
|
+
query["page-size"] = options[:limit] if options[:limit]
|
30
|
+
opts = {:query => query}
|
31
|
+
|
32
|
+
if options[:conditions]
|
33
|
+
conditions = options[:conditions]
|
34
|
+
query[:type] = conditions[:type] if conditions[:type]
|
35
|
+
query[:section] = conditions[:section] if conditions[:section]
|
36
|
+
end
|
37
|
+
|
38
|
+
response = self.get("/tags", opts).nested_symbolize_keys![:response]
|
39
|
+
|
40
|
+
results = recursively_symbolize_keys!(response[:results])
|
41
|
+
content = []
|
42
|
+
|
43
|
+
results.each do |result|
|
44
|
+
content << GuardianContent::Tag.new(recursively_symbolize_keys!(result))
|
45
|
+
end
|
46
|
+
return content
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Returns the section associated with a Tag.
|
51
|
+
def section
|
52
|
+
return GuardianContent::Section.new(:id => self.section_id, :webTitle => self.section_name, :webUrl => "http://www.guardian.co.uk/" + self.section_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Retrieve a tag based upon its ID. Ids generally take the form of <tt>section/tag-name</tt>.
|
57
|
+
# === Examples
|
58
|
+
# * <tt>GuardianContent::Tag.find_by_id("politics/gordon-brown")</tt>
|
59
|
+
# * <tt>GuardianContent::Tag.find_by_id("environment/nuclearpower")</tt>
|
60
|
+
def self.find_by_id(id)
|
61
|
+
|
62
|
+
query = {}
|
63
|
+
query["show-fields"] = "all"
|
64
|
+
query["show-tags"] = "all"
|
65
|
+
query[:format] = "json"
|
66
|
+
opts = {:query => query}
|
67
|
+
|
68
|
+
return self.get("/#{id}").nested_symbolize_keys![:response][:tag]
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'httparty'
|
5
|
+
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
require 'guardian-content'
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestGuardianContent < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# should "do a reload" do
|
6
|
+
# article = GuardianContent::Content.new(:id => "world/2010/may/12/thailand-red-shirt-protesters-siege")
|
7
|
+
# assert article.title.nil?
|
8
|
+
# article.reload
|
9
|
+
# assert_equal "", article.title
|
10
|
+
# end
|
11
|
+
|
12
|
+
should "get a keyword" do
|
13
|
+
keyword = GuardianContent::Keyword.find_by_id("world/thailand")
|
14
|
+
|
15
|
+
assert_equal "Thailand", keyword.title
|
16
|
+
assert_equal "world/thailand", keyword.id
|
17
|
+
assert_equal "http://www.guardian.co.uk/world/thailand", keyword.url
|
18
|
+
sleep 1
|
19
|
+
end
|
20
|
+
|
21
|
+
should "get a contributor" do
|
22
|
+
contributor = GuardianContent::Contributor.find_by_id("profile/charliebrooker")
|
23
|
+
|
24
|
+
assert_equal "profile/charliebrooker", contributor.id
|
25
|
+
sleep 1
|
26
|
+
end
|
27
|
+
|
28
|
+
should "get an article's associated section" do
|
29
|
+
article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege")
|
30
|
+
|
31
|
+
assert_equal "world", article.section_id
|
32
|
+
# assert_equal "A", article.section.title
|
33
|
+
|
34
|
+
sleep 1
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
should "get an article" do
|
40
|
+
|
41
|
+
article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege")
|
42
|
+
|
43
|
+
assert !article.nil?
|
44
|
+
assert_equal "world/2010/may/12/thailand-red-shirt-protesters-siege", article.id
|
45
|
+
assert_equal "Thai army puts off plan for siege of redshirt protesters", article.title
|
46
|
+
assert_equal "http://www.guardian.co.uk/world/2010/may/12/thailand-red-shirt-protesters-siege", article.url
|
47
|
+
assert_equal "2010-05-12T17:13:00+01:00", article.publication_date.to_s
|
48
|
+
sleep 1
|
49
|
+
end
|
50
|
+
|
51
|
+
should "get an article's extended meta-data" do
|
52
|
+
|
53
|
+
article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege", :select => :all)
|
54
|
+
|
55
|
+
assert_equal "Thai army puts off plan for siege of redshirt protesters", article.headline
|
56
|
+
assert_equal "Authorities say cutting supplies to Bangkok protesters would hit residents as government cancels plans for November election", article.fields[:standfirst]
|
57
|
+
sleep 1
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
should "get an article's tags" do
|
62
|
+
|
63
|
+
article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege", :select => :all)
|
64
|
+
|
65
|
+
assert_equal 5, article.tags.size
|
66
|
+
assert_equal "world/thailand", article.tags.first[:id]
|
67
|
+
|
68
|
+
sleep 1
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
# should "get an article's body" do
|
74
|
+
# article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege")
|
75
|
+
|
76
|
+
# assert_equal "Blah", article.body
|
77
|
+
#sleep 1
|
78
|
+
# end
|
79
|
+
|
80
|
+
# should "get an article's keywords" do
|
81
|
+
# article = GuardianContent::Content.find_by_id("world/2010/may/12/thailand-red-shirt-protesters-siege")
|
82
|
+
|
83
|
+
# assert article.keywords.size > 0
|
84
|
+
|
85
|
+
# end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSearchContent < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "do a search" do
|
6
|
+
results = GuardianContent::Content.search("Gordon Brown")
|
7
|
+
assert_equal 10, results.size
|
8
|
+
sleep 1
|
9
|
+
end
|
10
|
+
|
11
|
+
should "do a search in order of relevance" do
|
12
|
+
results = GuardianContent::Content.search("Gordon Brown", :order => :relevance)
|
13
|
+
|
14
|
+
assert !results.first.id.nil?
|
15
|
+
sleep 1
|
16
|
+
end
|
17
|
+
|
18
|
+
should "do a search in order of newest" do
|
19
|
+
results = GuardianContent::Content.search("Gordon Brown", :order => :newest, :limit => 2)
|
20
|
+
|
21
|
+
assert (results.first.publication_date > results.last.publication_date)
|
22
|
+
sleep 1
|
23
|
+
end
|
24
|
+
|
25
|
+
should "do a search requesting 20 results" do
|
26
|
+
|
27
|
+
results = GuardianContent::Content.search("Gordon Brown", :limit => 20)
|
28
|
+
|
29
|
+
assert_equal 20, results.size
|
30
|
+
sleep 1
|
31
|
+
end
|
32
|
+
|
33
|
+
should "do a search and select tags" do
|
34
|
+
|
35
|
+
results = GuardianContent::Content.search("Gordon Brown", :limit => 1, :select => {:tags => :all})
|
36
|
+
|
37
|
+
assert (results.first.tags.size > 1)
|
38
|
+
|
39
|
+
sleep 1
|
40
|
+
end
|
41
|
+
|
42
|
+
should "do a search and not select tags" do
|
43
|
+
|
44
|
+
results = GuardianContent::Content.search("Gordon Brown", :limit => 1)
|
45
|
+
|
46
|
+
assert !results.first.tags
|
47
|
+
|
48
|
+
sleep 1
|
49
|
+
end
|
50
|
+
|
51
|
+
should "do a search with a to date" do
|
52
|
+
|
53
|
+
results = GuardianContent::Content.search("Volcano", :limit => 1, :conditions => {:to => "2010-04-28"})
|
54
|
+
|
55
|
+
assert_equal "2010-04-28T18:59:14+01:00", results.first.publication_date.to_s
|
56
|
+
sleep 1
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
should "do a search with a from date" do
|
61
|
+
|
62
|
+
results = GuardianContent::Content.search("Election", :limit => 1, :conditions => {:from => "2010-02-01"}, :order => :oldest)
|
63
|
+
|
64
|
+
assert_equal "2010-02-01T00:05:38+00:00", results.first.publication_date.to_s
|
65
|
+
sleep 1
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSection < Test::Unit::TestCase
|
4
|
+
|
5
|
+
|
6
|
+
should "get a section" do
|
7
|
+
section = GuardianContent::Section.find_by_id("books")
|
8
|
+
|
9
|
+
assert !section.nil?
|
10
|
+
assert_equal "books", section.id
|
11
|
+
assert_equal "Books", section.title
|
12
|
+
assert_equal "http://www.guardian.co.uk/books", section.url
|
13
|
+
sleep 1
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
should "get a section's content" do
|
18
|
+
section = GuardianContent::Section.find_by_id("politics")
|
19
|
+
|
20
|
+
content = section.content
|
21
|
+
assert_equal 10, content.size
|
22
|
+
assert_equal "politics", content.first.section_id
|
23
|
+
end
|
24
|
+
|
25
|
+
should "do a section search" do
|
26
|
+
section = GuardianContent::Section.search("design")
|
27
|
+
|
28
|
+
assert_equal "artanddesign", section.first.id
|
29
|
+
assert_equal "Art and design", section.first.title
|
30
|
+
end
|
31
|
+
|
32
|
+
should "get all sections" do
|
33
|
+
sections = GuardianContent::Section.all
|
34
|
+
|
35
|
+
assert_equal 38, sections.size
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTagSearch < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "do a search" do
|
6
|
+
results = GuardianContent::Tag.search("cycling")
|
7
|
+
assert_equal 5, results.size
|
8
|
+
assert_equal "lifeandstyle/series/cycling", results.first.id
|
9
|
+
sleep 1
|
10
|
+
end
|
11
|
+
|
12
|
+
should "do a search limited to 2" do
|
13
|
+
results = GuardianContent::Tag.search("cycling", :limit => 2)
|
14
|
+
assert_equal 2, results.size
|
15
|
+
sleep 1
|
16
|
+
end
|
17
|
+
|
18
|
+
should "do a search for a contributor" do
|
19
|
+
results = GuardianContent::Tag.search("Brown", :conditions => {:type => :contributor})
|
20
|
+
assert_equal "contributor", results.first.type
|
21
|
+
sleep 1
|
22
|
+
end
|
23
|
+
|
24
|
+
should "do a search for a keyword" do
|
25
|
+
results = GuardianContent::Tag.search("Brown", :conditions => {:type => :keyword})
|
26
|
+
assert_equal "keyword", results.first.type
|
27
|
+
sleep 1
|
28
|
+
end
|
29
|
+
|
30
|
+
should "do a search limited to a section" do
|
31
|
+
results = GuardianContent::Tag.search("brown", :limit => 1, :conditions => {:type => :keyword, :section => :politics})
|
32
|
+
assert_equal "politics", results.first.section_id
|
33
|
+
sleep 1
|
34
|
+
end
|
35
|
+
|
36
|
+
should "get associated sections on a tag serch" do
|
37
|
+
results = GuardianContent::Tag.search("brown", :limit => 1, :conditions => {:type => :keyword, :section => :politics})
|
38
|
+
assert_equal "Politics", results.first.section.title
|
39
|
+
assert_equal "http://www.guardian.co.uk/politics", results.first.section.url
|
40
|
+
sleep 1
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: guardian-content
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- frankieroberto
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-19 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: shoulda
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 10
|
30
|
+
- 3
|
31
|
+
version: 2.10.3
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: httparty
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 5
|
44
|
+
- 2
|
45
|
+
version: 0.5.2
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
description: A library for the Guardian Content API
|
49
|
+
email: frankie@frankieroberto.com
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files:
|
55
|
+
- LICENSE
|
56
|
+
- README.rdoc
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- LICENSE
|
60
|
+
- README.rdoc
|
61
|
+
- Rakefile
|
62
|
+
- VERSION
|
63
|
+
- guardian-content.gemspec
|
64
|
+
- lib/guardian-content.rb
|
65
|
+
- lib/guardian-content/content.rb
|
66
|
+
- lib/guardian-content/contributor.rb
|
67
|
+
- lib/guardian-content/extensions.rb
|
68
|
+
- lib/guardian-content/keyword.rb
|
69
|
+
- lib/guardian-content/section.rb
|
70
|
+
- lib/guardian-content/tag.rb
|
71
|
+
- test/helper.rb
|
72
|
+
- test/test_guardian-content.rb
|
73
|
+
- test/test_search_content.rb
|
74
|
+
- test/test_section.rb
|
75
|
+
- test/test_tag_search.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://github.com/frankieroberto/guardian-content
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --charset=UTF-8
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
requirements: []
|
100
|
+
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.3.6
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Queries the Guardian Content API
|
106
|
+
test_files:
|
107
|
+
- test/helper.rb
|
108
|
+
- test/test_guardian-content.rb
|
109
|
+
- test/test_search_content.rb
|
110
|
+
- test/test_section.rb
|
111
|
+
- test/test_tag_search.rb
|