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