factual-api 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## v1.3
2
+ * added diffs
3
+ * changed raw read to get
4
+ * added raw post
5
+ * moved README to wiki
6
+ * added match
7
+
8
+ ## v1.2.1
9
+ * crosswalk endpoint change
10
+
1
11
  ## v1.2
2
12
  * releasing geo features, facets, writes, multi and monetize
3
13
 
data/README.md CHANGED
@@ -3,8 +3,6 @@
3
3
  This is the Factual supported Ruby driver for [Factual's public API](http://developer.factual.com/display/docs/Factual+Developer+APIs+Version+3).
4
4
 
5
5
 
6
- This driver is supported via the [Factual Developer Group](https://groups.google.com/group/factual_developers)
7
-
8
6
  # Overview
9
7
 
10
8
  ## Basic Design
@@ -24,11 +22,19 @@ Results are returned as Ruby Arrays of Hashes, where each Hash is a result recor
24
22
 
25
23
  ## Setup
26
24
 
27
- The driver's gems are hosted at [Rubygems.org](http://rubygems.org). You can install the factual-api gem as follows:
25
+ The driver's gems are hosted at [Rubygems.org](http://rubygems.org).
26
+
27
+ You can install the factual-api gem as follows:
28
28
 
29
- `````bash
29
+ ````bash
30
30
  $ gem install factual-api
31
- `````
31
+ ````
32
+
33
+ Or add one line to the Gemfile of your Rails project, and run `bundle`:
34
+
35
+ ````ruby
36
+ gem 'factual-api'
37
+ ````
32
38
 
33
39
  Once the gem is installed, you can use it in your Ruby project like:
34
40
 
@@ -138,616 +144,6 @@ query.rows # return many rows
138
144
  query.total_count
139
145
  ````
140
146
 
141
- # Read API
142
-
143
- ## All Top Level Query Parameters
144
-
145
- <table>
146
- <col width="33%"/>
147
- <col width="33%"/>
148
- <col width="33%"/>
149
- <tr>
150
- <th>Parameter</th>
151
- <th>Description</th>
152
- <th>Example</th>
153
- </tr>
154
- <tr>
155
- <td>filters</td>
156
- <td>Restrict the data returned to conform to specific conditions.</td>
157
- <td><tt>query = query.filters("name" => {"$bw" => "starbucks"})</tt></td>
158
- </tr>
159
- <tr>
160
- <td>get total row count</td>
161
- <td>returns the total count of the number of rows in the dataset that conform to the query.</td>
162
- <td><tt>query.total_count</tt></td>
163
- </tr>
164
- <tr>
165
- <td>geo</td>
166
- <td>Restrict data to be returned to be within a geographical range based.</td>
167
- <td>(See the section on Geo Filters)</td>
168
- </tr>
169
- <tr>
170
- <td>limit</td>
171
- <td>Limit the results</td>
172
- <td><tt>query = query.limit(12)</tt></td>
173
- </tr>
174
- <tr>
175
- <td>page</td>
176
- <td>Limit the results to a specific "page".</td>
177
- <td><tt>query = query.page(2, :per => 10)</tt></td>
178
- </tr>
179
- <tr>
180
- <td>search (across entity)</td>
181
- <td>Full text search across entity</td>
182
- <td>
183
- Find "sushi":<br><tt>query = query.search("sushi")</tt><p>
184
- Find "sushi" or "sashimi":<br><tt>query = query.search("sushi", "sashimi")</tt><p>
185
- Find "sushi" and "santa" and "monica":<br><tt>query.search("sushi santa monica")</tt>
186
- </td>
187
- </tr>
188
- <tr>
189
- <td>search (across field)</td>
190
- <td>Full text search on specific field</td>
191
- <td><tt>query = query.filters({"name" => {"$search" => "cafe"}})</tt></td>
192
- </tr>
193
- <tr>
194
- <td>select</td>
195
- <td>Specifiy which fields to include in the query results. Note that the order of fields will not necessarily be preserved in the resulting response due to the nature Hashes.</td>
196
- <td><tt>query = query.select(:name, :address, :locality, :region)</tt></td>
197
- </tr>
198
- <tr>
199
- <td>sort</td>
200
- <td>The field (or fields) to sort data on, as well as the direction of sort.<p>
201
- Sorts ascending by default, but supports both explicitly sorting ascending and descending, by using <tt>sort_asc</tt> or <tt>sort_desc</tt>.
202
- Supports $distance as a sort option if a geo-filter is specified.<p>
203
- Supports $relevance as a sort option if a full text search is specified either using the q parameter or using the $search operator in the filter parameter.<p>
204
- By default, any query with a full text search will be sorted by relevance.<p>
205
- Any query with a geo filter will be sorted by distance from the reference point. If both a geo filter and full text search are present, the default will be relevance followed by distance.</td>
206
- <td><tt>query = query.sort("name")</tt><br>
207
- <tt>query = query.sort_desc("$distance")</tt>
208
- <tt>query = query.sort_asc("name").sort_desc("rating")</tt></td>
209
- </tr>
210
- </table>
211
-
212
- ## Row Filters
213
-
214
- The driver supports various row filter logic. For example:
215
-
216
- `````ruby
217
- # Returns records from the Places dataset with names beginning with "starbucks"
218
- factual.table("places").filters("name" => {"$bw" => "starbucks"}).rows
219
- ````
220
-
221
- ### Supported row filter logic
222
-
223
- <table>
224
- <tr>
225
- <th>Predicate</th>
226
- <th width="25%">Description</th>
227
- <th>Example</th>
228
- </tr>
229
- <tr>
230
- <td>$eq</td>
231
- <td>equal to</td>
232
- <td><tt>query = query.filters("region" => {"$eq" => "CA"})</tt></td>
233
- </tr>
234
- <tr>
235
- <td>$neq</td>
236
- <td>not equal to</td>
237
- <td><tt>query = query.filters("region" => {"$neq" => "CA"})</tt></td>
238
- </tr>
239
- <tr>
240
- <td>search</td>
241
- <td>full text search</td>
242
- <td><tt>query = query.search("sushi")</tt></td>
243
- </tr>
244
- <tr>
245
- <td>$in</td>
246
- <td>equals any of</td>
247
- <td><tt>query = query.filters("region" => {"$in" => ["CA", "NM", "NY"]})</tt></td>
248
- </tr>
249
- <tr>
250
- <td>$nin</td>
251
- <td>does not equal any of</td>
252
- <td><tt>query = query.filters("region" => {"$nin" => ["CA", "NM", "NY"]})</tt></td>
253
- </tr>
254
- <tr>
255
- <td>$bw</td>
256
- <td>begins with</td>
257
- <td><tt>query = query.filters("name" => {"$bw" => "starbucks"})</tt></td>
258
- </tr>
259
- <tr>
260
- <td>$nbw</td>
261
- <td>does not begin with</td>
262
- <td><tt>query = query.filters("name" => {"$nbw" => "starbucks"})</tt></td>
263
- </tr>
264
- <tr>
265
- <td>$bwin</td>
266
- <td>begins with any of</td>
267
- <td><tt>query = query.filters("name" => {"$bwin" => ["starbucks", "coffee", "tea"]})</tt></td>
268
- </tr>
269
- <tr>
270
- <td>$nbwin</td>
271
- <td>does not begin with any of</td>
272
- <td><tt>query = query.filters("name" => {"$nbwin" => ["starbucks", "coffee", "tea"]})</tt></td>
273
- </tr>
274
- <tr>
275
- <td>$blank</td>
276
- <td>test to see if a value is (or is not) blank or null</td>
277
- <td><tt>query = query.filters("tel" => {"$blank" => true})</tt><br>
278
- <tt>query = query.filters("website" => {"$blank" => false})</tt></td>
279
- </tr>
280
- <tr>
281
- <td>$gt</td>
282
- <td>greater than</td>
283
- <td><tt>query = query.filters("rating" => {"$gt" => 7.5})</tt></td>
284
- </tr>
285
- <tr>
286
- <td>$gte</td>
287
- <td>greater than or equal</td>
288
- <td><tt>query = query.filters("rating" => {"$gte" => 7.5})</tt></td>
289
- </tr>
290
- <tr>
291
- <td>$lt</td>
292
- <td>less than</td>
293
- <td><tt>query = query.filters("rating" => {"$lt" => 7.5})</tt></td>
294
- </tr>
295
- <tr>
296
- <td>$lte</td>
297
- <td>less than or equal</td>
298
- <td><tt>query = query.filters("rating" => {"$lte" => 7.5})</tt></td>
299
- </tr>
300
- </table>
301
-
302
- ### AND
303
-
304
- Filters can be logically AND'd together. For example:
305
-
306
- ````ruby
307
- # name begins with "coffee" AND tel is not blank
308
- query = query.filters({ "$and" => [{"name" => {"$bw" => "coffee"}}, {"tel" => {"$blank" => false}}] })
309
- ````
310
-
311
- ### OR
312
-
313
- Filters can be logically OR'd. For example:
314
-
315
- ````ruby
316
- # name begins with "coffee" OR tel is not blank
317
- query = query.filters({ "$or" => [{"name" => {"$bw" => "coffee"}}, {"tel" => {"$blank" => false}}] })
318
- ````
319
-
320
- ### Combined ANDs and ORs
321
-
322
- You can nest AND and OR logic to whatever level of complexity you need. For example:
323
-
324
- ````ruby
325
- # (name begins with "Starbucks") OR (name begins with "Coffee")
326
- # OR
327
- # (name full text search matches on "tea" AND tel is not blank)
328
- query = query.filters({ "$or" => [ {"$or" => [ {"name" => {"$bw" => "starbucks"}},
329
- {"name" => {"$bw" => "coffee"}}]},
330
- {"$and" => [ {"name" => {"$search" => "tea"}},
331
- {"tel" => {"$blank" => false}} ]} ]})
332
- ````
333
-
334
- # Crosswalk
335
-
336
- The driver fully supports Factual's Crosswalk feature, which lets you "crosswalk" the web and relate entities between Factual's data and that of other web authorities.
337
-
338
- (See [the Crosswalk Blog](http://blog.factual.com/crosswalk-api) for more background.)
339
-
340
- ## Simple Crosswalk Example
341
-
342
- ````ruby
343
- # Get all Crosswalk data for a Place with a specific FactualID
344
- factual.crosswalk("110ace9f-80a7-47d3-9170-e9317624ebd9").rows
345
- ````
346
-
347
- ## Supported Crosswalk Options
348
-
349
- ### only
350
-
351
- You can specify which namespaces you want, like this:
352
-
353
- ````ruby
354
- # Get Crosswalk data for only yelp and facebook for a Place with a specific FactualID
355
- factual.crosswalk("110ace9f-80a7-47d3-9170-e9317624ebd9").only(:yelp, :facebook).rows
356
- ````
357
-
358
- This will generally return 1 record per requested namespace.
359
-
360
- ### limit
361
-
362
- You can limit the amount of Crosswalk results you get back, like this:
363
-
364
- ````ruby
365
- # Get only 3 Crosswalk results for a Place with a specific FactualID
366
- factual.crosswalk("110ace9f-80a7-47d3-9170-e9317624ebd9").limit(3).rows
367
- ````
368
-
369
- # Resolve
370
-
371
- The driver fully supports Factual's Resolve feature, which lets you start with incomplete data you may have for an entity, and get potential entity matches back from Factual.
372
-
373
- Each result record will include a confidence score (<tt>"similarity"</tt>), and a flag indicating whether Factual decided the entity is the correct resolved match with a high degree of accuracy (<tt>"resolved"</tt>).
374
-
375
- For any Resolve query, there will be 0 or 1 entities returned with <tt>"resolved"=true</tt>. If there was a full match, it is guaranteed to be the first record in the response Array.
376
-
377
- (See [the Resolve Blog](http://blog.factual.com/factual-resolve) for more background.)
378
-
379
- ## Simple Resolve Examples
380
-
381
- ````ruby
382
- # Returns resolved entities as an array of hashes
383
- query = factual.resolve("name" => "McDonalds",
384
- "address" => "10451 Santa Monica Blvd",
385
- "region" => "CA",
386
- "postcode" => "90025")
387
-
388
- query.first["resolved"] # true or false
389
- query.rows # all candidate rows
390
- ````
391
-
392
- # Geo Filters
393
-
394
- You can query Factual for entities located within a geographic area. For example:
395
-
396
- ````ruby
397
- query = query.geo("$circle" => {"$center" => [34.06021, -118.41828], "$meters" => 5000})
398
- ````
399
-
400
- # Facets
401
-
402
- The driver fully supports Factual's Facets feature, which lets you return row counts for Factual tables, grouped by facets of data. For example, you may want to query all businesses within 1 mile of a location and for a count of those businesses by category.
403
-
404
- For example:
405
-
406
- ````ruby
407
- # Returns a count of Starbucks by country
408
- factual.facets("global").select("country").search("starbucks").columns
409
- ````
410
-
411
- ## All Top Level Facets Parameters
412
-
413
- <table>
414
- <col width="33%"/>
415
- <col width="33%"/>
416
- <col width="33%"/>
417
- <tr>
418
- <th>Parameter</th>
419
- <th>Description</th>
420
- <th>Example</th>
421
- </tr>
422
- <tr>
423
- <td>select</td>
424
- <td>The fields for which facets should be generated. The response will not be ordered identically to this list, nor will it reflect any nested relationships between fields.</td>
425
- <td><tt>.select("region", "locality")</tt></td>
426
- </tr>
427
- <tr>
428
- <td>limit</td>
429
- <td>The maximum number of unique facet values that can be returned for a single field. Range is 1-250. The default is 25.</td>
430
- <td><tt>.limit(10)</tt></td>
431
- </tr>
432
- <tr>
433
- <td>filters</td>
434
- <td>Restrict the data returned to conform to specific conditions.</td>
435
- <td><tt>.filters("name" => {"$bw" => "starbucks"})</tt></td>
436
- </tr>
437
- <tr>
438
- <td>include_count</td>
439
- <td>Include a count of the total number of rows in the dataset that conform to the request based on included filters. Requesting the row count will increase the time required to return a response. The default behavior is to NOT include a row count. When the row count is requested, the Response object will contain a valid total row count via <tt>.getTotalRowCount()</tt>.</td>
440
- <td><tt>.include_count</tt></td>
441
- </tr>
442
- <tr>
443
- <td>geo</td>
444
- <td>Restrict data to be returned to be within a geographical range.</td>
445
- <td>(See the section on Geo Filters)</td>
446
- </tr>
447
- <tr>
448
- <td>search</td>
449
- <td>Full text search query string.</td>
450
- <td>
451
- Find "sushi":<br><tt>.search("sushi")</tt><p>
452
- Find "sushi" or "sashimi":<br><tt>.search("sushi, sashimi")</tt><p>
453
- Find "sushi" and "santa" and "monica":<br><tt>.search("sushi santa monica")</tt>
454
- </td>
455
- </tr>
456
- </table>
457
-
458
- </table>
459
-
460
-
461
- # Flag
462
-
463
- Factual's Flag feature enables flagging problematic rows in Factual tables. Use this feature if you are requesting for an entity to be deleted or merged into a duplicate record.
464
-
465
- ## Simple Flag Example
466
-
467
- ````ruby
468
- # User user123 flags row 0545b03f-9413-44ed-8882-3a9a461848da in the global dataset as inaccurate
469
- factual.flag("global", "0545b03f-9413-44ed-8882-3a9a461848da", :inaccurate, "user123").write
470
- ````
471
-
472
- The reason for flagging must be one of the following:
473
- <ul>
474
- <li>:duplicate
475
- <li>:nonexistent
476
- <li>:inaccurate
477
- <li>:inappropriate
478
- <li>:spam
479
- <li>:other
480
- </ul>
481
-
482
- You can also create a Flag object and set it with optional parameters beforing writing it. For example:
483
-
484
- ````ruby
485
- flag = factual.flag("global", "0545b03f-9413-44ed-8882-3a9a461848da", :inaccurate, "user123")
486
- flag = flag.comment("this row is outdated").reference("http://www.example.com/somepage.html")
487
- flag.write
488
- ````
489
-
490
- ## Optional Flag Parameters
491
-
492
- <table>
493
- <tr>
494
- <th>Parameter</th>
495
- <th>Description</th>
496
- <th>Example</th>
497
- </tr>
498
- <tr>
499
- <td>comment</td>
500
- <td>Any english text comment that may help explain your corrections.</td>
501
- <td><tt>.comment("this row is outdated")</tt></td>
502
- </tr>
503
- <tr>
504
- <td>reference</td>
505
- <td>A reference to a URL, title, person, etc. that is the source of this data.</td>
506
- <td><tt>.reference("http://www.example.com/somepage.html")</tt></td>
507
- </tr>
508
- </table>
509
-
510
-
511
- # Geopulse
512
-
513
- The driver fully supports Factual's <a href="http://developer.factual.com/display/DOCS/Places+API+-+Geopulse">Geopulse</a> feature, which provides point-based access to geographic attributes: you provide a long/lat coordinate pair, we provide everything we can know about that geography.
514
-
515
- The Geopulse API is made up of several "pulses". Pulses are georeferenced attributes generated by Factual, sourced from openly available content (such as the US Census), or provided to Factual by proprietary third-parties.
516
-
517
- ## Simple Geopulse Example
518
-
519
- The <tt>geopulse</tt> method fetches results based on the given point:
520
-
521
- ````ruby
522
- query = factual.geopulse(34.06021, -118.41828).select("commercial_density", "commercial_profile")
523
- query.first
524
- ````
525
-
526
-
527
- ## All Top Level Geopulse Parameters
528
-
529
- <table>
530
- <tr>
531
- <th>Parameter</th>
532
- <th>Description</th>
533
- <th>Example</th>
534
- </tr>
535
- <tr>
536
- <td>geo</td>
537
- <td>A geographic point around which information is retrieved.</td>
538
- <td><tt>factual.geopulse(34.06021, -118.41828)</tt></td>
539
- </tr>
540
- <tr>
541
- <td>select</td>
542
- <td>What fields to include in the query results. Note that the order of fields will not necessarily be preserved in the resulting JSON response due to the nature of JSON hashes.</td>
543
- <td><tt>.select("commercial_density", "commercial_profile")</tt></td>
544
- </tr>
545
- </table>
546
-
547
- Available pulses include commercial_density, commercial_profile, income, race, hispanic, and age_by_gender.
548
-
549
- You can see a full list of available Factual pulses and their possible return values, as well as full documentation, in [the Factual API docs for Geopulse](http://developer.factual.com/display/docs/Places+API+-+Geopulse).
550
-
551
-
552
- # Reverse Geocoder
553
-
554
- The driver fully supports Factual's <a href="http://developer.factual.com/display/DOCS/Places+API+-+Reverse+Geocoder">Reverse Geocoder</a> feature, which returns the nearest valid address given a longitude and latitude.
555
-
556
- ## Simple Reverse Geocoder Example
557
-
558
- The <tt>geocode</tt> method fetches results based on the given point:
559
-
560
- ````ruby
561
- query = factual.geocode(34.06021, -118.41828)
562
- query.first
563
- ````
564
-
565
- ## All Top Level Reverse Geocoder Parameters
566
-
567
- <table>
568
- <tr>
569
- <th>Parameter</th>
570
- <th>Description</th>
571
- <th>Example</th>
572
- </tr>
573
- <tr>
574
- <td>geo</td>
575
- <td>A valid geographic point for which the closest address is retrieved.</td>
576
- <td><tt>factual.geocode(34.06021, -118.41828)</tt></td>
577
- </tr>
578
- </table>
579
-
580
-
581
- # World Geographies
582
-
583
- World Geographies contains administrative geographies (states, counties, countries), natural geographies (rivers, oceans, continents), and assorted geographic miscallaney. This resource is intended to complement Factual's Global Places and add utility to any geo-related content.
584
-
585
- Common use cases include:
586
-
587
- * Determining all cities within a state or all postal codes in a city
588
- * Creating a type-ahead placename lookup
589
- * Validating data against city, state, country and county names
590
- * A translation table to convert between the search key used by a user, i.e. '慕尼黑' or 'Munich' for the native 'München'
591
-
592
- You can use the <tt>query</tt> function to query World Geographies, supplying "world-geographies" as the table name.
593
-
594
- Examples:
595
-
596
- ````ruby
597
- # Get all towns surrounding Philadelphia
598
- query = factual.table("world-geographies").select("neighbors").filters(:factual_id => "08ca0f62-8f76-11e1-848f-cfd5bf3ef515")
599
- query.rows
600
- ````
601
-
602
- ````ruby
603
- # Find the town zipcode 95008 belongs to
604
- query = factual.table("world-geographies").filters(
605
- {"$and" => [ {:name => "95008"},
606
- {:country => "us"} ]} )
607
- query.rows
608
- ````
609
-
610
- ````ruby
611
- # Searching by placename, placetype, country and geographic hierarchy
612
- query = factual.table("world-geographies").filters(
613
- {"$and" => [ {:name => "wayne"},
614
- {:country => "us"},
615
- {:placetype => "locality"},
616
- {:ancestors => {:"$search" => "08666f5c-8f76-11e1-848f-cfd5bf3ef515"}} ]} )
617
-
618
- query.rows
619
- ````
620
-
621
- For more details about World Geographies, including schema, see [the main API docs for World Geographies](http://developer.factual.com/display/docs/World+Geographies).
622
-
623
-
624
- # Submit
625
-
626
- The driver fully supports Factual's Submit feature, which enables you to submit edits to existing rows and/or submit new rows of data in Factual tables. For information on deleting records, see Flag.
627
-
628
-
629
- ## Simple Submit Examples
630
-
631
- The <tt>submit</tt> method is a contribution to edit an existing row or add a new row:
632
-
633
- ````ruby
634
- # Submit a new row to Factual's global dataset
635
- factual.submit("global", "user123").values({"name" => "McDenny's", "address" => "1 Main St.", "locality" => "Bedrock", "region" => "BC"}).write
636
- ````
637
-
638
- ````ruby
639
- # Submit a correction to an existing row in Factual's places dataset.
640
- # Also set optional comment and reference
641
- submit = factual.submit("places", "user123").values({:name => "McDenny's"})
642
- submit = submit.comment("They changed their name last month").reference("http://www.example.com/mypage.html")
643
- submit.write
644
- ````
645
-
646
-
647
- ## Required Submit Parameters
648
-
649
- <table>
650
- <tr>
651
- <th>Parameter</th>
652
- <th>Description</th>
653
- <th>Example</th>
654
- </tr>
655
- <tr>
656
- <td>values</td>
657
- <td>A hash of names and values to be added to a Factual table</td>
658
- <td><tt>{"name" => "McDenny's", "address" => "1 Main St.", "locality" => "Bedrock", "region" => "BC"}</tt></td>
659
- </tr>
660
- <tr>
661
- <td>user</td>
662
- <td>An arbitrary token representing the user contributing the data.</td>
663
- <td><tt>user123</tt></td>
664
- </tr>
665
- </table>
666
-
667
- ## Optional Submit Parameters
668
-
669
- <table>
670
- <tr>
671
- <th>Parameter</th>
672
- <th>Description</th>
673
- <th>Example</th>
674
- </tr>
675
- <tr>
676
- <td>factual_id</td>
677
- <td>The factual_id of the row to which you want to submit a correction</td>
678
- <td><tt>.factual_id("0545b03f-9413-44ed-8882-3a9a461848da")</tt></td>
679
- </tr>
680
- <tr>
681
- <td>comment</td>
682
- <td>Any english text comment that may help explain your corrections.</td>
683
- <td><tt>.comment("They changed their name last month")</tt></td>
684
- </tr>
685
- <tr>
686
- <td>reference</td>
687
- <td>A reference to a URL, title, person, etc. that is the source of this data.</td>
688
- <td><tt>.reference("http://www.example.com/mypage.html")</tt></td>
689
- </tr>
690
- </table>
691
-
692
-
693
- # Schema
694
-
695
- You can query Factual for the detailed schema of any specific table in Factual. For example:
696
-
697
- ````ruby
698
- # Returns a hash of metadata for the table named "global", including an array of fields
699
- factual.table("global").schema
700
- ````
701
-
702
- # Raw Read Queries
703
-
704
- You can perform any read queries documented in the Factual API using the
705
- raw read query. Just supply the full path (including the first
706
- forward-slash) and the request will be made using your OAuth token:
707
-
708
- ````ruby
709
- # Find rows in the restaurant database whose name begins with "Star" and return both the data and a total count of the matched rows
710
- factual.read('/t/restaurants-us?filters={"name":{"$bw":"Star"}}&include_count=true')
711
- ````
712
-
713
- # Monetize
714
-
715
- The <a href="http://developer.factual.com/display/docs/Places+API+-+Monetize">Monetize API</a> enables you to find deals for places in Factual's Global Places database.
716
-
717
- ````ruby
718
- query = @factual.monetize.search('sushi').filters(:place_postcode => 90067)
719
- query.rows
720
- ````
721
-
722
- # Multi
723
-
724
- The <a href="http://developer.factual.com/display/docs/Core+API+-+Multi">multi API call</a> enables making multiple API GET requests on the same connection. Multi supports the read, crosswalk, resolve, facets, geocode and geopulse API calls.
725
-
726
- ````ruby
727
- places_query = @factual.table("places").search('sushi').filters(:postcode => 90067)
728
- geocode_query = @factual.geocode(34.06021,-118.41828)
729
-
730
- responses = @factual.multi(
731
- :nearby_sushi => places_query,
732
- :factual_inc => geocode_query)
733
-
734
- responses[:nearby_sushi].first
735
- responses[:factual_inc].first
736
- ````
737
-
738
- # Debug Mode
739
-
740
- To see the query paths generated by the driver you can use it in debug mode by passing :debug => true as
741
- the third argument of the Factual constructor. Here is an example in irb:
742
-
743
-
744
- ````ruby
745
- > factual = Factual.new(key, secret, :debug => true)
746
- > factual.table("places").filters("name" => {"$bw" => "starbucks"})
747
- Request: http://api.v3.factual.com/t/places?filters=%7B%22name%22%3A%7B%22%24bw%22%3A%22starbucks%22%7D%7D
748
- => [{"address"=>"11290 Donner Pass Rd", "category"=>"Food & Beverage > Cafes, Coffee Houses & Tea Houses", ...
749
- ````
750
-
751
147
  # Where to Get Help
752
148
 
753
149
  If you think you've identified a specific bug in this driver, please file an issue in the github repo. Please be as specific as you can, including:
@@ -758,3 +154,6 @@ If you think you've identified a specific bug in this driver, please file an iss
758
154
  * Detailed stack trace and/or line numbers
759
155
 
760
156
  If you are having any other kind of issue, such as unexpected data or strange behaviour from Factual's API (or you're just not sure WHAT'S going on), please contact us through [GetSatisfaction](http://support.factual.com/factual).
157
+
158
+ # Ruby Driver Wiki
159
+ https://github.com/Factual/factual-ruby-driver/wiki
data/lib/factual.rb CHANGED
@@ -2,6 +2,7 @@ require 'oauth'
2
2
  require 'factual/api'
3
3
  require 'factual/query/table'
4
4
  require 'factual/query/facets'
5
+ require 'factual/query/match'
5
6
  require 'factual/query/resolve'
6
7
  require 'factual/query/crosswalk'
7
8
  require 'factual/query/monetize'
@@ -28,9 +29,10 @@ class Factual
28
29
 
29
30
  def crosswalk(namespace_id, namespace = nil)
30
31
  if namespace
31
- Query::Crosswalk.new(@api, :namespace_id => namespace_id, :namespace => namespace)
32
+ raise "DEPRECATED. For more information, please visit http://developer.factual.com/display/docs/Places+API+-+Crosswalk"
33
+ Query::Crosswalk.new(@api, :filters => {:namespace_id => namespace_id, :namespace => namespace})
32
34
  else
33
- Query::Crosswalk.new(@api, :factual_id => namespace_id)
35
+ Query::Crosswalk.new(@api, :filters => {:factual_id => namespace_id})
34
36
  end
35
37
  end
36
38
 
@@ -38,6 +40,10 @@ class Factual
38
40
  Query::Monetize.new(@api)
39
41
  end
40
42
 
43
+ def match(values)
44
+ Query::Match.new(@api, :values => values)
45
+ end
46
+
41
47
  def resolve(values)
42
48
  Query::Resolve.new(@api, :values => values)
43
49
  end
@@ -50,8 +56,16 @@ class Factual
50
56
  Query::Geopulse.new(@api, lat, lng)
51
57
  end
52
58
 
53
- def read(path)
54
- @api.raw_read(path)
59
+ def get(path, query={})
60
+ @api.raw_get(path, query)
61
+ end
62
+
63
+ def post(path, body={})
64
+ @api.raw_post(path, body)
65
+ end
66
+
67
+ def diffs(view, params = {})
68
+ @api.diffs(view, params)
55
69
  end
56
70
 
57
71
  def multi(queries)
data/lib/factual/api.rb CHANGED
@@ -3,7 +3,7 @@ require 'cgi'
3
3
 
4
4
  class Factual
5
5
  class API
6
- VERSION = "1.2"
6
+ VERSION = "1.3"
7
7
  API_V3_HOST = "api.v3.factual.com"
8
8
  DRIVER_VERSION_TAG = "factual-ruby-driver-v" + VERSION
9
9
  PARAM_ALIASES = { :search => :q, :sort_asc => :sort }
@@ -29,11 +29,35 @@ class Factual
29
29
  handle_request(:schema, query.path, query.params)["view"]
30
30
  end
31
31
 
32
- def raw_read(path)
33
- payload = JSON.parse(make_request("http://#{@host}#{path}").body)
32
+ def raw_get(path, query)
33
+ path = '/' + path unless path =~ /^\//
34
+ url = "http://#{@host}#{path}?#{query_string(query)}"
35
+ resp = make_request(url)
36
+ payload = JSON.parse(resp.body)
34
37
  handle_payload(payload)
35
38
  end
36
39
 
40
+ def raw_post(path, body)
41
+ path = '/' + path unless path =~ /^\//
42
+ url = "http://#{@host}#{path}"
43
+ resp = make_request(url, query_string(body), :post)
44
+ payload = JSON.parse(resp.body)
45
+ handle_payload(payload)
46
+ end
47
+
48
+ def diffs(view_id, params = {})
49
+ start_date = (params[:start] || params["start"] || 0).to_i * 1000
50
+ end_date = (params[:end] || params["end"] || Time.now).to_i * 1000
51
+
52
+ path = "/t/#{view_id}/diffs?start=#{start_date}&end=#{end_date}"
53
+ url = "http://#{@host}#{path}"
54
+ resp = make_request(url)
55
+
56
+ resp.body.split("\n").collect do |rowJson|
57
+ row = JSON.parse(rowJson)
58
+ end
59
+ end
60
+
37
61
  def full_path(action, path, params)
38
62
  fp = "/#{path}"
39
63
  fp += "/#{action}" unless action == :read
@@ -4,12 +4,24 @@ class Factual
4
4
  module Query
5
5
  class Crosswalk < Base
6
6
  def initialize(api, params = {})
7
- @path = "places/crosswalk"
7
+ @path = "t/crosswalk"
8
8
  @action = :read
9
9
  super(api, params)
10
10
  end
11
11
 
12
- [:factual_id, :only, :limit, :include_count].each do |param|
12
+ def only(*namespaces)
13
+ filters = @params[:filters] ? @params[:filters].dup : {}
14
+
15
+ if (namespaces.length == 1)
16
+ filters.merge!(:namespace => namespaces.first)
17
+ else
18
+ filters.merge!(:namespace => {"$in" => namespaces})
19
+ end
20
+
21
+ self.class.new(@api, @params.merge(:filters => filters))
22
+ end
23
+
24
+ [:limit, :include_count].each do |param|
13
25
  define_method(param) do |*args|
14
26
  self.class.new(@api, @params.merge(param => form_value(args)))
15
27
  end
@@ -0,0 +1,19 @@
1
+ require 'factual/query/base'
2
+
3
+ class Factual
4
+ module Query
5
+ class Match < Base
6
+ def initialize(api, params = {})
7
+ @path = "places/match"
8
+ @action = :read
9
+ super(api, params)
10
+ end
11
+
12
+ [:values].each do |param|
13
+ define_method(param) do |*args|
14
+ self.class.new(@api, @params.merge(param => form_value(args)))
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,62 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: factual-api
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.3'
4
5
  prerelease:
5
- version: "1.2"
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Rudiger Lippert
9
9
  - Forrest Cao
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
-
14
- date: 2012-06-21 00:00:00 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
13
+ date: 2012-08-08 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
17
16
  name: oauth
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
20
18
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
24
22
  version: 0.4.4
25
23
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: json
29
24
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 0.4.4
31
+ - !ruby/object:Gem::Dependency
32
+ name: json
33
+ requirement: !ruby/object:Gem::Requirement
31
34
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
35
38
  version: 1.2.0
36
39
  type: :runtime
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: rspec
40
40
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
42
42
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: "0"
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 1.2.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
47
55
  type: :development
48
- version_requirements: *id003
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
49
63
  description: Factual's official Ruby driver for the Factual public API.
50
- email:
64
+ email:
51
65
  - rudy@factual.com
52
66
  - forrest@factual.com
53
67
  executables: []
54
-
55
68
  extensions: []
56
-
57
69
  extra_rdoc_files: []
58
-
59
- files:
70
+ files:
60
71
  - lib/factual/api.rb
61
72
  - lib/factual/multi.rb
62
73
  - lib/factual/query/base.rb
@@ -64,6 +75,7 @@ files:
64
75
  - lib/factual/query/facets.rb
65
76
  - lib/factual/query/geocode.rb
66
77
  - lib/factual/query/geopulse.rb
78
+ - lib/factual/query/match.rb
67
79
  - lib/factual/query/monetize.rb
68
80
  - lib/factual/query/resolve.rb
69
81
  - lib/factual/query/table.rb
@@ -75,30 +87,26 @@ files:
75
87
  - CHANGELOG.md
76
88
  homepage: http://github.com/Factual/factual-ruby-driver
77
89
  licenses: []
78
-
79
90
  post_install_message:
80
91
  rdoc_options: []
81
-
82
- require_paths:
92
+ require_paths:
83
93
  - lib
84
- required_ruby_version: !ruby/object:Gem::Requirement
94
+ required_ruby_version: !ruby/object:Gem::Requirement
85
95
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
89
99
  version: 1.8.6
90
- required_rubygems_version: !ruby/object:Gem::Requirement
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
101
  none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
95
105
  version: 1.3.6
96
106
  requirements: []
97
-
98
107
  rubyforge_project:
99
108
  rubygems_version: 1.8.24
100
109
  signing_key:
101
110
  specification_version: 3
102
111
  summary: Ruby driver for Factual
103
112
  test_files: []
104
-