classifieds_api 0.1.0 → 1.0.0

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
  SHA1:
3
- metadata.gz: 486b9412804f50e3cc7e010055abf47b683a7cb6
4
- data.tar.gz: 4edab757b113ff0470117d37585b83d710671abc
3
+ metadata.gz: 714c4645bfb468ff19cb1512775b8933d91c3fb6
4
+ data.tar.gz: b3d558c70659613ce0cfad26b8dcb63296c16bd6
5
5
  SHA512:
6
- metadata.gz: 3a08b4db4f33829aae03460c6cc5476e6491e3b0dfe59082ca4a0c1bc3d1adede678239dbcd0e1bbbc058820b36d8ff7b53e31b8d4fe0fa85d7a10cae747d52d
7
- data.tar.gz: 34fec05b950afeefec26f909e5e168f124cf7fc6858bf95a394b25d331f54295e5de8c12c6858b16d8062355723fb9a6bb35f47f74345bada2cbf9aca39dde3d
6
+ metadata.gz: 0b4c19a643adf817a6dd7fb9a8333772cb466d7f88c8cbe31ee7e2e2ed39411565c6c4a38ee8d80b5078976377ef691a9879e1d25ff41430e84f550e5bb069bf
7
+ data.tar.gz: 8e5623695ce780cf04cd8f47ffb34645a3d0d130784f7fc778a96a177e50066d6ec1563ec82a1e84b4f0cce5eec2f6473d408ce7baf758605881331249aff0ab
data/.gitignore CHANGED
@@ -34,5 +34,10 @@ bower.json
34
34
  # Ignore pow environment settings
35
35
  .powenv
36
36
 
37
- # Ignore the gem files
37
+ # Ignore gem files
38
38
  *.gem
39
+
40
+ # Ignore vim temporary files and swap files
41
+ *~
42
+ *.swp
43
+ *.swo
data/README.rdoc ADDED
@@ -0,0 +1,9 @@
1
+ = Classifieds API
2
+
3
+ == Description
4
+
5
+ Simple Ruby API for popular classifieds website.
6
+
7
+ == Installation
8
+
9
+ gem install classifieds_api
data/Rakefile CHANGED
@@ -1,2 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Jean-Francois Bisson"]
10
10
  spec.email = ["jbisson@uwaterloo.ca"]
11
11
 
12
- spec.summary = %q{Ruby API for popular classifieds website}
13
- spec.description = %q{Simple Ruby API for filtered ad searchs on popular classifieds website}
12
+ spec.summary = %q{Simple API for popular classifieds website}
13
+ spec.description = %q{Simple API for popular classifieds website. Currently, the gem allows you to do search items on Kijiji in Ontario.}
14
14
  spec.homepage = "https://github.com/jfbisson4/classifieds_api"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 1.8"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "test-unit", "~> 3.0"
27
28
 
28
29
  spec.add_runtime_dependency "nokogiri", "~> 1.6"
29
30
  end
@@ -1,5 +1,7 @@
1
- require "classifieds_api/version"
1
+ require 'classifieds_api/version'
2
+ require 'classifieds_api/search_filters'
3
+ require 'classifieds_api/ad'
4
+ require 'classifieds_api/kijiji'
2
5
 
3
6
  module ClassifiedsApi
4
- # Your code goes here...
5
7
  end
@@ -0,0 +1,115 @@
1
+ module ClassifiedsApi
2
+ class Ad
3
+ attr_reader :title, :date_listed, :price, :address, :description,
4
+ :image_urls, :offering, :featured, :url
5
+
6
+ def initialize(title, date_listed, price, address, description, image_urls,
7
+ offering, featured, url)
8
+ self.title = title
9
+ self.date_listed = date_listed
10
+ self.price = price
11
+ self.address = address
12
+ self.description = description
13
+ self.image_urls = image_urls
14
+ self.offering = offering
15
+ self.featured = featured
16
+ self.url = url
17
+ end
18
+
19
+ def title=(title)
20
+ unless title.is_a? String
21
+ raise TypeError, "Argument #{title} is not a string."
22
+ end
23
+ @title = title
24
+ end
25
+
26
+ def date_listed=(date_listed)
27
+ if date_listed.nil? == false
28
+ unless date_listed.is_a? DateTime
29
+ raise TypeError, "Argument #{date_listed} is not a DateTime."
30
+ end
31
+ end
32
+ @date_listed = date_listed
33
+ end
34
+
35
+ def price=(price)
36
+ if price.nil? == false
37
+ unless price.is_a? Numeric
38
+ raise TypeError, "Argument #{price} is not a numeric."
39
+ end
40
+ end
41
+ @price = price
42
+ end
43
+
44
+ def address=(address)
45
+ if address.nil? == false
46
+ unless address.is_a? String
47
+ raise TypeError, "Argument #{address} is not a string."
48
+ end
49
+ end
50
+ @address = address
51
+ end
52
+
53
+ def description=(description)
54
+ unless description.is_a? String
55
+ raise TypeError, "Argument #{description} is not a string."
56
+ end
57
+ @description = description
58
+ end
59
+
60
+ def image_urls=(image_urls)
61
+ if image_urls.nil? == false
62
+ unless image_urls.is_a? Array
63
+ raise TypeError, "Argument #{image_urls} is not a string."
64
+ end
65
+ end
66
+ @image_urls = image_urls
67
+ end
68
+
69
+ def offering=(offering)
70
+ unless !!offering == offering
71
+ raise TypeError "Argument #{offering} is not a string."
72
+ end
73
+ @offering = offering
74
+ end
75
+
76
+ def featured=(featured)
77
+ unless !!featured == featured
78
+ raise TypeError "Argument #{featured} is not a boolean."
79
+ end
80
+ @featured = featured
81
+ end
82
+
83
+ def url=(url)
84
+ unless url.is_a? String
85
+ raise TypeError, "Argument #{address} is no a string."
86
+ end
87
+ @url = url
88
+ end
89
+
90
+ def print_ad
91
+ puts '-------------------------------------------------------------------'
92
+ if @offering == true
93
+ print "Offering - "
94
+ else
95
+ print "Wanted - "
96
+ end
97
+ if @featured_ad == true
98
+ puts "Featured Ad"
99
+ else
100
+ puts "Regular Ad"
101
+ end
102
+ if (@date_listed.nil? == false)
103
+ puts "Date Listed: #{@date_listed.strftime("%d/%m/%Y %H:%M")}"
104
+ else
105
+ puts "Date Listed:"
106
+ end
107
+ puts "Title: #{@title}"
108
+ puts "Price: #{@price}"
109
+ puts "Description: #{@description}"
110
+ puts "Address: #{@address}"
111
+ puts "URL: #{@url}"
112
+ puts '-------------------------------------------------------------------'
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,322 @@
1
+ module ClassifiedsApi
2
+ class Kijiji
3
+
4
+ def search(keyword, search_limit, search_filters)
5
+
6
+ unless keyword.is_a? String
7
+ raise TypeError, "Argument #{keyword} is not a string."
8
+ end
9
+ unless search_limit.is_a? Numeric
10
+ raise TypeError, "Argument #{search_limit} is not a numeric."
11
+ end
12
+ if search_limit <= 0
13
+ raise RangeError, "Argument #{search_limit} should be bigger than 0."
14
+ end
15
+ if search_limit > SEARCH_LIMIT
16
+ raise RangeError,
17
+ "Argument #{search_limit} should be smaller than the search limit " +
18
+ "of #{SEARCH_LIMIT}."
19
+ end
20
+ unless search_filters.instance_of? SearchFilters
21
+ raise TypeError,
22
+ "The search filters argument is not of the SearchFilters class."
23
+ end
24
+
25
+ ads = []
26
+ page_number = 1
27
+ until ads.count >= search_limit
28
+
29
+ search_page_url = get_search_page_url(keyword,
30
+ page_number,
31
+ search_filters)
32
+ search_page_html = get_search_page_html(search_page_url)
33
+ noko_search_html = get_nokogiri_html(search_page_html)
34
+ noko_search_results = get_noko_results_on_search_page(
35
+ noko_search_html,
36
+ search_filters.include_sponsored_ads)
37
+
38
+ if noko_search_results.count == 0
39
+ return ads
40
+ end
41
+
42
+ noko_search_results.each do |noko_result|
43
+ if ads.count >= search_limit
44
+ return ads
45
+ end
46
+
47
+ ad_title_wanted = get_title (noko_result)
48
+ ad_title = remove_wanted (ad_title_wanted)
49
+ ad_price = get_price (noko_result)
50
+ ad_short_description = get_short_description (noko_result)
51
+ ad_offering = get_offering (ad_title_wanted)
52
+ ad_featured = get_ad_featured (noko_result)
53
+ ad_url = get_ad_url (noko_result)
54
+
55
+
56
+ new_ad = Ad.new(ad_title,
57
+ nil,
58
+ ad_price,
59
+ nil,
60
+ ad_short_description,
61
+ nil,
62
+ ad_offering,
63
+ ad_featured,
64
+ ad_url)
65
+
66
+ ads.push(new_ad)
67
+ end
68
+ page_number += 1
69
+ end
70
+ return ads
71
+ end
72
+
73
+ private
74
+
75
+ def get_search_page_url(keyword, page_number, search_filters)
76
+ category_key = get_category_key (search_filters.category)
77
+ category_id = get_category_id (search_filters.category)
78
+ page_key = get_page_key (page_number)
79
+ location_string_key = get_location_string_key (search_filters.location)
80
+ location_id = get_location_id (search_filters.location)
81
+ distance_key = get_distance_key (search_filters.distance)
82
+ offer_type_key = get_offer_type_key (search_filters.offer_type)
83
+ price_key = get_price_key(search_filters.price_minimum,
84
+ search_filters.price_maximum,
85
+ offer_type_key)
86
+
87
+
88
+ url = ""
89
+ url += "http://www.kijiji.ca/b-"
90
+ url += "#{category_key}"
91
+ url += "#{location_string_key}/"
92
+ url += "#{keyword}/"
93
+ url += "#{page_key}"
94
+ url += "#{category_id}"
95
+ url += "#{location_id}"
96
+ url += "#{distance_key}"
97
+ url += "#{offer_type_key}"
98
+ url += "#{price_key}"
99
+ return url
100
+ end
101
+
102
+ def get_search_page_html(page_url)
103
+ html = ""
104
+ open(page_url) {|io| html = io.read}
105
+ end
106
+
107
+ def get_nokogiri_html(html)
108
+ noko_html = Nokogiri::HTML(html)
109
+ end
110
+
111
+ def get_noko_results_on_search_page(noko_html, include_sponsored_ads)
112
+ noko_regular_ads = noko_html.css('table.regular-ad')
113
+ if include_sponsored_ads == true
114
+ noko_featured_ads = noko_html.css('table.top-feature')
115
+ noko_ads = noko_featured_ads + noko_regular_ads
116
+ else
117
+ noko_ads = noko_regular_ads
118
+ end
119
+ return noko_ads
120
+ end
121
+
122
+ def get_title(noko_result)
123
+ title = noko_result.css('td.description').css('a.title').text.strip
124
+ end
125
+
126
+ def remove_wanted(title_wanted)
127
+ title = title_wanted.gsub('Wanted:', '').strip
128
+ end
129
+
130
+ def get_price(noko_result)
131
+ string_price =
132
+ noko_result.css('td.price').text.strip.gsub('$', '').gsub(',', '')
133
+ price = string_price.to_f
134
+ if string_price == "Free"
135
+ return 0
136
+ elsif string_price == "Please Contact" || string_price == ""
137
+ return nil
138
+ else
139
+ return price
140
+ end
141
+ end
142
+
143
+ def get_short_description(noko_result)
144
+ description = noko_result.css('td.description').css('p').text.strip
145
+ end
146
+
147
+ def get_offering(title_wanted)
148
+ if title_wanted.include? 'Wanted:'
149
+ return false
150
+ else
151
+ return true
152
+ end
153
+ end
154
+
155
+ def get_ad_featured(noko_result)
156
+ css_class = get_node_class(noko_result)
157
+ if (css_class.include? 'regular-ad')
158
+ return false
159
+ else
160
+ return true
161
+ end
162
+ end
163
+
164
+ def get_node_class(noko_result)
165
+ css_class = noko_result['class'].strip
166
+ end
167
+
168
+ def get_ad_url(noko_result)
169
+ extension = noko_result.css('td.description').css('a.title')[0]["href"]
170
+ url = "http://www.kijiji.ca" + extension
171
+ end
172
+
173
+ def get_category_key(category)
174
+ if category == 'all'
175
+ return ""
176
+ else
177
+ return "#{CATEGORY_KEYS[category]}/"
178
+ end
179
+ end
180
+
181
+ def get_category_id(category)
182
+ return CATEGORY_IDS[category]
183
+ end
184
+
185
+ def get_page_key(page_number)
186
+ if (page_number > 1)
187
+ return "page-#{page_number}/"
188
+ else
189
+ return ""
190
+ end
191
+ end
192
+
193
+ def get_location_string_key(location)
194
+ if location == 'Toronto (GTA)'
195
+ return 'gta-greater-toronto-area'
196
+ end
197
+ location_string = location.dup
198
+ location_string.gsub! '/', ''
199
+ location_string.gsub! '.', ''
200
+ location_string.downcase!
201
+ location_string.split(' ').join('-')
202
+ end
203
+
204
+ def get_location_id(location)
205
+ location_id = LOCATION_IDS[location]
206
+ end
207
+
208
+ def get_distance_key(distance)
209
+ if distance != 50
210
+ return "r#{distance}"
211
+ else
212
+ return ""
213
+ end
214
+ end
215
+
216
+ def get_offer_type_key(offer_type)
217
+ offer_key = ""
218
+ if offer_type == 'Offering'
219
+ offer_key = "?ad=offering"
220
+ elsif offer_type == 'Wanted'
221
+ offer_key = '?ad=wanted'
222
+ end
223
+ return offer_key
224
+ end
225
+
226
+ def get_price_key(min_price, max_price, previous_param)
227
+ price_key = ""
228
+ if min_price != 0 || max_price != 10000000
229
+ if previous_param != ""
230
+ price_key += "&price="
231
+ else
232
+ price_key += "?price="
233
+ end
234
+ if min_price != 0
235
+ price_key += "#{min_price}"
236
+ end
237
+ price_key += "__"
238
+ if max_price != 10000000
239
+ price_key += "#{max_price}"
240
+ end
241
+ end
242
+ return price_key
243
+ end
244
+
245
+ SEARCH_LIMIT = 10
246
+
247
+ CATEGORY_KEYS = Hash[ 'buy and sell', 'buy-sell',
248
+ 'services', 'services',
249
+ 'cars & vehicles', 'cars-vehicles',
250
+ 'pets', 'pets',
251
+ 'vacation rentals', 'vacation-rentals',
252
+ 'community', 'community',
253
+ 'real estate', 'real-estate',
254
+ 'jobs', 'jobs',
255
+ 'resumes', 'resumes']
256
+
257
+
258
+ CATEGORY_IDS = Hash['all', 'k0l',
259
+ 'buy and sell', 'k0c10l',
260
+ 'services', 'k0c72l',
261
+ 'cars & vehicles', 'k0c27l',
262
+ 'pets', 'k0c112l',
263
+ 'vacation rentals', 'k0c800l',
264
+ 'community', 'k0c1l',
265
+ 'real estate', 'k0c34l',
266
+ 'jobs', 'k0c45l',
267
+ 'resumes', 'k0c218l']
268
+
269
+ LOCATION_IDS = Hash['Berrie', '1700006',
270
+ 'Belleville Area', '1700129',
271
+ 'Belleville', '1700130',
272
+ 'Trenton', '1700132',
273
+ 'Brantford', '1700206',
274
+ 'Brockville', '1700247',
275
+ 'Chatham-Kent', '1700239',
276
+ 'Cornwall', '1700133',
277
+ 'Guelph', '1700242',
278
+ 'Hamilton', '80014',
279
+ 'Kapuskasing', '1700237',
280
+ 'Kenora', '1700249',
281
+ 'Kingston Area', '1700181',
282
+ 'Kingston', '1700183',
283
+ 'Napanee', '1700182',
284
+ 'Kitchener Area', '1700209',
285
+ 'Cambridge', '1700210',
286
+ 'Kitchener / Waterloo', '1700212',
287
+ 'Stratford', '1700213',
288
+ 'Leamington', '1700240',
289
+ 'London', '1700214',
290
+ 'Muskoka', '1700078',
291
+ 'Norfolk County', '1700248',
292
+ 'North Bay', '1700243',
293
+ 'Ottawa / Gatineau Area', '1700184',
294
+ 'Gatineau', '1700186',
295
+ 'Ottawa', '1700185',
296
+ 'Owen Sound', '1700187',
297
+ 'Peterborough Area', '1700217',
298
+ 'Kawartha Lakes', '1700219',
299
+ 'Peterborough', '1700218',
300
+ 'Renfrew County Area', '1700074',
301
+ 'Pembroke', '1700075',
302
+ 'Petawawa', '1700076',
303
+ 'Renfrew', '1700077',
304
+ 'Sarnia Area', '1700189',
305
+ 'Grand Bend', '1700190',
306
+ 'Sarnia', '1700191',
307
+ 'Sault Ste. Marie', '1700244',
308
+ 'St. Catharines', '80016',
309
+ 'Sudbury', '1700245',
310
+ 'Thunder Bay', '1700126',
311
+ 'Timmins', '1700238',
312
+ 'Toronto (GTA)', '1700272',
313
+ 'City of Toronto', '1700273',
314
+ 'Markham / York Region', '1700274',
315
+ 'Mississauga / Peel Region', '1700276',
316
+ 'Oakville / Halton Region', '1700277',
317
+ 'Oshawa / Durham Region', '1700275',
318
+ 'Windsor Region', '1700220',
319
+ 'Woodstock', '1700241']
320
+
321
+ end
322
+ end
@@ -0,0 +1,134 @@
1
+ module ClassifiedsApi
2
+ class SearchFilters
3
+
4
+ attr_reader :category, :location, :distance, :offer_type, :price_minimum,
5
+ :price_maximum, :additional_info, :include_sponsored_ads
6
+
7
+ def initialize(params={})
8
+ self.category = params[:category] || 'all'
9
+ self.location = params[:location]
10
+ self.distance = params[:distance] || 50
11
+ self.offer_type = params[:offer_type] || 'all'
12
+ self.price_minimum = params[:price_minimum] || 0
13
+ self.price_maximum = params[:price_maximum] || 10000000
14
+ self.include_sponsored_ads = params[:include_sponsored_ads] || false
15
+ end
16
+
17
+ def category=(category)
18
+ unless CATEGORIES.include? category
19
+ #print_list('CATEGORIES', CATEGORIES)
20
+ raise ArgumentError,
21
+ "Argument #{category} is not a valid category."
22
+ end
23
+ @category = category
24
+ end
25
+
26
+ def location=(location)
27
+ unless LOCATIONS.include? location
28
+ #print_list('LOCATIONS', LOCATIONS)
29
+ raise ArgumentError,
30
+ "Argument #{location} is not a valid location."
31
+ end
32
+ @location = location
33
+ end
34
+
35
+ def distance=(distance)
36
+ unless distance.is_a? Numeric
37
+ raise TypeError, "Argument #{distance} is not numeric."
38
+ end
39
+ if 0 > distance || distance > 500
40
+ raise RangeError, "Argument #{distance} should be between 0 and 500."
41
+ end
42
+ @distance = distance
43
+ end
44
+
45
+ def offer_type=(offer_type)
46
+ unless OFFER_TYPES.include? offer_type
47
+ #print_list('OFFER TYPES', OFFER_TYPES)
48
+ raise ArgumentError,
49
+ "Argument #{offer_type} is not a valid offer type."
50
+ end
51
+ @offer_type = offer_type
52
+ end
53
+
54
+ def price_minimum=(price_minimum)
55
+ unless price_minimum.is_a? Numeric
56
+ raise TypeError, "Argument #{price_minimum} is not numeric."
57
+ end
58
+ if 0 > price_minimum
59
+ raise RangeError,
60
+ "Argument #{price_minimum} should be between bigger than 0."
61
+ end
62
+ if price_minimum > (@price_maximum || 10000000)
63
+ raise RangeError,
64
+ "Argument #{price_minimum} should be smaller than maximum price " +
65
+ "#{@price_maximum}."
66
+ end
67
+ @price_minimum = price_minimum
68
+ end
69
+
70
+ def price_maximum=(price_maximum)
71
+ unless price_maximum.is_a? Numeric
72
+ raise TypeError, "Argument #{price_maximum} is not numeric."
73
+ end
74
+ if price_maximum < (@price_minimum || 0)
75
+ raise RangeError,
76
+ "Argument #{price_maximum} should be bigger than minimum price " +
77
+ "#{@price_minimum}."
78
+ end
79
+ @price_maximum = price_maximum
80
+ end
81
+
82
+ def include_sponsored_ads=(include_sponsored_ads)
83
+ unless !!include_sponsored_ads == include_sponsored_ads
84
+ raise TypeError, "Argument #{include_sponsored_ads} is not a boolean."
85
+ end
86
+ @include_sponsored_ads = include_sponsored_ads
87
+ end
88
+
89
+ def print_filters
90
+ puts '-------------------------------------------------------------------'
91
+ puts 'Search Filters:'
92
+ puts "Category: #{@category}"
93
+ puts "Location: #{@location}"
94
+ puts "Distance: #{@distance}"
95
+ puts "Offer Type: #{@offer_type}"
96
+ puts "Minimum Price: #{@price_minimum}"
97
+ puts "Maximum Price: #{@price_maximum}"
98
+ puts "Include Sponsored Ads: #{@include_sponsored_ads}"
99
+ puts '-------------------------------------------------------------------'
100
+ end
101
+
102
+ private
103
+
104
+ def print_list(list_name, list)
105
+ puts '-------------------------------------------------------------------'
106
+ puts "#{list_name}:"
107
+ list.each do |element|
108
+ puts element
109
+ end
110
+ puts '-------------------------------------------------------------------'
111
+ end
112
+
113
+ CATEGORIES = ['all', 'buy and sell', 'services', 'cars & vehicles', 'pets',
114
+ 'vacation rentals', 'community', 'real estate', 'jobs',
115
+ 'resumes']
116
+
117
+ LOCATIONS = ['Berrie', 'Belleville Area', 'Belleville', 'Trenton',
118
+ 'Brantford', 'Brockville', 'Chatham-Kent', 'Cornwall',
119
+ 'Guelph', 'Hamilton', 'Kapuskasing', 'Kenora', 'Kingston Area',
120
+ 'Kingston', 'Napanee', 'Kitchener Area', 'Cambridge',
121
+ 'Kitchener / Waterloo', 'Stratford', 'Leamington', 'London',
122
+ 'Muskoka', 'Norfolk County', 'North Bay',
123
+ 'Ottawa / Gatineau Area', 'Gatineau', 'Ottawa', 'Owen Sound',
124
+ 'Peterborough Area', 'Kawartha Lakes', 'Peterborough',
125
+ 'Renfrew County Area', 'Pembroke', 'Petawawa', 'Renfrew',
126
+ 'Sarnia Area', 'Grand Bend', 'Sarnia', 'Sault Ste. Marie',
127
+ 'St. Catharines', 'Sudbury', 'Thunder Bay', 'Timmins',
128
+ 'Toronto (GTA)', 'City of Toronto', 'Markham / York Region',
129
+ 'Mississauga / Peel Region', 'Oakville / Halton Region',
130
+ 'Oshawa / Durham Region', 'Windsor Region', 'Woodstock']
131
+
132
+ OFFER_TYPES = ['all', 'Offering', 'Wanted']
133
+ end
134
+ end
@@ -1,3 +1,3 @@
1
1
  module ClassifiedsApi
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classifieds_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Francois Bisson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-04-17 00:00:00.000000000 Z
11
+ date: 2015-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: nokogiri
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +66,8 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.6'
55
- description: Simple Ruby API for filtered ad searchs on popular classifieds website
69
+ description: Simple API for popular classifieds website. Currently, the gem allows
70
+ you to do search items on Kijiji in Ontario.
56
71
  email:
57
72
  - jbisson@uwaterloo.ca
58
73
  executables: []
@@ -63,12 +78,15 @@ files:
63
78
  - ".travis.yml"
64
79
  - Gemfile
65
80
  - LICENSE
66
- - README.md
81
+ - README.rdoc
67
82
  - Rakefile
68
83
  - bin/console
69
84
  - bin/setup
70
85
  - classifieds_api.gemspec
71
86
  - lib/classifieds_api.rb
87
+ - lib/classifieds_api/ad.rb
88
+ - lib/classifieds_api/kijiji.rb
89
+ - lib/classifieds_api/search_filters.rb
72
90
  - lib/classifieds_api/version.rb
73
91
  homepage: https://github.com/jfbisson4/classifieds_api
74
92
  licenses: []
@@ -93,5 +111,5 @@ rubyforge_project:
93
111
  rubygems_version: 2.4.5
94
112
  signing_key:
95
113
  specification_version: 4
96
- summary: Ruby API for popular classifieds website
114
+ summary: Simple API for popular classifieds website
97
115
  test_files: []
data/README.md DELETED
@@ -1,2 +0,0 @@
1
- # classifieds_api
2
- Ruby API for popular classifieds website