atduskgreg-dm-fql-adapter 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/History.txt +4 -0
- data/Manifest.txt +15 -0
- data/PostInstall.txt +3 -0
- data/README.rdoc +14 -0
- data/Rakefile +27 -0
- data/example_app.rb +27 -0
- data/lib/dm-fql-adapter.rb +49 -0
- data/lib/dm-fql-adapter/facemask.rb +80 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/dm-fql-adapter_spec.rb +29 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/rspec.rake +21 -0
- metadata +80 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
example_app.rb
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
PostInstall.txt
|
5
|
+
README.rdoc
|
6
|
+
Rakefile
|
7
|
+
lib/dm-fql-adapter.rb
|
8
|
+
lib/dm-fql-adapter/facemask.rb
|
9
|
+
script/console
|
10
|
+
script/destroy
|
11
|
+
script/generate
|
12
|
+
spec/dm-fql-adapter_spec.rb
|
13
|
+
spec/spec.opts
|
14
|
+
spec/spec_helper.rb
|
15
|
+
tasks/rspec.rake
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
An FQL Adapter for DataMapper. Read-only.
|
2
|
+
|
3
|
+
FQL is the "Facebook Query Language": an API that allows you to send SQL-ish strings along with session information and API credentials to Facebook in order to query for information about users, comments, stream activity and more. See the FQL docs here: http://wiki.developers.facebook.com/index.php/FQL
|
4
|
+
|
5
|
+
For usage, see example_app.rb.
|
6
|
+
|
7
|
+
As of 7/16/09, this only ran on the DataMapper Next branch (i.e. 0.10). For details on how to upgrade to that branch, see here: http://sick.snusnu.info/2009/06/03/migrating-to-datamapper-0100/
|
8
|
+
|
9
|
+
At some point, I will probably factor this into a gem. You know, if people bug me.
|
10
|
+
|
11
|
+
Also, this repo includes Facemask, a more straightforward approach to querying the Facebook API than some of the more complex libs out there.
|
12
|
+
|
13
|
+
-- Greg Borenstein
|
14
|
+
7/16/09 in Portland, OR
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
require './lib/dm-fql-adapter'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'dm-fql-adapter' do
|
14
|
+
self.developer 'Greg Borenstein', 'greg.borenstein@gmail.com'
|
15
|
+
self.version = "0.0.1"
|
16
|
+
self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
17
|
+
self.summary = "FQL Adapter for DataMapper"
|
18
|
+
# self.extra_deps = [['activesupport','>= 2.0.2']]
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'newgem/tasks'
|
23
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
24
|
+
|
25
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
26
|
+
# remove_task :default
|
27
|
+
# task :default => [:spec, :features]
|
data/example_app.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'dm-core'
|
4
|
+
require 'dm-fql-adapter'
|
5
|
+
|
6
|
+
class User
|
7
|
+
include DataMapper::Resource
|
8
|
+
|
9
|
+
# NB: If you don't pick a key DM will act weird
|
10
|
+
property :uid, Integer, :key => true
|
11
|
+
property :name, String
|
12
|
+
property :sex, String
|
13
|
+
property :pic_big, String
|
14
|
+
end
|
15
|
+
|
16
|
+
post "/" do
|
17
|
+
adapter = DataMapper.setup(:default,
|
18
|
+
{:adapter => 'fql',
|
19
|
+
:api_key => "YOUR API KEY",
|
20
|
+
:secret_key => "YOUR SECRET KEY",
|
21
|
+
:session_key => params[:fb_sig_session_key]
|
22
|
+
}
|
23
|
+
)
|
24
|
+
|
25
|
+
user = User.get(546502145)
|
26
|
+
"#{user.name} - #{user.sex} <img src=\"#{user.pic_big}\" />"
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'dm-core'
|
5
|
+
require DataMapper.root / 'lib' / 'dm-core' / 'adapters' / 'abstract_adapter'
|
6
|
+
require DataMapper.root / 'lib' / 'dm-core' / 'adapters' / 'data_objects_adapter'
|
7
|
+
require File.expand_path(File.dirname(__FILE__)) + '/dm-fql-adapter/facemask.rb'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
module DataMapper
|
11
|
+
module Adapters
|
12
|
+
|
13
|
+
class DataObjectsAdapter
|
14
|
+
module SQL
|
15
|
+
def quote_name(name)
|
16
|
+
name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class FqlAdapter < AbstractAdapter
|
22
|
+
|
23
|
+
include DataMapper::Adapters::DataObjectsAdapter::SQL
|
24
|
+
|
25
|
+
def initialize(name, options={})
|
26
|
+
super
|
27
|
+
|
28
|
+
self.resource_naming_convention = DataMapper::NamingConventions::Resource::Underscored
|
29
|
+
|
30
|
+
@facebook = Facemask.new :api_key => options[:api_key],
|
31
|
+
:secret_key => options[:secret_key],
|
32
|
+
:session_key => options[:session_key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def read(query)
|
36
|
+
q = select_statement(query).to_s
|
37
|
+
|
38
|
+
# hack around the mysterious '?'
|
39
|
+
q = q.gsub(/\?(\w*)/){"\"#{$1}\""}
|
40
|
+
|
41
|
+
results = @facebook.find_by_fql(q)
|
42
|
+
results = JSON.parse(results)
|
43
|
+
query.filter_records(results)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end # class FqlAdapter
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'md5'
|
2
|
+
require 'json'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rest_client'
|
5
|
+
|
6
|
+
class Facemask
|
7
|
+
class FaceFail < StandardError; end
|
8
|
+
|
9
|
+
attr_accessor :session_key, :api_key, :secret_key
|
10
|
+
|
11
|
+
def initialize opts={}
|
12
|
+
@api_key = opts[:api_key]
|
13
|
+
@secret_key = opts[:secret_key]
|
14
|
+
@session_key = opts[:session_key]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Execute raw FQL and return the results in JSON
|
18
|
+
def find_by_fql(query)
|
19
|
+
post('facebook.fql.query', :query => query, :format => "json")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends a templatized feed for the given bundle_id with the given data hash.
|
23
|
+
def publish_user_feed(bundle_id, data)
|
24
|
+
post("facebook.feed.publishUserAction", {:template_bundle_id=> bundle_id,
|
25
|
+
:template_data => data.to_json} )
|
26
|
+
end
|
27
|
+
|
28
|
+
def publish_page_feed(data)
|
29
|
+
data[:title_template] ||= "{actor} Item"
|
30
|
+
post("facebook.feed.publishTemplatizedAction", data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def post(method, params)
|
34
|
+
params.merge! generate_params(method)
|
35
|
+
params.merge! :sig => signature_for(params)
|
36
|
+
Facemask.execute(params)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
def self.execute(params)
|
42
|
+
begin
|
43
|
+
puts "[FBOOK REQUEST] #{params.inspect}"
|
44
|
+
result = RestClient.post("http://api.facebook.com/restserver.php", params)
|
45
|
+
rescue Errno::ECONNRESET, EOFError
|
46
|
+
if attempt == 0
|
47
|
+
attempt += 1
|
48
|
+
puts "Failed once, retrying..."
|
49
|
+
retry
|
50
|
+
end
|
51
|
+
rescue Exception => e
|
52
|
+
raise FaceFail.new(e)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def signature_for(params)
|
57
|
+
raw_string = params.inject([]) do |collection, pair|
|
58
|
+
collection << pair.join("=")
|
59
|
+
collection
|
60
|
+
end.sort.join
|
61
|
+
puts "ABOUT TO HEX"
|
62
|
+
puts raw_string
|
63
|
+
puts self.secret_key
|
64
|
+
Digest::MD5.hexdigest([raw_string, self.secret_key].join)
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_params(method)
|
68
|
+
result = {}
|
69
|
+
if session_key
|
70
|
+
result[:session_key] = session_key
|
71
|
+
end
|
72
|
+
|
73
|
+
result[:method] = method
|
74
|
+
result[:api_key] = api_key
|
75
|
+
result[:call_id] = Time.now.to_f.to_s
|
76
|
+
result[:v] = "1.0"
|
77
|
+
|
78
|
+
result
|
79
|
+
end
|
80
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/dm-fql-adapter.rb'}"
|
9
|
+
puts "Loading dm-fql-adapter gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'dm-core'
|
4
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../lib/dm-fql-adapter.rb'
|
5
|
+
|
6
|
+
class User
|
7
|
+
include DataMapper::Resource
|
8
|
+
|
9
|
+
property :uid, Integer, :key => true # !important
|
10
|
+
property :name, String
|
11
|
+
property :sex, String
|
12
|
+
property :pic_big, String
|
13
|
+
end
|
14
|
+
|
15
|
+
describe DataMapper::Adapters::FqlAdapter do
|
16
|
+
before :all do
|
17
|
+
Facemask.stub!(:new).and_return(@f = mock('Facemask'))
|
18
|
+
|
19
|
+
@adapter = DataMapper.setup(:default, :adapter => 'fql',
|
20
|
+
:api_key => 'api',
|
21
|
+
:secret_key => 'secret')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should generate the correct FQL" do
|
25
|
+
@f.should_receive(:find_by_fql).with("SELECT uid, name, sex, pic_big FROM user WHERE uid = \"12345\"").and_return('[{"name":"Cyndy Glucksman","pic_big":"http:\/\/profile.ak.fbcdn.net\/v227\/1454\/108\/n500409376_1710.jpg","sex":"female","uid":500409376}]')
|
26
|
+
User.get(12345)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
require 'spec'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run the specs under spec/models"
|
18
|
+
Spec::Rake::SpecTask.new do |t|
|
19
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atduskgreg-dm-fql-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Greg Borenstein
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-16 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.3.2
|
24
|
+
version:
|
25
|
+
description: ""
|
26
|
+
email:
|
27
|
+
- greg.borenstein@gmail.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- History.txt
|
34
|
+
- Manifest.txt
|
35
|
+
- PostInstall.txt
|
36
|
+
files:
|
37
|
+
- example_app.rb
|
38
|
+
- History.txt
|
39
|
+
- Manifest.txt
|
40
|
+
- PostInstall.txt
|
41
|
+
- README.rdoc
|
42
|
+
- Rakefile
|
43
|
+
- lib/dm-fql-adapter.rb
|
44
|
+
- lib/dm-fql-adapter/facemask.rb
|
45
|
+
- script/console
|
46
|
+
- script/destroy
|
47
|
+
- script/generate
|
48
|
+
- spec/dm-fql-adapter_spec.rb
|
49
|
+
- spec/spec.opts
|
50
|
+
- spec/spec_helper.rb
|
51
|
+
- tasks/rspec.rake
|
52
|
+
has_rdoc: true
|
53
|
+
homepage:
|
54
|
+
post_install_message: PostInstall.txt
|
55
|
+
rdoc_options:
|
56
|
+
- --main
|
57
|
+
- README.rdoc
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project: dm-fql-adapter
|
75
|
+
rubygems_version: 1.2.0
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: FQL Adapter for DataMapper
|
79
|
+
test_files: []
|
80
|
+
|