npr 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/.travis.yml +13 -0
  2. data/{LICENSE → MIT-LICENSE} +1 -1
  3. data/README.md +115 -3
  4. data/Rakefile +6 -0
  5. data/gemfiles/Gemfile.rb-1.8.7 +6 -0
  6. data/lib/npr/api/client.rb +87 -0
  7. data/lib/npr/api/message.rb +38 -0
  8. data/lib/npr/api/query_builder.rb +222 -0
  9. data/lib/npr/api/response.rb +32 -0
  10. data/lib/npr/api.rb +7 -0
  11. data/lib/npr/concern/attr_typecast.rb +59 -0
  12. data/lib/npr/concern/relation.rb +103 -0
  13. data/lib/npr/concern/shallow_attributes.rb +71 -0
  14. data/lib/npr/concern.rb +9 -0
  15. data/lib/npr/configuration.rb +120 -0
  16. data/lib/npr/core_ext/array/wrap.rb +15 -0
  17. data/lib/npr/entity/audio.rb +28 -0
  18. data/lib/npr/entity/author.rb +22 -0
  19. data/lib/npr/entity/base.rb +19 -0
  20. data/lib/npr/entity/book.rb +21 -0
  21. data/lib/npr/entity/book_edition.rb +26 -0
  22. data/lib/npr/entity/byline.rb +18 -0
  23. data/lib/npr/entity/collection.rb +11 -0
  24. data/lib/npr/entity/crop.rb +20 -0
  25. data/lib/npr/entity/enlargement.rb +20 -0
  26. data/lib/npr/entity/formats.rb +19 -0
  27. data/lib/npr/entity/image.rb +33 -0
  28. data/lib/npr/entity/intro_text.rb +21 -0
  29. data/lib/npr/entity/link.rb +23 -0
  30. data/lib/npr/entity/list.rb +28 -0
  31. data/lib/npr/entity/list_text.rb +19 -0
  32. data/lib/npr/entity/member.rb +23 -0
  33. data/lib/npr/entity/member_byline.rb +17 -0
  34. data/lib/npr/entity/member_promo_art.rb +17 -0
  35. data/lib/npr/entity/mp3.rb +23 -0
  36. data/lib/npr/entity/organization.rb +18 -0
  37. data/lib/npr/entity/paragraph.rb +27 -0
  38. data/lib/npr/entity/permissions.rb +18 -0
  39. data/lib/npr/entity/program.rb +24 -0
  40. data/lib/npr/entity/promo_art.rb +17 -0
  41. data/lib/npr/entity/promo_art_book_edition.rb +18 -0
  42. data/lib/npr/entity/provider.rb +23 -0
  43. data/lib/npr/entity/pull_quote.rb +16 -0
  44. data/lib/npr/entity/related_link.rb +21 -0
  45. data/lib/npr/entity/show.rb +19 -0
  46. data/lib/npr/entity/story.rb +179 -0
  47. data/lib/npr/entity/text.rb +22 -0
  48. data/lib/npr/entity/title.rb +21 -0
  49. data/lib/npr/entity/transcript.rb +16 -0
  50. data/lib/npr/entity.rb +7 -0
  51. data/lib/npr/errors.rb +17 -0
  52. data/lib/npr/version.rb +1 -1
  53. data/lib/npr.rb +64 -3
  54. data/npr.gemspec +12 -2
  55. data/spec/fixtures/README.md +30 -0
  56. data/spec/fixtures/atom/01_story_full_media.atom +36 -0
  57. data/spec/fixtures/atom/02_story_multiple_images.atom +32 -0
  58. data/spec/fixtures/atom/03_no_results.atom +10 -0
  59. data/spec/fixtures/atom/04_invalid_id.atom +344 -0
  60. data/spec/fixtures/atom/05_no_api_key.atom +9 -0
  61. data/spec/fixtures/atom/06_story_multiple_ids.atom +59 -0
  62. data/spec/fixtures/fetch_formats.rb +65 -0
  63. data/spec/fixtures/html/01_story_full_media.html +54 -0
  64. data/spec/fixtures/html/02_story_multiple_images.html +55 -0
  65. data/spec/fixtures/html/03_no_results.html +38 -0
  66. data/spec/fixtures/html/04_invalid_id.html +82 -0
  67. data/spec/fixtures/html/05_no_api_key.html +8 -0
  68. data/spec/fixtures/html/06_story_multiple_ids.html +69 -0
  69. data/spec/fixtures/js/01_story_full_media.js +1 -0
  70. data/spec/fixtures/js/02_story_multiple_images.js +1 -0
  71. data/spec/fixtures/js/03_no_results.js +1 -0
  72. data/spec/fixtures/js/04_invalid_id.js +1 -0
  73. data/spec/fixtures/js/05_no_api_key.js +8 -0
  74. data/spec/fixtures/js/06_story_multiple_ids.js +1 -0
  75. data/spec/fixtures/json/01_story_full_media.json +1 -0
  76. data/spec/fixtures/json/02_story_multiple_images.json +1 -0
  77. data/spec/fixtures/json/03_no_results.json +1 -0
  78. data/spec/fixtures/json/04_invalid_id.json +1 -0
  79. data/spec/fixtures/json/05_no_api_key.json +1 -0
  80. data/spec/fixtures/json/06_story_multiple_ids.json +1 -0
  81. data/spec/fixtures/json/list.json +1 -0
  82. data/spec/fixtures/mediarss/01_story_full_media.rss +31 -0
  83. data/spec/fixtures/mediarss/02_story_multiple_images.rss +40 -0
  84. data/spec/fixtures/mediarss/03_no_results.rss +17 -0
  85. data/spec/fixtures/mediarss/04_invalid_id.rss +279 -0
  86. data/spec/fixtures/mediarss/05_no_api_key.rss +31 -0
  87. data/spec/fixtures/mediarss/06_story_multiple_ids.rss +65 -0
  88. data/spec/fixtures/nprml/01_story_full_media.xml +271 -0
  89. data/spec/fixtures/nprml/02_story_multiple_images.xml +165 -0
  90. data/spec/fixtures/nprml/03_no_results.xml +14 -0
  91. data/spec/fixtures/nprml/04_invalid_id.xml +1780 -0
  92. data/spec/fixtures/nprml/05_no_api_key.xml +9 -0
  93. data/spec/fixtures/nprml/06_story_multiple_ids.xml +435 -0
  94. data/spec/fixtures/nprml/list.xml +440 -0
  95. data/spec/fixtures/podcast/01_story_full_media.rss +30 -0
  96. data/spec/fixtures/podcast/02_story_multiple_images.rss +32 -0
  97. data/spec/fixtures/podcast/03_no_results.rss +19 -0
  98. data/spec/fixtures/podcast/04_invalid_id.rss +186 -0
  99. data/spec/fixtures/podcast/05_no_api_key.rss +31 -0
  100. data/spec/fixtures/podcast/06_story_multiple_ids.rss +43 -0
  101. data/spec/fixtures/rss/01_story_full_media.rss +25 -0
  102. data/spec/fixtures/rss/02_story_multiple_images.rss +25 -0
  103. data/spec/fixtures/rss/03_no_results.rss +17 -0
  104. data/spec/fixtures/rss/04_invalid_id.rss +137 -0
  105. data/spec/fixtures/rss/05_no_api_key.rss +31 -0
  106. data/spec/fixtures/rss/06_story_multiple_ids.rss +33 -0
  107. data/spec/spec_helper.rb +23 -0
  108. data/spec/support/config_helper.rb +64 -0
  109. data/spec/support/fake_response.rb +54 -0
  110. data/spec/support/fixture_helper.rb +23 -0
  111. data/spec/unit/api/client_spec.rb +42 -0
  112. data/spec/unit/api/message_spec.rb +68 -0
  113. data/spec/unit/api/query_builder_spec.rb +195 -0
  114. data/spec/unit/api/response_spec.rb +45 -0
  115. data/spec/unit/configuration_spec.rb +63 -0
  116. data/spec/unit/entity/audio_spec.rb +75 -0
  117. data/spec/unit/entity/author_spec.rb +30 -0
  118. data/spec/unit/entity/base_spec.rb +87 -0
  119. data/spec/unit/entity/book_edition_spec.rb +57 -0
  120. data/spec/unit/entity/book_spec.rb +31 -0
  121. data/spec/unit/entity/byline_spec.rb +23 -0
  122. data/spec/unit/entity/collection_spec.rb +39 -0
  123. data/spec/unit/entity/crop_spec.rb +25 -0
  124. data/spec/unit/entity/englargement_spec.rb +21 -0
  125. data/spec/unit/entity/formats_spec.rb +41 -0
  126. data/spec/unit/entity/image_spec.rb +82 -0
  127. data/spec/unit/entity/intro_text_spec.rb +25 -0
  128. data/spec/unit/entity/link_spec.rb +25 -0
  129. data/spec/unit/entity/list_spec.rb +22 -0
  130. data/spec/unit/entity/list_text_spec.rb +31 -0
  131. data/spec/unit/entity/member_byline_spec.rb +21 -0
  132. data/spec/unit/entity/member_promo_art_spec.rb +21 -0
  133. data/spec/unit/entity/member_spec.rb +59 -0
  134. data/spec/unit/entity/mp3_spec.rb +25 -0
  135. data/spec/unit/entity/organization_spec.rb +29 -0
  136. data/spec/unit/entity/paragraph_spec.rb +25 -0
  137. data/spec/unit/entity/permissions_spec.rb +56 -0
  138. data/spec/unit/entity/program_spec.rb +27 -0
  139. data/spec/unit/entity/promo_art_book_edition_spec.rb +21 -0
  140. data/spec/unit/entity/promo_art_spec.rb +42 -0
  141. data/spec/unit/entity/pull_quote_spec.rb +29 -0
  142. data/spec/unit/entity/related_link_spec.rb +55 -0
  143. data/spec/unit/entity/show_spec.rb +41 -0
  144. data/spec/unit/entity/story_spec.rb +154 -0
  145. data/spec/unit/entity/text_spec.rb +54 -0
  146. data/spec/unit/entity/title_spec.rb +25 -0
  147. data/spec/unit/entity/transcript_spec.rb +22 -0
  148. metadata +340 -8
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - ruby-head
6
+
7
+ matrix:
8
+ include:
9
+ - rvm: 1.8.7
10
+ gemfile: gemfiles/Gemfile.rb-1.8.7
11
+
12
+ notifications:
13
+ email: false
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,40 @@
1
- # NPR Ruby Client
1
+ # NPR API Ruby Client
2
+
3
+ [![Build Status](https://travis-ci.org/bricker88/npr.png)](https://travis-ci.org/bricker88/npr)
4
+
5
+ **NOTE** This gem is a WIP
6
+
7
+ A simple Ruby client for the
8
+ [NPR API](http://www.npr.org/api/index).
9
+
10
+
11
+ ## Support
12
+
13
+ This gem is tested with these versions (but may
14
+ work with others):
15
+
16
+ * Ruby 1.8.7, 1.9.2, 1.9.3, ruby-head
17
+ * NPR API version 0.94
18
+
19
+
20
+ ## Dependencies
21
+
22
+ * `faraday >= 0.8.0` (HTTP requests)
23
+ * `faraday_middleware >= 0.9.0` (response processing)
24
+
25
+ **NOTE** If you are running **Ruby < 1.9**, you will have to install
26
+ the [json gem](http://rubygems.org/gems/json):
27
+
28
+ In your Gemfile:
29
+
30
+ gem 'json', '~> 1.7.5'
31
+
32
+ From the command line:
33
+
34
+ $ gem install json
35
+
36
+ Ruby 1.9+ comes with JSON support built-in!
2
37
 
3
- A simple Ruby client for the NPR API
4
38
 
5
39
  ## Installation
6
40
 
@@ -16,9 +50,87 @@ Or install it yourself as:
16
50
 
17
51
  $ gem install npr
18
52
 
53
+
19
54
  ## Usage
20
55
 
21
- TODO: Write usage instructions here
56
+ ### API Key
57
+
58
+ NPR requires that you have an API key in order to use
59
+ their API. More information about this (including how
60
+ to register) can be found at
61
+ [NPR's API Documentation](http://www.npr.org/api/index).
62
+
63
+ ### Configuration
64
+
65
+ API requests can be configured globally. This is recommended
66
+ for setting the API Key, but you can also set other parameters
67
+ which will be passed in with every request (unless overridden):
68
+
69
+ ```ruby
70
+ NPR.configure do |config|
71
+ config.apiKey = "YOUR_API_KEY"
72
+ config.sort = "date descending"
73
+ config.requiredAssets = "text"
74
+ end
75
+ ```
76
+
77
+ For a Rails application, a good place to put the configuration
78
+ would be in an initializer, such as `config/initializers/npr_config.rb`.
79
+
80
+ ### DSL
81
+
82
+ The DSL is modeled after Rails' `ActiveRecord::Relation`, so for the
83
+ most part, if you understand that, then using the NPR gem will come
84
+ naturally to you!
85
+
86
+ To find a story by ID:
87
+
88
+ ```ruby
89
+ NPR::Story.find(1999) #=> NPR::Story
90
+ ```
91
+
92
+ `NPR::Story#find` will either return a Story object if it was found,
93
+ or an array of Messages from the NPR API.
94
+
95
+ Building a query:
96
+
97
+ ```
98
+ NPR::Story.where(date: [2.days.ago..Time.now]).order("date ascending").limit(10).offset(50)
99
+ ```
100
+
101
+ That's a contrived example but it shows all the methods available.
102
+
103
+ You can also query directly on an `NPR::API::Client` object, if you're
104
+ feeling adventurous:
105
+
106
+ ```ruby
107
+ client = NPR::API::Client.new(apiKey: NPR.config.apiKey)
108
+ client.query(sort: "editor assigned", numResults: "12")
109
+ ```
110
+
111
+ The params that get passed into the `#query` method map directly to
112
+ the parameters that NPR's API accepts. See the
113
+ [NPR API Input Reference](http://www.npr.org/api/inputReference.php)
114
+ for all of the options.
115
+
116
+
117
+ ## TODO
118
+
119
+ * More Documentation
120
+ * Search functionality
121
+ * Add "select" method to QueryBuilder for the "fields" input
122
+ * Abstract attributes so they're not tied directly to the API response.
123
+ Also to make them more Ruby-conventional (i.e. snake_case)
124
+ * Example: "apiKey" => :api_key
125
+ * Support for "container" node
126
+ * Support for "parent" node
127
+ * Support for "thumbnail" node
128
+ * Support a way to return raw formats of:
129
+ * HTML / Javascript (for views)
130
+ * JSON
131
+ * ATOM
132
+ * RSS
133
+
22
134
 
23
135
  ## Contributing
24
136
 
data/Rakefile CHANGED
@@ -1,2 +1,8 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ task :default => "spec"
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in npr.gemspec
4
+ gemspec :path => "../"
5
+
6
+ gem 'json', '~> 1.7.5'
@@ -0,0 +1,87 @@
1
+ ##
2
+ # NPR::API::Client
3
+ #
4
+ # Basic client for interacting with the NPR API.
5
+ #
6
+ # Options passed in when initializing the client will
7
+ # go out with every API request. You may also pass in
8
+ # options to +#query+ for a per-request basis.
9
+ #
10
+ # You can also set params via +client.params+
11
+ #
12
+ # Params should be passed in exactly as they will be sent
13
+ # to the API. Example: "apiKey", not "api_key"
14
+ # See the API documentation for what those params are.
15
+ #
16
+ module NPR
17
+ module API
18
+ class Client
19
+ attr_accessor :params
20
+
21
+ #-----------------
22
+ # Argument is a hash of params to send to the API.
23
+ # See <http://www.npr.org/api/inputReference.php> for
24
+ # API documentation.
25
+ #
26
+ # Example:
27
+ #
28
+ # NPR::Client.new(apiKey: "YOUR_API_KEY", sort: "date descending")
29
+ #
30
+ # Any parameters passed into this method will override the
31
+ # global configuration.
32
+ #
33
+ def initialize(params={})
34
+ @params = NPR.config.merge(params)
35
+ @apiKey = @params.delete(:apiKey)
36
+ end
37
+
38
+ #-----------------
39
+ # Send a query to the NPR API.
40
+ #
41
+ # Accepts a hash of options which get passed
42
+ # directly to the API.
43
+ #
44
+ # Any parameters passed directly into this method
45
+ # will override both the global configuration,
46
+ # as well as any parameters stored in this object's
47
+ # @params.
48
+ #
49
+ # Example:
50
+ #
51
+ # client.query(sort: "date descending", requiredAssets: "image")
52
+ #
53
+ # For now, this forced JSON output.
54
+ # TODO: Support more formats
55
+ #
56
+ def query(params={})
57
+ if @apiKey.nil?
58
+ raise NPR::NotConfiguredError, "apiKey must be set to perform a query"
59
+ end
60
+
61
+ response = connection.get do |request|
62
+ request.url NPR::Configuration::API_QUERY_PATH
63
+ request.params = @params.merge(params)
64
+ request.params['output'] = "json"
65
+ request.params['apiKey'] = @apiKey
66
+ end
67
+
68
+ NPR::API::Response.new(response)
69
+ end
70
+
71
+ #-----------------
72
+
73
+ private
74
+
75
+ #-----------------
76
+
77
+ def connection
78
+ @connection ||= begin
79
+ Faraday.new NPR::Configuration::API_ROOT do |conn|
80
+ conn.response :json, :content_type => /\bjson$/
81
+ conn.adapter Faraday.default_adapter
82
+ end
83
+ end
84
+ end
85
+ end # Client
86
+ end # API
87
+ end # NPR
@@ -0,0 +1,38 @@
1
+ ##
2
+ # NPR::API::Message
3
+ #
4
+ # If the API returns any messages, use this class
5
+ # to represent it.
6
+ #
7
+ module NPR
8
+ module API
9
+ class Message
10
+ include NPR::Concern::ShallowAttributes
11
+
12
+ attr_accessor :id, :level
13
+ shallow_attribute "text", "timestamp"
14
+
15
+ #------------------
16
+
17
+ def initialize(json)
18
+ @_json = json
19
+ @id = @_json["id"]
20
+ @level = @_json["level"]
21
+
22
+ extract_shallow_attributes(@_json)
23
+ end
24
+
25
+ #------------------
26
+
27
+ def error?
28
+ self.level == "error"
29
+ end
30
+
31
+ #------------------
32
+
33
+ def warning?
34
+ self.level == "warning"
35
+ end
36
+ end # Message
37
+ end # API
38
+ end # NPR
@@ -0,0 +1,222 @@
1
+ ##
2
+ # NPR::API::QueryBuilder
3
+ #
4
+ module NPR
5
+ module API
6
+ class QueryBuilder
7
+ CLASS_BUILDER_METHODS = [
8
+ :where,
9
+ :order,
10
+ :limit,
11
+ :offset
12
+ ]
13
+
14
+ attr_reader :_klass, :builder
15
+
16
+ #-----------------------
17
+
18
+ def initialize(klass)
19
+ @_klass = klass
20
+ @builder = {}
21
+ end
22
+
23
+ #-----------------------
24
+ # Build the params hash.
25
+ # This is automatically called by #to_a, so it probably
26
+ # doesn't need to be used manually.
27
+ def to_params
28
+ if @_klass == NPR::Entity::Story && @builder[:conditions]
29
+ conditions = parse_conditions(@builder[:conditions])
30
+ else
31
+ conditions = @builder[:conditions]
32
+ end
33
+
34
+ params = conditions || {}
35
+ params[:sort] = @builder[:order] if @builder[:order]
36
+ params[:numResults] = @builder[:limit] if @builder[:limit]
37
+ params[:startNum] = @builder[:offset] if @builder[:offset]
38
+ params.merge!(@builder[:extra]) if @builder[:extra]
39
+
40
+ params
41
+ end
42
+
43
+ #-----------------------
44
+ # Fire the query and return an Array of stories (or empty [])
45
+ #
46
+ # Named +to_a+ to keep in line with ActiveRecord::Relation's
47
+ # naming convention. It is also aliased as +query+, which
48
+ # probably makes a little more sense.
49
+ #
50
+ # Returns an Array. If the query returned any stories, then
51
+ # it will be an array of those stories. If no stories were
52
+ # returned, then it will be an empty array.
53
+ #
54
+ # There is no way to access the List or Messages returned
55
+ # from the response. This method is meant to be a way to
56
+ # get to the Stories as quickly and easily as possible.
57
+ # If you want access to the full Response object, use #query.
58
+ #
59
+ # Example:
60
+ #
61
+ # query = NPR::API::QueryBuilder.new(NPR::Story)
62
+ # query.where(:id => [100, 150]).to_a
63
+ # #=> [NPR::Story, NPR::Story]
64
+ #
65
+ # # Assuming there is no story with an ID of 1
66
+ # query.where(:id => 1).to_a
67
+ # #=> []
68
+ #
69
+ # Note that for this method, +NPR.config.apiKey+ must be set.
70
+ #
71
+ def to_a
72
+ response = self.query
73
+ stories = []
74
+
75
+ if list = response.list
76
+ stories = Array.wrap(response.list.stories)
77
+ end
78
+
79
+ stories
80
+ end
81
+
82
+ #-----------------------
83
+ # Fire the query and return the full Response object
84
+ #
85
+ # Example:
86
+ #
87
+ # query = NPR::API::QueryBuilder.new(NPR::Story)
88
+ # query.where(:id => [100, 150]).query
89
+ # #=> NPR::API::Response
90
+ #
91
+ # See NPR::API::Response for what methods are available
92
+ # to you.
93
+ #
94
+ # Note that for this method, +NPR.config.apiKey+ must be set.
95
+ def query
96
+ client.query(self.to_params)
97
+ end
98
+
99
+ #-----------------------
100
+ # Add in arbitrary parameters.
101
+ #
102
+ # These take precedence over anything set via
103
+ # any of the other builder methods.
104
+ #
105
+ # Accepts a hash of key/values that the API
106
+ # can receive and handle.
107
+ #
108
+ # Example:
109
+ #
110
+ # query.set(apiKey: "YOUR_API_KEY")
111
+ #
112
+ def set(params)
113
+ @builder[:extra] = (@builder[:extra] || {}).merge(params)
114
+ self
115
+ end
116
+
117
+ #-----------------------
118
+ # Merge in the passed-in conditions to what
119
+ # already exists.
120
+ #
121
+ # Accepts a Hash.
122
+ #
123
+ # Example:
124
+ #
125
+ # query.where(id: 999, requiredAssets: "text")
126
+ #
127
+ # Extra convenience:
128
+ #
129
+ # * You may pass an array to :id
130
+ #
131
+ # query.where(id: [70, 180])
132
+ #
133
+ # * You may pass a date range to :date
134
+ #
135
+ # last_week = Time.new(2012, 10, 21)
136
+ # yesterday = Time.new(2012, 10, 25)
137
+ # query.where(date: (last_week..yesterday))
138
+ #
139
+ def where(conditions)
140
+ @builder[:conditions] = (@builder[:conditions] || {}).merge(conditions)
141
+ self
142
+ end
143
+
144
+ #-----------------------
145
+ # Set the order.
146
+ #
147
+ # Accepts a String.
148
+ #
149
+ # Example:
150
+ #
151
+ # query.order("date descending")
152
+ #
153
+ def order(order)
154
+ @builder[:order] = order
155
+ self
156
+ end
157
+
158
+ #-----------------------
159
+ # Set the limit.
160
+ #
161
+ # Accepts an Integer.
162
+ #
163
+ # Example:
164
+ #
165
+ # query.limit(10)
166
+ #
167
+ # Note that NPR limits the maximum results to 20,
168
+ # and will return only 20 results if more than the
169
+ # maximum is requested.
170
+ def limit(limit)
171
+ @builder[:limit] = limit
172
+ self
173
+ end
174
+
175
+ #-----------------------
176
+ # Offset the number of results
177
+ # Useful for pagination
178
+ #
179
+ # Accepts an Integer.
180
+ #
181
+ # Example:
182
+ #
183
+ # query.offset(100)
184
+ #
185
+ def offset(offset)
186
+ @builder[:offset] = offset
187
+ self
188
+ end
189
+
190
+ #-----------------------
191
+
192
+ private
193
+
194
+ def client
195
+ @client ||= NPR::API::Client.new(:apiKey => NPR.config.apiKey)
196
+ end
197
+
198
+ #-----------------------
199
+
200
+ def parse_conditions(conditions)
201
+ parse_conditions!(conditions.dup)
202
+ end
203
+
204
+ #-----------------------
205
+
206
+ def parse_conditions!(conditions)
207
+
208
+ if conditions[:id].is_a? Array
209
+ conditions[:id] = conditions[:id].join(",")
210
+ end
211
+
212
+ if conditions[:date].is_a? Range
213
+ conditions[:startDate] = conditions[:date].first
214
+ conditions[:endDate] = conditions[:date].last
215
+ conditions.delete(:date)
216
+ end
217
+
218
+ conditions
219
+ end
220
+ end # QueryBuilder
221
+ end # API
222
+ end # NPR
@@ -0,0 +1,32 @@
1
+ ##
2
+ # NPR::API::Response
3
+ #
4
+ # Wrapper around a Faraday response object
5
+ # Pass in the full response object from Faraday
6
+ #
7
+ module NPR
8
+ module API
9
+ class Response
10
+ include NPR::Concern::Relation
11
+
12
+ has_many "messages", :key => "message", :class_name => NPR::API::Message
13
+ attr_reader :raw, :version, :messages, :list
14
+
15
+ #--------------------------
16
+
17
+ def initialize(response)
18
+ create_relations(response)
19
+ @raw = response
20
+ @version = response.body["version"]
21
+
22
+ if response.body["list"]
23
+ @list = NPR::Entity::List.new(response.body["list"])
24
+ end
25
+
26
+ Array.wrap(response.body["message"]).each do |message|
27
+ @messages.push NPR::API::Message.new(message)
28
+ end
29
+ end
30
+ end # Response
31
+ end # API
32
+ end # NPR
data/lib/npr/api.rb ADDED
@@ -0,0 +1,7 @@
1
+ ##
2
+ # :D
3
+ #
4
+ module NPR
5
+ module API
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ require 'time'
2
+
3
+ ##
4
+ # NPR::Concern::AttrTypecast
5
+ #
6
+ module NPR
7
+ #------------------
8
+ # Attributes that are being typecast to Ruby classes
9
+ ATTR_TYPES = {
10
+ "id" => :string_to_i,
11
+ "partnerId" => :string_to_i,
12
+ "storyDate" => :string_time_parse,
13
+ "pubDate" => :string_time_parse,
14
+ "lastModifiedDate" => :string_time_parse,
15
+ "showDate" => :string_time_parse,
16
+ "date" => :string_time_parse,
17
+ "segNum" => :string_to_i,
18
+ "num" => :string_to_i,
19
+ "timestamp" => :string_time_at,
20
+ "duration" => :string_to_i
21
+ }
22
+
23
+ module Concern
24
+ module AttrTypecast
25
+
26
+ private
27
+
28
+ #------------------
29
+ # Typecasting methods
30
+ def string_to_i(value)
31
+ value.to_i
32
+ end
33
+
34
+ #------------------
35
+
36
+ def string_time_parse(value)
37
+ !value.empty? ? Time.parse(value) : nil
38
+ end
39
+
40
+ #------------------
41
+
42
+ def string_time_at(value)
43
+ Time.at(value.to_f)
44
+ end
45
+
46
+
47
+ #------------------
48
+ #------------------
49
+
50
+ def attr_typecast(key, value)
51
+ if method = NPR::ATTR_TYPES[key]
52
+ send method, value
53
+ else
54
+ value
55
+ end
56
+ end
57
+ end # AttrTypecast
58
+ end # Concern
59
+ end # NPR