ruby-factual 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +15 -0
  2. data/lib/factual.rb +141 -0
  3. 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
+