rfql 0.1.alpha
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.tar.gz.sig +2 -0
- data/CHANGELOG +1 -0
- data/LICENSE +21 -0
- data/Manifest +20 -0
- data/README.rdoc +14 -0
- data/Rakefile +19 -0
- data/lib/rfql.rb +12 -0
- data/lib/rfql/core_ext/object/blank.rb +10 -0
- data/lib/rfql/query.rb +29 -0
- data/lib/rfql/query/methods.rb +148 -0
- data/lib/rfql/query/quoting.rb +39 -0
- data/lib/rfql/request.rb +92 -0
- data/lib/rfql/request/delegations.rb +11 -0
- data/lib/rfql/response.rb +29 -0
- data/lib/rfql/response/fql_error.rb +10 -0
- data/lib/rfql/response/json.rb +22 -0
- data/lib/rfql/response/json/parsed.rb +26 -0
- data/lib/rfql/response/json/parsed/error.rb +23 -0
- data/lib/rfql/response/json/parsed/null.rb +9 -0
- data/lib/rfql/response/json/parsed/records.rb +15 -0
- data/lib/rfql/response/json/raw.rb +14 -0
- data/rfql.gemspec +31 -0
- metadata +131 -0
- metadata.gz.sig +3 -0
data.tar.gz.sig
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1.alpha. WIP
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Maurizio De Santis <desantis.maurizio at gmail.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
LICENSE
|
3
|
+
Manifest
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
lib/rfql.rb
|
7
|
+
lib/rfql/core_ext/object/blank.rb
|
8
|
+
lib/rfql/query.rb
|
9
|
+
lib/rfql/query/methods.rb
|
10
|
+
lib/rfql/query/quoting.rb
|
11
|
+
lib/rfql/request.rb
|
12
|
+
lib/rfql/request/delegations.rb
|
13
|
+
lib/rfql/response.rb
|
14
|
+
lib/rfql/response/fql_error.rb
|
15
|
+
lib/rfql/response/json.rb
|
16
|
+
lib/rfql/response/json/parsed.rb
|
17
|
+
lib/rfql/response/json/parsed/error.rb
|
18
|
+
lib/rfql/response/json/parsed/null.rb
|
19
|
+
lib/rfql/response/json/parsed/records.rb
|
20
|
+
lib/rfql/response/json/raw.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
= RFQL - Ruby interface for Facebook Query Language
|
2
|
+
|
3
|
+
Work In Progress
|
4
|
+
|
5
|
+
== TODO
|
6
|
+
|
7
|
+
* Implement XML fetching
|
8
|
+
* A bit of refactoring (commenting, move thing up and down and all around...)
|
9
|
+
* Have I implemented errors managing before??? Who knows!
|
10
|
+
* ADD TESTS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
11
|
+
|
12
|
+
== License
|
13
|
+
|
14
|
+
MIT (see LICENSE)
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'psych'
|
2
|
+
require 'echoe'
|
3
|
+
|
4
|
+
Echoe.new("rfql") do |p|
|
5
|
+
p.project = 'ProGNOMmers'
|
6
|
+
p.author = "De Santis Maurizio"
|
7
|
+
p.email = 'desantis.maurizio@gmail.com'
|
8
|
+
p.description = "RFQL - Ruby interface for Facebook Query Language"
|
9
|
+
p.summary = "It lets you use ORM-style code for fetching data from Facebook through the Facebook Query Language"
|
10
|
+
end
|
11
|
+
|
12
|
+
#task :default => :irb
|
13
|
+
task :irb do
|
14
|
+
$LOAD_PATH << "#{Dir.pwd}/lib"
|
15
|
+
require 'rfql'
|
16
|
+
require 'irb'
|
17
|
+
ARGV.clear
|
18
|
+
IRB.start
|
19
|
+
end
|
data/lib/rfql.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rfql/query'
|
2
|
+
require 'rfql/request'
|
3
|
+
module RFQL
|
4
|
+
VERSION = '0.1.alpha'
|
5
|
+
FQLURL = "https://api.facebook.com/method/fql.query"
|
6
|
+
def self.request(obj = nil)
|
7
|
+
RFQL::Request.new(obj)
|
8
|
+
end
|
9
|
+
def self.query(obj = nil)
|
10
|
+
RFQL::Query.new(obj)
|
11
|
+
end
|
12
|
+
end
|
data/lib/rfql/query.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module RFQL
|
2
|
+
class Query < String
|
3
|
+
VALID_QUERY_METHODS = [:select, :from, :where, :order, :limit]
|
4
|
+
def initialize(obj = '')
|
5
|
+
if obj.is_a?(Hash)
|
6
|
+
obj.each do |k, v|
|
7
|
+
if VALID_QUERY_METHODS.include?(k)
|
8
|
+
self.send(k, v)
|
9
|
+
else
|
10
|
+
raise ArgumentError, "hash keys expected to be included in #{VALID_QUERY_METHODS}; got #{k.inspect}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
super(to_s)
|
14
|
+
else
|
15
|
+
@query = obj.to_s
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def to_s
|
19
|
+
@query.present? ? @query.to_s : compose_query
|
20
|
+
end
|
21
|
+
def inspect
|
22
|
+
to_s.inspect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# This is here in order to avoid conflicts between the RFQL::Query declarations
|
28
|
+
require 'rfql/query/methods'
|
29
|
+
RFQL::Query.send(:include, RFQL::Query::Methods)
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'rfql/query/quoting'
|
2
|
+
module RFQL::Query::Methods
|
3
|
+
include RFQL::Query::Quoting
|
4
|
+
|
5
|
+
def query(query = nil)
|
6
|
+
@query = query
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def select(*fields)
|
11
|
+
@select =
|
12
|
+
if fields.blank?
|
13
|
+
nil
|
14
|
+
else
|
15
|
+
fields.flatten!; fields.uniq!; fields.join(', ')
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
def select?; @select; end
|
20
|
+
|
21
|
+
def from(from = nil)
|
22
|
+
@from = from
|
23
|
+
self
|
24
|
+
end
|
25
|
+
def from?; @from; end
|
26
|
+
|
27
|
+
def where(where = nil)
|
28
|
+
@where =
|
29
|
+
case where
|
30
|
+
when String then where
|
31
|
+
when Array then sanitize_sql_array(where)
|
32
|
+
when Hash then sanitize_sql_hash_for_conditions(where)
|
33
|
+
when NilClass then nil
|
34
|
+
else raise ArgumentError, "only strings, hashes or arrays can be converted to sql conditions"
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
def where?; @where; end
|
39
|
+
|
40
|
+
def order(order = nil)
|
41
|
+
@order = order
|
42
|
+
self
|
43
|
+
end
|
44
|
+
def order?; @order; end
|
45
|
+
|
46
|
+
def limit(limit = nil)
|
47
|
+
@limit = limit
|
48
|
+
self
|
49
|
+
end
|
50
|
+
def limit?; @limit; end
|
51
|
+
|
52
|
+
private
|
53
|
+
def compose_query
|
54
|
+
[].tap do |arr|
|
55
|
+
arr << "SELECT #{@select}" if @select.present?
|
56
|
+
arr << "FROM #{@from}" if @from.present?
|
57
|
+
arr << "WHERE #{@where}" if @where.present?
|
58
|
+
arr << "ORDER BY #{@order}" if @order.present?
|
59
|
+
arr << "LIMIT #{@limit}" if @limit.present?
|
60
|
+
end.join(' ')
|
61
|
+
end
|
62
|
+
|
63
|
+
def sanitize_sql_hash_for_conditions(attrs)
|
64
|
+
conditions = attrs.map do |attr, value|
|
65
|
+
attr = attr.to_s
|
66
|
+
attribute_condition(attr, value)
|
67
|
+
end.join(' AND ')
|
68
|
+
|
69
|
+
replace_bind_variables(conditions, expand_range_bind_variables(attrs.values))
|
70
|
+
end
|
71
|
+
|
72
|
+
def attribute_condition(quoted_column_name, argument)
|
73
|
+
case argument
|
74
|
+
when nil then "#{quoted_column_name} IS ?"
|
75
|
+
when Array then "#{quoted_column_name} IN (?)"
|
76
|
+
when Range then if argument.exclude_end?
|
77
|
+
"#{quoted_column_name} >= ? AND #{quoted_column_name} < ?"
|
78
|
+
else
|
79
|
+
"#{quoted_column_name} BETWEEN ? AND ?"
|
80
|
+
end
|
81
|
+
else "#{quoted_column_name} = ?"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def expand_range_bind_variables(bind_vars)
|
86
|
+
expanded = []
|
87
|
+
|
88
|
+
bind_vars.each do |var|
|
89
|
+
next if var.is_a?(Hash)
|
90
|
+
|
91
|
+
if var.is_a?(Range)
|
92
|
+
expanded << var.first
|
93
|
+
expanded << var.last
|
94
|
+
else
|
95
|
+
expanded << var
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
expanded
|
100
|
+
end
|
101
|
+
|
102
|
+
def sanitize_sql_array(ary)
|
103
|
+
statement, *values = ary
|
104
|
+
if values.first.is_a?(Hash) and statement =~ /:\w+/
|
105
|
+
replace_named_bind_variables(statement, values.first)
|
106
|
+
elsif statement.include?('?')
|
107
|
+
replace_bind_variables(statement, values)
|
108
|
+
else
|
109
|
+
statement % values.collect { |value| quote_string(value.to_s) }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def replace_named_bind_variables(statement, bind_vars)
|
114
|
+
statement.gsub(/(:?):([a-zA-Z]\w*)/) do
|
115
|
+
if $1 == ':' # skip postgresql casts
|
116
|
+
$& # return the whole match
|
117
|
+
elsif bind_vars.include?(match = $2.to_sym)
|
118
|
+
quote_bound_value(bind_vars[match])
|
119
|
+
else
|
120
|
+
raise ArgumentError, "missing value for :#{match} in #{statement}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def quote_bound_value(value)
|
126
|
+
if value.respond_to?(:map) && !value.acts_like?(:string)
|
127
|
+
if value.respond_to?(:empty?) && value.empty?
|
128
|
+
quote(nil)
|
129
|
+
else
|
130
|
+
value.map { |v| quote(v) }.join(',')
|
131
|
+
end
|
132
|
+
else
|
133
|
+
quote(value)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def replace_bind_variables(statement, values)
|
138
|
+
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
|
139
|
+
bound = values.dup
|
140
|
+
statement.gsub('?') { quote_bound_value(bound.shift) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def raise_if_bind_arity_mismatch(statement, expected, provided)
|
144
|
+
unless expected == provided
|
145
|
+
raise ArgumentError, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Adapted from https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
|
2
|
+
require 'yaml'
|
3
|
+
module RFQL
|
4
|
+
class Query
|
5
|
+
module Quoting
|
6
|
+
# Quotes the column value to help prevent
|
7
|
+
# {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].
|
8
|
+
def quote(value)
|
9
|
+
case value
|
10
|
+
when String then "'#{quote_string(value)}'"
|
11
|
+
when true then 'true'
|
12
|
+
when false then 'false'
|
13
|
+
when nil then "NULL"
|
14
|
+
when Numeric then value.to_s
|
15
|
+
when Date then value.to_time.to_i.to_s
|
16
|
+
when Time then value.to_i.to_s
|
17
|
+
when Symbol then value.to_s
|
18
|
+
else "'#{quote_string(YAML.dump(value))}'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
23
|
+
# characters.
|
24
|
+
def quote_string(s)
|
25
|
+
s.gsub(/\\/, '\&\&').gsub(/'/, "''") # ' (for ruby-mode)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Quotes the column name. Defaults to no quoting.
|
29
|
+
def quote_column_name(column_name)
|
30
|
+
column_name.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
# Quotes the table name. Defaults to column name quoting.
|
34
|
+
def quote_table_name(table_name)
|
35
|
+
quote_column_name(table_name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/rfql/request.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rfql/core_ext/object/blank'
|
2
|
+
require 'rfql/query'
|
3
|
+
require 'rfql/request/delegations'
|
4
|
+
require 'rfql/response'
|
5
|
+
|
6
|
+
module RFQL
|
7
|
+
class Request
|
8
|
+
include RFQL::Request::QueryMethodsDelegations
|
9
|
+
|
10
|
+
attr_reader :response
|
11
|
+
|
12
|
+
def initialize(str = nil)
|
13
|
+
@query = RFQL::Query.new(str)
|
14
|
+
@format_param = :json
|
15
|
+
end
|
16
|
+
|
17
|
+
def query(query = nil)
|
18
|
+
return @query if query.nil?
|
19
|
+
@query = RFQL::Query.new(query)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_sql
|
24
|
+
@query.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def access_token(access_token = nil)
|
28
|
+
return @access_token if access_token.nil?
|
29
|
+
@access_token = access_token
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def format_param(format_param = nil)
|
34
|
+
return @format_param if format_param.nil?
|
35
|
+
raise ArgumentError, "illegal format" unless [:json, :xml].include?(format_param)
|
36
|
+
@format_param = format_param
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def params(with_format_param = false)
|
41
|
+
params = {:query => to_sql, :access_token => access_token}
|
42
|
+
return params unless with_format_param
|
43
|
+
params.merge(:format => @format_param)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_url(with_format_param = false)
|
47
|
+
RFQL::FQLURL + '?' + hash_to_params_string(params(with_format_param))
|
48
|
+
end
|
49
|
+
|
50
|
+
def hash_to_params_string(params)
|
51
|
+
params.to_a.select do |param|
|
52
|
+
param[0].present? and param[1].present?
|
53
|
+
end.map do |param|
|
54
|
+
k, v = URI.escape(param[0].to_s), URI.escape(param[1].to_s)
|
55
|
+
k.gsub!('&', '%26'); k.gsub!('=', '%3D'); v.gsub!('&', '%26'); v.gsub!('=', '%3D')
|
56
|
+
"#{k}=#{v}"
|
57
|
+
end.join('&')
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_json(json_format = :parsed, options = {})
|
61
|
+
begin
|
62
|
+
to_json!(json_format, options)
|
63
|
+
rescue RFQL::Response::FQLError
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_json!(json_format = :parsed, options = {})
|
69
|
+
raise ArgumentError, "illegal format" unless [:raw, :parsed].include?(json_format)
|
70
|
+
unless options.is_a?(Hash) and (options.keys - [:open_uri_options, :json_parse_options, :force_execution]).blank?
|
71
|
+
raise ArgumentError, "illegal options"
|
72
|
+
end
|
73
|
+
|
74
|
+
if options.delete(:force_execution).blank? and @response and
|
75
|
+
( ( json_format == :parsed and ( @response.is_a?(RFQL::Response::JSON::Parsed) or
|
76
|
+
@response.is_a?(RFQL::Response::JSON::Parsed::Records) or
|
77
|
+
@response.is_a?(RFQL::Response::JSON::Parsed::Error) ) ) or
|
78
|
+
( json_format == :raw and @response.is_a?(RFQL::Response::JSON::Raw) ) )
|
79
|
+
return @response
|
80
|
+
end
|
81
|
+
|
82
|
+
json_parse_opts = options[:json_parse_options] || {}
|
83
|
+
open_uri_read_opts = options[:open_uri_options] || {}
|
84
|
+
|
85
|
+
@response = RFQL::Response::JSON.new(self, options.merge(:format => json_format))
|
86
|
+
|
87
|
+
raise RFQL::Response::FQLError.new(@response) if @response.is_a?(RFQL::Response::JSON::Parsed::Error)
|
88
|
+
|
89
|
+
@response
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RFQL
|
2
|
+
class Request
|
3
|
+
module QueryMethodsDelegations
|
4
|
+
def select(*fields); query.select(*fields); self; end
|
5
|
+
def from(from = nil); query.from(from); self; end
|
6
|
+
def where(where = nil); query.where(where); self; end
|
7
|
+
def order(order = nil); query.order(order); self; end
|
8
|
+
def limit(limit = nil); query.limit(limit); self; end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
require 'rfql/response/json'
|
4
|
+
require 'rfql/response/fql_error'
|
5
|
+
|
6
|
+
module RFQL
|
7
|
+
module Response
|
8
|
+
class << self
|
9
|
+
def new(request, options = {})
|
10
|
+
options[:format] ||= :json_parsed
|
11
|
+
raise ArgumentError, 'illegal format' unless [:xml, :json_raw, :json_parsed].include?(options[:format])
|
12
|
+
|
13
|
+
case options[:format]
|
14
|
+
when :json_raw, :json_parsed
|
15
|
+
options[:format] = options[:format] == :json_raw ? :raw : :parsed
|
16
|
+
RFQL::Response::JSON.new(request, options)
|
17
|
+
when :xml
|
18
|
+
raise NotImplementedError, 'xml fetching is still a WIP :-P'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
def read(request, options = {})
|
22
|
+
request_url = request.respond_to?(:to_url) ? request.to_url : request.to_s
|
23
|
+
raise ArgumentError, 'illegal format' unless [:xml, :json].include?(options[:format])
|
24
|
+
request_url << "&format=#{options[:format]}"
|
25
|
+
URI.parse(request_url).read(options[:open_uri_options] || {})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rfql/response/json/raw'
|
3
|
+
require 'rfql/response/json/parsed'
|
4
|
+
require 'rfql/response/json/parsed/records'
|
5
|
+
require 'rfql/response/json/parsed/null'
|
6
|
+
require 'rfql/response/json/parsed/error'
|
7
|
+
|
8
|
+
module RFQL
|
9
|
+
module Response
|
10
|
+
class JSON
|
11
|
+
def self.new(request, options = {})
|
12
|
+
options[:format] ||= :parsed
|
13
|
+
raise ArgumentError, 'illegal format' unless [:raw, :parsed].include?(options[:format])
|
14
|
+
|
15
|
+
case options[:format]
|
16
|
+
when :raw then RFQL::Response::JSON::Raw.new(request, options)
|
17
|
+
when :parsed then RFQL::Response::JSON::Parsed.new(request, options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RFQL
|
2
|
+
module Response
|
3
|
+
class JSON
|
4
|
+
class Parsed
|
5
|
+
attr_reader :request, :response
|
6
|
+
def self.new(request, options = {})
|
7
|
+
json_raw_response = RFQL::Response::JSON::Raw.new(request, options)
|
8
|
+
|
9
|
+
json_parsed_response = ::JSON.parse(json_raw_response, options[:json_parse_options] || {})
|
10
|
+
|
11
|
+
if json_parsed_response.is_a?(Hash) and json_parsed_response.has_key?('error_code')
|
12
|
+
RFQL::Response::JSON::Parsed::Error.new(request, json_parsed_response)
|
13
|
+
elsif json_parsed_response.is_a?(Array)
|
14
|
+
RFQL::Response::JSON::Parsed::Records.new(request, json_parsed_response)
|
15
|
+
else
|
16
|
+
super(request, json_parsed_response)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
private
|
20
|
+
def initialize(request, json_parsed_response)
|
21
|
+
@request, @response = request, json_parsed_response
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RFQL
|
2
|
+
module Response
|
3
|
+
class JSON
|
4
|
+
class Parsed
|
5
|
+
class Error < Hash
|
6
|
+
attr_reader :request
|
7
|
+
def initialize(request, hash)
|
8
|
+
@request = request
|
9
|
+
merge!(hash)
|
10
|
+
# FIXME SyntaxError, dunno why
|
11
|
+
# hash.keys.each do |key|
|
12
|
+
# self.class.class_eval<<-"RB"
|
13
|
+
# def #{key}
|
14
|
+
# send :fetch, #{key}
|
15
|
+
# end
|
16
|
+
# RB
|
17
|
+
# end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RFQL
|
2
|
+
module Response
|
3
|
+
class JSON
|
4
|
+
class Raw < String
|
5
|
+
attr_reader :request
|
6
|
+
def initialize(request, options = {})
|
7
|
+
@request = request
|
8
|
+
options[:format] = :json
|
9
|
+
super RFQL::Response.read(request, options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/rfql.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{rfql}
|
5
|
+
s.version = "0.1.alpha"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = [%q{De Santis Maurizio}]
|
9
|
+
s.cert_chain = [%q{/home/mau/.gem_keys/gem-public_cert.pem}]
|
10
|
+
s.date = %q{2011-06-30}
|
11
|
+
s.description = %q{RFQL - Ruby interface for Facebook Query Language}
|
12
|
+
s.email = %q{desantis.maurizio@gmail.com}
|
13
|
+
s.extra_rdoc_files = [%q{CHANGELOG}, %q{LICENSE}, %q{README.rdoc}, %q{lib/rfql.rb}, %q{lib/rfql/core_ext/object/blank.rb}, %q{lib/rfql/query.rb}, %q{lib/rfql/query/methods.rb}, %q{lib/rfql/query/quoting.rb}, %q{lib/rfql/request.rb}, %q{lib/rfql/request/delegations.rb}, %q{lib/rfql/response.rb}, %q{lib/rfql/response/fql_error.rb}, %q{lib/rfql/response/json.rb}, %q{lib/rfql/response/json/parsed.rb}, %q{lib/rfql/response/json/parsed/error.rb}, %q{lib/rfql/response/json/parsed/null.rb}, %q{lib/rfql/response/json/parsed/records.rb}, %q{lib/rfql/response/json/raw.rb}]
|
14
|
+
s.files = [%q{CHANGELOG}, %q{LICENSE}, %q{Manifest}, %q{README.rdoc}, %q{Rakefile}, %q{lib/rfql.rb}, %q{lib/rfql/core_ext/object/blank.rb}, %q{lib/rfql/query.rb}, %q{lib/rfql/query/methods.rb}, %q{lib/rfql/query/quoting.rb}, %q{lib/rfql/request.rb}, %q{lib/rfql/request/delegations.rb}, %q{lib/rfql/response.rb}, %q{lib/rfql/response/fql_error.rb}, %q{lib/rfql/response/json.rb}, %q{lib/rfql/response/json/parsed.rb}, %q{lib/rfql/response/json/parsed/error.rb}, %q{lib/rfql/response/json/parsed/null.rb}, %q{lib/rfql/response/json/parsed/records.rb}, %q{lib/rfql/response/json/raw.rb}, %q{rfql.gemspec}]
|
15
|
+
s.homepage = %q{http://ProGNOMmers.github.com/ProGNOMmers/rfql/}
|
16
|
+
s.rdoc_options = [%q{--line-numbers}, %q{--inline-source}, %q{--title}, %q{Rfql}, %q{--main}, %q{README.rdoc}]
|
17
|
+
s.require_paths = [%q{lib}]
|
18
|
+
s.rubyforge_project = %q{ProGNOMmers}
|
19
|
+
s.rubygems_version = %q{1.8.5}
|
20
|
+
s.signing_key = %q{/home/mau/.gem_keys/gem-private_key.pem}
|
21
|
+
s.summary = %q{It lets you use ORM-style code for fetching data from Facebook through the Facebook Query Language}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
|
+
else
|
28
|
+
end
|
29
|
+
else
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rfql
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.alpha
|
5
|
+
prerelease: 4
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- De Santis Maurizio
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- ! '-----BEGIN CERTIFICATE-----
|
13
|
+
|
14
|
+
MIIDRDCCAiygAwIBAgIBADANBgkqhkiG9w0BAQUFADBIMRowGAYDVQQDDBFkZXNh
|
15
|
+
|
16
|
+
bnRpcy5tYXVyaXppbzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
|
17
|
+
|
18
|
+
LGQBGRYDY29tMB4XDTExMDYzMDExMjIyOVoXDTEyMDYyOTExMjIyOVowSDEaMBgG
|
19
|
+
|
20
|
+
A1UEAwwRZGVzYW50aXMubWF1cml6aW8xFTATBgoJkiaJk/IsZAEZFgVnbWFpbDET
|
21
|
+
|
22
|
+
MBEGCgmSJomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
23
|
+
|
24
|
+
ggEBANa1yrC8nNkg8hfVU5LNqgh6WwaXSh6tGPn6V0XtMIyMiHF1ess24NPQqPpl
|
25
|
+
|
26
|
+
43t4hWOEGrcfwmnQso1sJsK+TiQ29dyC9upfRz4H0BxzIUUQNQae2F1d2BfptnUg
|
27
|
+
|
28
|
+
xPFPBhBztkpL9I6O1MeZn8zyCczqEHwV18dwbeLssxbJLloVEIpVQFvOI6DSZB1r
|
29
|
+
|
30
|
+
v4T8EieG79jsS2pf2yK9gWuyTnxq27RlTQxHghC0Xnu79b8TrUkiJt8sbjgGP2Ax
|
31
|
+
|
32
|
+
g08RtZP/owHzNWgLCT4exO68gEnRct/34ju0VL7zaG7TbA1cUFBWEtDR/YQw06+x
|
33
|
+
|
34
|
+
LseG3fuRWZIuENeXUJFLUkLF/Z8CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4E
|
35
|
+
|
36
|
+
FgQUcbnTN20o+PJYFy32iMllDe8CuE0wCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEB
|
37
|
+
|
38
|
+
BQUAA4IBAQBCkfsLuziCNp2uBRWwyr4b0/Yct172ftsAcgGQilVkaGx3VYu9G3WZ
|
39
|
+
|
40
|
+
uxLoofO1c1pgvPqbjLAKq0EUqLxna54ILER6WVaPk70RtIQc2d3Rkj7CEpTI+veW
|
41
|
+
|
42
|
+
ki7IL2OzjVD5Mxad5PEEyCLWrC5Ky2I8OqP8HfwnG0a19YfZRhxAH9XOkQX5HB3O
|
43
|
+
|
44
|
+
t7xlgHGYIHKHfIFCo3UZfaqn354vtbetA0Omt52ZHjt88PsVG0rTrovNctkh61Vq
|
45
|
+
|
46
|
+
99PUQdKGcIRcEsw4zQN3XgwJEqRVV5F6gGQyUY2LIeyyf+58kuHL2UkpVJU7b+7d
|
47
|
+
|
48
|
+
1qFkvs/eJXM+w3TkQ2vaW9KFXQkIewZs
|
49
|
+
|
50
|
+
-----END CERTIFICATE-----
|
51
|
+
|
52
|
+
'
|
53
|
+
date: 2011-06-30 00:00:00.000000000Z
|
54
|
+
dependencies: []
|
55
|
+
description: RFQL - Ruby interface for Facebook Query Language
|
56
|
+
email: desantis.maurizio@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files:
|
60
|
+
- CHANGELOG
|
61
|
+
- LICENSE
|
62
|
+
- README.rdoc
|
63
|
+
- lib/rfql.rb
|
64
|
+
- lib/rfql/core_ext/object/blank.rb
|
65
|
+
- lib/rfql/query.rb
|
66
|
+
- lib/rfql/query/methods.rb
|
67
|
+
- lib/rfql/query/quoting.rb
|
68
|
+
- lib/rfql/request.rb
|
69
|
+
- lib/rfql/request/delegations.rb
|
70
|
+
- lib/rfql/response.rb
|
71
|
+
- lib/rfql/response/fql_error.rb
|
72
|
+
- lib/rfql/response/json.rb
|
73
|
+
- lib/rfql/response/json/parsed.rb
|
74
|
+
- lib/rfql/response/json/parsed/error.rb
|
75
|
+
- lib/rfql/response/json/parsed/null.rb
|
76
|
+
- lib/rfql/response/json/parsed/records.rb
|
77
|
+
- lib/rfql/response/json/raw.rb
|
78
|
+
files:
|
79
|
+
- CHANGELOG
|
80
|
+
- LICENSE
|
81
|
+
- Manifest
|
82
|
+
- README.rdoc
|
83
|
+
- Rakefile
|
84
|
+
- lib/rfql.rb
|
85
|
+
- lib/rfql/core_ext/object/blank.rb
|
86
|
+
- lib/rfql/query.rb
|
87
|
+
- lib/rfql/query/methods.rb
|
88
|
+
- lib/rfql/query/quoting.rb
|
89
|
+
- lib/rfql/request.rb
|
90
|
+
- lib/rfql/request/delegations.rb
|
91
|
+
- lib/rfql/response.rb
|
92
|
+
- lib/rfql/response/fql_error.rb
|
93
|
+
- lib/rfql/response/json.rb
|
94
|
+
- lib/rfql/response/json/parsed.rb
|
95
|
+
- lib/rfql/response/json/parsed/error.rb
|
96
|
+
- lib/rfql/response/json/parsed/null.rb
|
97
|
+
- lib/rfql/response/json/parsed/records.rb
|
98
|
+
- lib/rfql/response/json/raw.rb
|
99
|
+
- rfql.gemspec
|
100
|
+
homepage: http://ProGNOMmers.github.com/ProGNOMmers/rfql/
|
101
|
+
licenses: []
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options:
|
104
|
+
- --line-numbers
|
105
|
+
- --inline-source
|
106
|
+
- --title
|
107
|
+
- Rfql
|
108
|
+
- --main
|
109
|
+
- README.rdoc
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '1.2'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project: ProGNOMmers
|
126
|
+
rubygems_version: 1.8.5
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: It lets you use ORM-style code for fetching data from Facebook through the
|
130
|
+
Facebook Query Language
|
131
|
+
test_files: []
|
metadata.gz.sig
ADDED