harrisj-nytimes-articles 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 2
3
- :patch: 1
2
+ :minor: 3
3
+ :patch: 0
4
4
  :major: 0
@@ -12,6 +12,7 @@ module Nytimes
12
12
 
13
13
  @@api_key = nil
14
14
  @@debug = false
15
+ @@decode_html_entities = true
15
16
 
16
17
  ##
17
18
  # Set the API key used for operations. This needs to be called before any requests against the API. To obtain an API key, go to http://developer.nytimes.com/
@@ -22,6 +23,12 @@ module Nytimes
22
23
  def self.debug=(flag)
23
24
  @@debug = flag
24
25
  end
26
+
27
+ ##
28
+ # Set whether or not to decode HTML entities when returning text fields.
29
+ def self.decode_html_entities=(flag)
30
+ @@decode_html_entities = flag
31
+ end
25
32
 
26
33
  ##
27
34
  # Returns the current value of the API Key
@@ -34,13 +41,12 @@ module Nytimes
34
41
  def self.build_request_url(params)
35
42
  URI::HTTP.build :host => API_SERVER,
36
43
  :path => API_BASE,
37
- :query => params.map {|k,v| "#{URI.escape(k)}=#{URI.escape(v)}"}.join('&')
44
+ :query => params.map {|k,v| "#{URI.escape(k)}=#{URI.escape(v.to_s)}"}.join('&')
38
45
  end
39
46
 
40
47
  def self.text_field(value)
41
48
  return nil if value.nil?
42
- coder = HTMLEntities.new
43
- coder.decode(value)
49
+ @@decode_html_entities ? HTMLEntities.new.decode(value) : value
44
50
  end
45
51
 
46
52
  def self.integer_field(value)
@@ -0,0 +1,28 @@
1
+ require 'digest'
2
+
3
+ module Nytimes
4
+ module Articles
5
+ ##
6
+ # The Query class represents a single query to the Article Search API. Supports
7
+ # all of the named parameters to Article.search as accessor methods.
8
+ #
9
+ class Query
10
+ FIELDS = [:only_facets, :except_facets, :begin_date, :end_date, :since,
11
+ :before, :fee, :has_thumbnail, :facets, :fields, :query, :offset] + Article::TEXT_FIELDS.map(&:to_sym)
12
+ FIELDS.each {|f| attr_accessor f}
13
+
14
+ # Produce a hash which uniquely identifies this query
15
+ def hash
16
+ strs = FIELDS.collect {|f| "#{f}:#{send(f).inspect}"}
17
+ Digest::SHA256.hexdigest(strs.join(' '))
18
+ end
19
+
20
+ # Perform this query. Returns result of Article.search
21
+ def perform
22
+ params = {}
23
+ FIELDS.each {|f| params[f] = send(f) unless send(f).nil?}
24
+ Article.search(params)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,9 +1,6 @@
1
1
  # should I be setting this?
2
2
  $KCODE = 'UTF8'
3
3
 
4
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'exceptions')
5
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'base')
6
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'facet')
7
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'thumbnail')
8
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'article')
9
- require File.join(File.dirname(__FILE__), 'nytimes_articles', 'result_set')
4
+ %w(exceptions base facet thumbnail article result_set query).each do |f|
5
+ require File.join(File.dirname(__FILE__), 'nytimes_articles', f)
6
+ end
@@ -88,5 +88,33 @@ class TestNytimes::TestArticles::TestBase < Test::Unit::TestCase
88
88
  end
89
89
  end
90
90
  end
91
+
92
+ context "when passing Integer for offset" do
93
+ # note Article.search requries integer for offset
94
+ setup do
95
+ FakeWeb.register_uri(api_url_for('offset' => '1'), :status => ['200', 'OK'], :string => '{}')
96
+ end
97
+
98
+ should "not raise NoMethodError" do
99
+ assert_nothing_raised(NoMethodError) { Base.invoke('offset' => 1) }
100
+ end
101
+ end
91
102
  end
103
+
104
+ context "Base#text_field" do
105
+ context "when decode_html_entities == true" do
106
+ should "decode HTML entities in text fields" do
107
+ assert_equal "foó", Base.text_field("fo&oacute;")
108
+ end
109
+ end
110
+
111
+ context "when decode_html_entities == false" do
112
+ setup { Base.decode_html_entities = false }
113
+ teardown { Base.decode_html_entities = true }
114
+
115
+ should "not decode HTML entities in text fields" do
116
+ assert_equal "fo&oacute;", Base.text_field("fo&oacute;")
117
+ end
118
+ end
119
+ end
92
120
  end
@@ -0,0 +1,89 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class TestNytimes::TestArticles::TestQuery < Test::Unit::TestCase
4
+ include Nytimes::Articles
5
+
6
+ def setup
7
+ Base.stubs(:invoke)
8
+ @query = Query.new
9
+ end
10
+
11
+ def assert_has_accessor(obj, name, value='foo')
12
+ assert_nothing_raised { obj.send("#{name}=", value) }
13
+ assert_equal value, obj.send(name)
14
+ end
15
+
16
+ def expect_search_with(hsh)
17
+ Article.expects(:search).with(has_entry(hsh))
18
+ end
19
+
20
+ def self.should_proxy_search_param(name, value)
21
+ should "provide accessor for :#{name}" do
22
+ assert_has_accessor(@query, name, value)
23
+ end
24
+
25
+ should "pass :#{name} to Article#search" do
26
+ @query.send("#{name}=", value)
27
+ expect_search_with name => value
28
+ @query.perform
29
+ end
30
+ end
31
+
32
+ context "proxying named parameters to Article.search" do
33
+ (Article::TEXT_FIELDS + [:query]).each do |name|
34
+ should_proxy_search_param name.to_sym, 'some text field'
35
+ end
36
+
37
+ [:only_facets, :except_facets].each do |name|
38
+ should_proxy_search_param name, {'geo_facet' => 'NEW YORK CITY'}
39
+ end
40
+
41
+ [:begin_date, :end_date, :since, :before].each do |name|
42
+ should_proxy_search_param name, Time.now
43
+ end
44
+
45
+ [:fee, :has_thumbnail].each do |name|
46
+ should_proxy_search_param name, true
47
+ end
48
+
49
+ should_proxy_search_param :facets, ['geo_facet', 'org_facet', 'per_facet']
50
+ should_proxy_search_param :fields, ['title', 'abstract']
51
+ should_proxy_search_param :offset, 99
52
+
53
+ should "not pass nil parameters" do
54
+ @query.query = 'foo'
55
+ Article.expects(:search).with(:query => 'foo')
56
+ @query.perform
57
+ end
58
+ end
59
+
60
+ context "generating hash" do
61
+ # not sure how one would test this exhaustively, going for coverage + non-regression...
62
+
63
+ should "produce the same hash for identical queries" do
64
+ q0 = Query.new
65
+ q0.query = 'foo bar baz'
66
+ q0.only_facets = {'geo_facet' => 'NEW YORK CITY'}
67
+
68
+ q1 = Query.new
69
+ q1.query = 'foo bar baz'
70
+ q1.only_facets = {'geo_facet' => 'NEW YORK CITY'}
71
+
72
+ assert_equal q0.hash, q1.hash
73
+ end
74
+
75
+ should "not produce the same hash for non-identical queries" do
76
+ q0 = Query.new; q0.query = 'foo'
77
+ q1 = Query.new; q1.query = 'bar'
78
+ assert_not_equal q0.hash, q1.hash
79
+
80
+ q0 = Query.new; q0.facets = {'geo_facet' => 'NEW YORK CITY'}
81
+ q1 = Query.new; q1.facets = {'geo_facet' => 'CALIFORNIA'}
82
+ assert_not_equal q0.hash, q1.hash
83
+
84
+ q0 = Query.new; q0.since = Date.parse('1/1/2009')
85
+ q1 = Query.new; q1.since = Date.parse('1/2/2009')
86
+ assert_not_equal q0.hash, q1.hash
87
+ end
88
+ end
89
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harrisj-nytimes-articles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Harris
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-01 00:00:00 -08:00
12
+ date: 2009-03-03 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -37,6 +37,7 @@ files:
37
37
  - lib/nytimes_articles/base.rb
38
38
  - lib/nytimes_articles/exceptions.rb
39
39
  - lib/nytimes_articles/facet.rb
40
+ - lib/nytimes_articles/query.rb
40
41
  - lib/nytimes_articles/result_set.rb
41
42
  - lib/nytimes_articles/thumbnail.rb
42
43
  - lib/nytimes_articles.rb
@@ -45,6 +46,7 @@ files:
45
46
  - test/nytimes/articles/test_article.rb
46
47
  - test/nytimes/articles/test_base.rb
47
48
  - test/nytimes/articles/test_facet.rb
49
+ - test/nytimes/articles/test_query.rb
48
50
  - test/nytimes/articles/test_result_set.rb
49
51
  - test/nytimes/articles/test_thumbnail.rb
50
52
  - test/test_helper.rb