classifieds_api 0.1.0 → 1.0.0

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 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