primal 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dfe6776b27a2665fb3bf680618ca23dcbeb623d4
4
+ data.tar.gz: c3e4f6c2e0757efa8af11ce30df9fe7842c91cdd
5
+ SHA512:
6
+ metadata.gz: 6a1c0414e1d069298d3d30973483fac9b55d80644dcbe2917da33375012108da4e8472e8cdd211a0cfcd0dd41062f1ee291f0b6de33a381e69769f3f3b0cd9cd
7
+ data.tar.gz: 7e211be3602d8f589aa7bb7697482986c23cc97dbc78984d627b69bd060ae2baac1bc0072e56dc14343d7f1efc2e2b509b0f16d2910b8fe67fe393ebac405109
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.project ADDED
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>primal</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ </buildSpec>
9
+ <natures>
10
+ <nature>com.aptana.projects.webnature</nature>
11
+ <nature>com.aptana.ruby.core.rubynature</nature>
12
+ </natures>
13
+ </projectDescription>
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in primal.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 w2davids@gmail.com
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
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.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Primal
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'primal'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install primal
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/primal.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "primal/version"
2
+
3
+ module Primal
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,340 @@
1
+ # We need to use some ruby gems
2
+ require 'rubygems'
3
+ require 'uri'
4
+ require 'httparty'
5
+ require 'json'
6
+
7
+ module Primal
8
+
9
+
10
+ #
11
+ # The InputTermExtraction class abstracts accessing AlchemyAPI
12
+ # (http://www.alchemyapi.com/) to extract important information from Web
13
+ # pages/News articles/blog posts/plain text.
14
+ #
15
+ # The main function is getPrimalRequest, which accepts a string that represents
16
+ # a Web page URL or some text, and build a Primal topic URI that will direct the
17
+ # user to the Primal Web App.
18
+ #
19
+ class InputTermExtraction
20
+ include HTTParty
21
+
22
+ # Uncomment this next line to see what HTTParty is doing
23
+ # debug_output $stderr
24
+
25
+ # Set this to true/false in order to turn on/off debugging of this class
26
+ @@debugMe = true
27
+
28
+ @@alchemyRoot = "http://access.alchemyapi.com/calls"
29
+ @@alchemyURL = "#{@@alchemyRoot}/url"
30
+ @@alchemyText = "#{@@alchemyRoot}/text"
31
+
32
+ # change these variables to modify how the Primal request is built
33
+ @@entitiesLimit = 1
34
+ @@keywordsLimit = 3
35
+
36
+ # We ignore keywords that intersect with entities of the following types:
37
+ @@categoryIgnores = {
38
+ 'person' => 1,
39
+ 'organization' => 1,
40
+ 'city' => 1,
41
+ 'company' => 1,
42
+ 'continent' => 1,
43
+ 'country' => 1,
44
+ 'region' => 1,
45
+ 'stateorcountry' => 1,
46
+ 'geographicfeature' => 1
47
+ }
48
+
49
+ #
50
+ # Constructor for the InputTermExtraction class
51
+ #
52
+ # Pass in the Api Key for Alchemy services.
53
+ # You can register for a free API key here:
54
+ # http://www.alchemyapi.com/api/register.html
55
+ # to test your application.
56
+ # Please read the license of Alchemy API.
57
+ #
58
+ def initialize(alchemyApiKey)
59
+ @alchemyApiKey = alchemyApiKey
60
+ end
61
+
62
+ #
63
+ # Receives a string that represents a Web page URL or some text, and returns
64
+ # a Primal topic URI.
65
+ #
66
+ # Returns nil on error
67
+ #
68
+ def getPrimalRequest(urlOrText)
69
+ if isURI(urlOrText)
70
+ getPrimalRequestURL(urlOrText)
71
+ else
72
+ getPrimalRequestTEXT(urlOrText)
73
+ end
74
+ end
75
+
76
+ #
77
+ # Indicates whether or not a given string represents a URL
78
+ #
79
+ def isURI(string)
80
+ uri = URI.parse(string)
81
+ %w( http https ).include?(uri.scheme)
82
+ rescue URI::BadURIError
83
+ false
84
+ rescue URI::InvalidURIError
85
+ false
86
+ end
87
+
88
+ #
89
+ # Processes the given URL at Alchemy and then translates the results to a
90
+ # valid Primal URL
91
+ #
92
+ def getPrimalRequestURL(urlToProcess)
93
+ if @@debugMe
94
+ $stderr.puts "Extracting information from URL..."
95
+ end
96
+
97
+ # get category of the Web page
98
+ categoryJSON = getAlchemy("#{@@alchemyURL}/URLGetCategory",
99
+ :query => {
100
+ :outputMode => 'json',
101
+ :apikey => @alchemyApiKey,
102
+ :url => urlToProcess
103
+ })
104
+
105
+ # get entities in the Web page
106
+ entitiesJSON = getAlchemy("#{@@alchemyURL}/URLGetRankedNamedEntities",
107
+ :query => {
108
+ :outputMode => 'json',
109
+ :apikey => @alchemyApiKey,
110
+ :url => urlToProcess
111
+ })
112
+
113
+ # get keywords from the Web page
114
+ keywordsJSON = getAlchemy("#{@@alchemyURL}/URLGetRankedKeywords",
115
+ :query => {
116
+ :outputMode => 'json',
117
+ :apikey => @alchemyApiKey,
118
+ :url => urlToProcess
119
+ })
120
+
121
+ buildPrimalRequest(categoryJSON, entitiesJSON, keywordsJSON)
122
+ end
123
+
124
+ #
125
+ # Processes the given Text at Alchemy and then translates the results to a
126
+ # valid Primal URL
127
+ #
128
+ def getPrimalRequestTEXT(textToProcess)
129
+ if @@debugMe
130
+ $stderr.puts "Extracting information from text..."
131
+ end
132
+
133
+ # get category
134
+ categoryJSON = postAlchemy("#{@@alchemyText}/TextGetCategory",
135
+ :query => {
136
+ :outputMode => 'json',
137
+ :apikey => @alchemyApiKey,
138
+ :text => textToProcess
139
+ })
140
+
141
+ # get entities
142
+ entitiesJSON = postAlchemy("#{@@alchemyText}/TextGetRankedNamedEntities",
143
+ :query => {
144
+ :outputMode => 'json',
145
+ :apikey => @alchemyApiKey,
146
+ :text => textToProcess
147
+ })
148
+
149
+ # get keywords
150
+ keywordsJSON = postAlchemy("#{@@alchemyText}/TextGetRankedKeywords",
151
+ :query => {
152
+ :outputMode => 'json',
153
+ :apikey => @alchemyApiKey,
154
+ :text => textToProcess
155
+ })
156
+
157
+ buildPrimalRequest(categoryJSON, entitiesJSON, keywordsJSON)
158
+ end
159
+
160
+ #
161
+ # Uses the deconstructed Alchemy information to create a valid Primal URL
162
+ #
163
+ def buildPrimalRequest(categoryJSON, entitiesJSON, keywordsJSON)
164
+ # Check if any of the extractions failed
165
+ if !categoryJSON or !entitiesJSON or !keywordsJSON
166
+ $stderr.puts "Cannot build Primal request. Alchemy failed to extract information."
167
+ return nil
168
+ end
169
+
170
+ if @@debugMe
171
+ $stderr.puts "Building Primal request..."
172
+ end
173
+
174
+ ### Get information required for building a Primal request
175
+ # Get the category from the extracted data
176
+ category = rewriteCategory(categoryJSON['category'])
177
+
178
+ if @@debugMe
179
+ $stderr.puts "Category = #{category}"
180
+ end
181
+
182
+ ### Select top entities from all extracted entities
183
+ entitiesList = entitiesJSON['entities'].collect { |entity|
184
+ entity['text'].downcase
185
+ }[0, @@entitiesLimit]
186
+
187
+ if @@debugMe
188
+ prettified = entitiesJSON['entities'].collect { |entity|
189
+ entity['text']
190
+ }.join(', ')
191
+ $stderr.puts "Entities = #{prettified}"
192
+ end
193
+
194
+ ### Select top keywords from all extracted keywords
195
+ # Remove keywords that intersect with entities of the types in @@categoryIgnores
196
+ allEntities = entitiesJSON['entities'].select { |entity|
197
+ @@categoryIgnores.has_key? entity['type'].downcase
198
+ }.collect { |entity|
199
+ entity['text'].downcase
200
+ }
201
+
202
+ if @@debugMe
203
+ prettified = keywordsJSON['keywords'].collect { |keyword|
204
+ keyword['text']
205
+ }.join(', ')
206
+ $stderr.puts "Keywords = #{prettified}"
207
+ end
208
+
209
+ keywordsList = keywordsJSON['keywords'].select { |keyword|
210
+ normalizedKw = keyword['text'].downcase
211
+ intersectsWithEntity = !(allEntities.select { |entity|
212
+ entity.include? normalizedKw or normalizedKw.include? entity
213
+ }.empty?)
214
+ # Ignore keywords > 4 words or those that intersect with entities
215
+ normalizedKw.split.size < 5 && !intersectsWithEntity
216
+ }.collect { |keyword|
217
+ keyword['text'].downcase
218
+ }
219
+
220
+ # Remove repeated keywords
221
+ keywordsList = getNonRepeatedKeywords(keywordsList)
222
+
223
+ ### Build Primal topic URI
224
+ primalRequest = ""
225
+ unless category.nil? then primalRequest = "/" + category end
226
+ if entitiesList.size > 0 then primalRequest = primalRequest + "/" + entitiesList.join("/") end
227
+ if keywordsList.size > 0 then primalRequest = primalRequest + "/" + keywordsList.join(";") end
228
+ if @@debugMe
229
+ $stderr.puts "Primal request = #{primalRequest}"
230
+ end
231
+ URI::encode(primalRequest)
232
+ end #function
233
+
234
+ #
235
+ # Returns the top @@keywordsLimit keywords, ignoring those contained
236
+ # within other keywords
237
+ #
238
+ def getNonRepeatedKeywords(keywordsList)
239
+ # If there is less than @@keywordsLimit, or if the first @@keywordsLimit keywords
240
+ # are unique, return the first @@keywordsLimit keywords
241
+ repeatedKeywords = getRepeatedKeywords(keywordsList[0, @@keywordsLimit])
242
+ if keywordsList.length <= @@keywordsLimit or repeatedKeywords.empty?
243
+ keywordsList[0, @@keywordsLimit]
244
+ else
245
+ # Remove repeated elements from the first @@keywordsLimit keywords, and recursively
246
+ # call this function
247
+ getNonRepeatedKeywords(keywordsList - repeatedKeywords)
248
+ end
249
+ end
250
+
251
+ #
252
+ # Returns any repeated words in the list
253
+ #
254
+ def getRepeatedKeywords(keywordsList)
255
+ keywordsList.select { |keyword|
256
+ not(keywordsList.select { |other|
257
+ other != keyword and other.include? keyword
258
+ }.empty?)
259
+ }
260
+ end
261
+
262
+ #
263
+ # Modifies the extracted category string to become a clear topic in the Primal
264
+ # request.
265
+ #
266
+ # AlchemyAPI categorizes text into a limited set of category types.
267
+ #
268
+ # See http://www.alchemyapi.com/api/categ/categs.html for a complete list.
269
+ #
270
+ # Some of the cateogy type names have two strings concatenated by an
271
+ # underscore character. This function selects one of the two strings (or a
272
+ # totally new string) to be the topic in the Primal request.
273
+ #
274
+ def rewriteCategory(category)
275
+ case category
276
+ when "unknown" # AlchemyAPI failed to classify the text
277
+ category = nil
278
+ when "arts_entertainment"
279
+ category = "arts" # rewrite to 'arts'
280
+ when "computer_internet"
281
+ category = "technology" # rewrite to 'technology', a clearer topic for this category
282
+ when "culture_politics"
283
+ category = "politics" # rewrite to 'politics'
284
+ when "law_crime"
285
+ category = "law" # rewrite to 'law'
286
+ when "science_technology"
287
+ category = "science" # rewrite to 'science'
288
+ else
289
+ # The previous conditions should cover all the categories extracted by
290
+ # Alchemy. In case of a new category that contains an underscore, replace
291
+ # it and keep the two words as the topic.
292
+ category = category.sub('_', ' ')
293
+ end
294
+ end
295
+
296
+ #
297
+ # Perform a POST request to Alchemy service URL and return the response as a
298
+ # JSON object
299
+ #
300
+ # Returns nil on error
301
+ #
302
+ def postAlchemy(serviceURL, parameters)
303
+ response = self.class.post(serviceURL, parameters)
304
+ returnAlchemyResponseJSON(response)
305
+ end
306
+
307
+ #
308
+ # Perform a GET request to Alchemy service URL and return the
309
+ # response as a JSON object
310
+ #
311
+ # Returns nil on error
312
+ #
313
+ def getAlchemy(serviceURL, parameters)
314
+ response = self.class.get(serviceURL, parameters)
315
+ returnAlchemyResponseJSON(response)
316
+ end
317
+
318
+ #
319
+ # Return the body of the response in a JSON object
320
+ # or nil on error
321
+ #
322
+ def returnAlchemyResponseJSON(response)
323
+ code = response.code
324
+ body = response.body
325
+ bodyJSON = JSON.parse(body)
326
+
327
+ # A statusInfo field contains the details of the error
328
+ if bodyJSON['status'] != "OK"
329
+ puts bodyJSON['statusInfo']
330
+ nil
331
+ else
332
+ bodyJSON
333
+ end
334
+ end
335
+ end
336
+ Ï
337
+
338
+ end
339
+
340
+
@@ -0,0 +1,204 @@
1
+ require 'rubygems'
2
+ require 'httparty'
3
+ require 'json'
4
+
5
+ module Primal
6
+ #
7
+ # The PrimalAccess class abstracts the access to Primal such
8
+ # that you can call simple methods on it to get what you need.
9
+ #
10
+ class PrimalAccess
11
+ include HTTParty
12
+ base_uri 'https://data.primal.com'
13
+ # Uncomment this next line to see what HTTParty is doing
14
+ # debug_output $stderr
15
+ # Set this to false in order to turn off debugging of this class
16
+ @@debugMe = true
17
+ #
18
+ # Constructor for the PrimalAccess class
19
+ #
20
+ # Pass in the username and password of the user you're going
21
+ # to access in order to construct and object that will work
22
+ # with that user
23
+ #
24
+ def initialize(appId, appKey, username, password)
25
+ @headers = {
26
+ :headers => {
27
+ 'Primal-App-ID' => appId,
28
+ 'Primal-App-Key' => appKey
29
+ },
30
+ :basic_auth => {
31
+ :username => username,
32
+ :password => password
33
+ }
34
+ }
35
+ end
36
+
37
+ #
38
+ # Sometimes we're going to get topics that are complex (i.e. they contain a
39
+ # scheme and host) and we want to simplify those. Because we're not making
40
+ # calls with bare URLs but have told HTTParty what the base_uri is, we need to
41
+ # pull that base uri off of the topic, should it be there.
42
+ #
43
+ def extractJustTopic(topic)
44
+ topic.sub(%r{https://.*?/}, '/')
45
+ end
46
+
47
+ #
48
+ # POSTs a new topic to Primal in order to seed that topic.
49
+ #
50
+ # The 'topic' parameter will be used to construct a POST URL
51
+ # that looks like "/topic"
52
+ #
53
+ # Returns two values: the response code and the body.
54
+ # Anything but a response code of 201 is to be considered
55
+ # an error.
56
+ #
57
+ def postNewTopic(topic, opts = {})
58
+ topic = extractJustTopic(topic)
59
+ count = 0
60
+ code = 400
61
+ body = ''
62
+ options = @headers.merge(opts)
63
+ while (count < 5)
64
+ if @@debugMe
65
+ $stderr.puts "POSTing to #{topic}"
66
+ end
67
+ response = self.class.post("#{topic}", options)
68
+ code = response.code
69
+ body = response.body
70
+ #
71
+ # 400 - bad request
72
+ # 401 - application not authorized to access the user's account
73
+ # 403 - application not authorized to use Primal
74
+ #
75
+ if code >= 400 && code <= 403
76
+ if @@debugMe
77
+ $stderr.puts "POST received a #{code}"
78
+ end
79
+ break
80
+ #
81
+ # 429 - application has reached its request limit for the moment
82
+ #
83
+ elsif code == 429
84
+ # Sleep for 10 seconds
85
+ if @@debugMe
86
+ $stderr.puts "Got a 429. Waiting (#{count})."
87
+ end
88
+ sleep 10
89
+ count += 1
90
+ #
91
+ # 201 - success
92
+ #
93
+ elsif code == 201
94
+ if @@debugMe
95
+ $stderr.puts "POST successful"
96
+ end
97
+ break
98
+ else
99
+ abort "Received unexpected response code (#{code}) for POST #{uri}"
100
+ end
101
+ end
102
+ return code, body
103
+ end
104
+
105
+ #
106
+ # Uses the pre-existing topic to filter the default source
107
+ # of content through the interest network defined by the topic.
108
+ #
109
+ # The given parameter will be used to construct a GET URL
110
+ # that looks like "/topic"
111
+ #
112
+ # You can pass a dictionary of optional arguments that will
113
+ # be merged in to the query parameters, if you wish.
114
+ # e.g.
115
+ # { :"primal:contentScore:min" => 0.7 }
116
+ # { :"primal:contentCount:max" => 5 }
117
+ # { :contentSource => MyDataSource } ... or ...
118
+ # { :contentSource => PrimalSource }
119
+ #
120
+ # Returns two values: the response code, and the body.
121
+ # If successful (i.e. a response code of 200) then the body
122
+ # will be the JSON payload of the filtered content.
123
+ #
124
+ def filterContent(topic, opts = {})
125
+ topic = extractJustTopic(topic)
126
+ count = 0
127
+ code = 400
128
+ body = ''
129
+ options = @headers.merge({ :query => {
130
+ :timeOut => 'max'
131
+ }.merge(opts)
132
+ })
133
+ while (count < 10)
134
+ if @@debugMe
135
+ $stderr.puts "GETting #{topic}"
136
+ end
137
+ response = self.class.get("#{topic}", options)
138
+ code = response.code
139
+ body = response.body
140
+ #
141
+ # 400 - bad request
142
+ # 401 - application not authorized to access the user's account
143
+ # 403 - application not authorized to use Primal
144
+ # 404 - object not found
145
+ #
146
+ if code >= 400 && code <= 404
147
+ if @@debugMe
148
+ $stderr.puts "GET received a #{code}"
149
+ end
150
+ break
151
+ #
152
+ # 429 - application has reached its request limit for the moment
153
+ #
154
+ elsif code == 429
155
+ if @@debugMe
156
+ $stderr.puts "Got a 429. Waiting (#{count})."
157
+ end
158
+ # Sleep for 10 seconds
159
+ sleep 10
160
+ # We don't allow as many retries when we might be throttled
161
+ count += 2
162
+ #
163
+ # 200 - success
164
+ #
165
+ elsif code == 200
166
+ if @@debugMe
167
+ $stderr.puts "Results are complete"
168
+ end
169
+ break
170
+ #
171
+ # We don't know what happened but it can't be good
172
+ #
173
+ else
174
+ abort "Received unexpected response code (#{code}) for GET #{topic}"
175
+ end
176
+ end
177
+ return code, body
178
+ end
179
+
180
+ #
181
+ # This is a convenience method that will POST the topic to
182
+ # Primal and then filter the default source of content through the
183
+ # resulting interest network.
184
+ #
185
+ # The response from this method is a bit less clear than using
186
+ # a POST and filter explicitly, since you may not know which
187
+ # one of the two operations has failed (assuming a failure).
188
+ #
189
+ # Returns two values: the response code and the body. The only
190
+ # successful response code from this method is 200. If
191
+ # successful then the body contains the JSON payload of the
192
+ # filtered content.
193
+ #
194
+ def postThenFilter(topic, opts = {})
195
+ code, body = postNewTopic(topic)
196
+ if code == 201
197
+ code, body = filterContent(topic, opts)
198
+ end
199
+ return code, body
200
+ end
201
+ end
202
+
203
+ end
204
+
@@ -0,0 +1,3 @@
1
+ module Primal
2
+ VERSION = "0.0.1"
3
+ end
data/primal.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'primal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "primal"
8
+ spec.version = Primal::VERSION
9
+ spec.authors = ["w2davids@gmail.com"]
10
+ spec.email = ["w2davids@gmail.com"]
11
+ spec.description = %q{Ruby gem for accessing Primal Data web services}
12
+ spec.summary = %q{Ruby client to access Primal Data web services}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.rubyforge_project = "primal"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "json"
26
+ spec.add_development_dependency "httparty"
27
+
28
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: primal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - w2davids@gmail.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Ruby gem for accessing Primal Data web services
70
+ email:
71
+ - w2davids@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .project
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/primal.rb
83
+ - lib/primal/AlchemyAPIWrapper.rb
84
+ - lib/primal/PrimalAccess.rb
85
+ - lib/primal/version.rb
86
+ - primal.gemspec
87
+ homepage: ''
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project: primal
107
+ rubygems_version: 2.0.3
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Ruby client to access Primal Data web services
111
+ test_files: []