ruby-factual 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.
- data/README.md +15 -0
- data/lib/factual.rb +141 -0
- metadata +74 -0
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
## Sample Usage
|
2
|
+
> require 'ruby-factual'
|
3
|
+
>
|
4
|
+
> api = Factual::Api.new(:api_key => '<YOUR_FACTUAL_API_KEY>', :version => 2)
|
5
|
+
>
|
6
|
+
> table = api.get_table('g9R1u2')
|
7
|
+
> puts table.name
|
8
|
+
>
|
9
|
+
> table.read(:state => 'hawaii').each do |row|
|
10
|
+
> fact = row['test_field']
|
11
|
+
> puts fact.value
|
12
|
+
> if fact.input('the corrected value', :source => 'source', :comment => 'comment')
|
13
|
+
> puts 'inputted'
|
14
|
+
> end
|
15
|
+
> end
|
data/lib/factual.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'curl'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Factual
|
6
|
+
class Api
|
7
|
+
def initialize(opts)
|
8
|
+
@api_key = opts[:api_key]
|
9
|
+
@version = opts[:version]
|
10
|
+
@adapter = Adapter.new(@api_key, @version)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_table(table_key)
|
14
|
+
Table.new(table_key, @adapter)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Table
|
19
|
+
attr_accessor :name, :description, :rating, :source, :creator, :total_row_count, :created_at, :updated_at, :fields
|
20
|
+
def initialize(table_key, adapter)
|
21
|
+
@table_key = table_key
|
22
|
+
@adapter = adapter
|
23
|
+
@schema = adapter.schema(@table_key)
|
24
|
+
|
25
|
+
[:name, :description, :rating, :source, :creator, :total_row_count, :created_at, :updated_at, :fields].each do |attr|
|
26
|
+
self.send("#{attr}=", @schema[attr.to_s])
|
27
|
+
end
|
28
|
+
|
29
|
+
@fields.each do |f|
|
30
|
+
fid = f['id']
|
31
|
+
f['field_ref'] = @schema["fieldRefs"][fid.to_s]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def read(filters=nil)
|
36
|
+
filters_query = "filters=" + filters.to_json if filters
|
37
|
+
resp = @adapter.api_call("/tables/#{@table_key}/read.jsaml?limit=999&" + filters_query.to_s)
|
38
|
+
|
39
|
+
@total_rows = resp["response"]["total_rows"]
|
40
|
+
rows = resp["response"]["data"]
|
41
|
+
|
42
|
+
# TODO iterator
|
43
|
+
rows.collect do |row_data|
|
44
|
+
Row.new(@adapter, @table_key, @fields, row_data)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Row
|
50
|
+
attr_accessor :subject_key, :subject
|
51
|
+
|
52
|
+
def initialize(adapter, table_key, fields, row_data)
|
53
|
+
@subject_key = row_data[0]
|
54
|
+
@fields = fields
|
55
|
+
@table_key = table_key
|
56
|
+
@adapter = adapter
|
57
|
+
|
58
|
+
@subject = []
|
59
|
+
@fields.each_with_index do |f, idx|
|
60
|
+
next unless f["isPrimary"]
|
61
|
+
@subject << row_data[idx+1]
|
62
|
+
end
|
63
|
+
|
64
|
+
@facts_hash = {}
|
65
|
+
@fields.each_with_index do |f, idx|
|
66
|
+
next if f["isPrimary"]
|
67
|
+
@facts_hash[f["field_ref"]] = Fact.new(@adapter, @table_key, @subject_key, f['id'], row_data[idx+1])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def [](field_ref)
|
72
|
+
@facts_hash[field_ref]
|
73
|
+
end
|
74
|
+
|
75
|
+
# TODO
|
76
|
+
def input(values)
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Fact
|
82
|
+
attr_accessor :value, :subject_key, :field_id, :adapter
|
83
|
+
|
84
|
+
def initialize(adapter, table_key, subject_key, field_id, value)
|
85
|
+
@value = value
|
86
|
+
@subject_key = subject_key
|
87
|
+
@table_key = table_key
|
88
|
+
@field_id = field_id
|
89
|
+
@adapter = adapter
|
90
|
+
end
|
91
|
+
|
92
|
+
def input(value, opts)
|
93
|
+
hash = opts.merge({
|
94
|
+
:subjectKey => @subject_key,
|
95
|
+
:fieldId => @field_id,
|
96
|
+
:value => value
|
97
|
+
})
|
98
|
+
query_string = hash.to_a.collect{ |k,v| URI.escape(k.to_s) + '=' + URI.escape(v.to_s) }.join('&')
|
99
|
+
|
100
|
+
@adapter.api_call("/tables/#{@table_key}/input.js?" + query_string)
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
@value
|
106
|
+
end
|
107
|
+
|
108
|
+
def inspect
|
109
|
+
@value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
class Adapter
|
115
|
+
CONNECT_TIMEOUT = 30
|
116
|
+
|
117
|
+
def initialize(api_key, version)
|
118
|
+
@base = "http://api.factual.com/v#{version}/#{api_key}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def api_call(url)
|
122
|
+
api_url = @base + url
|
123
|
+
curl = Curl::Easy.new(api_url) do |c|
|
124
|
+
c.connect_timeout = CONNECT_TIMEOUT
|
125
|
+
end
|
126
|
+
curl.http_get
|
127
|
+
|
128
|
+
resp = JSON.parse(curl.body_str)
|
129
|
+
raise ApiError.new(resp["error"]) if resp["status"] == "error"
|
130
|
+
return resp
|
131
|
+
end
|
132
|
+
|
133
|
+
def schema(table_key)
|
134
|
+
resp = api_call("/tables/#{table_key}/schema.json")
|
135
|
+
return resp["schema"]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class ApiError < Exception
|
140
|
+
end
|
141
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-factual
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Forrest Cao
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-09-14 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: ""
|
23
|
+
email: forrest@factual.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.md
|
30
|
+
files:
|
31
|
+
- README.md
|
32
|
+
- lib/factual.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/forrestc/ruby-factual
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --line-numbers
|
40
|
+
- --inline-source
|
41
|
+
- --title
|
42
|
+
- ruby-factual
|
43
|
+
- --main
|
44
|
+
- README.md
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
hash: 3
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 11
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 2
|
65
|
+
version: "1.2"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.7
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: ""
|
73
|
+
test_files: []
|
74
|
+
|