facemock 0.0.4 → 0.0.5
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/.coveralls.yml +1 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +6 -0
- data/db/.gitkeep +0 -0
- data/facemock.gemspec +31 -0
- data/lib/facemock/config.rb +88 -0
- data/lib/facemock/database/application.rb +20 -0
- data/lib/facemock/database/permission.rb +21 -0
- data/lib/facemock/database/table.rb +340 -0
- data/lib/facemock/database/user.rb +26 -0
- data/lib/facemock/database.rb +121 -0
- data/lib/facemock/errors.rb +7 -0
- data/lib/facemock/fb_graph/application/test_users.rb +36 -0
- data/lib/facemock/fb_graph/application/user/permission.rb +10 -0
- data/lib/facemock/fb_graph/application/user.rb +69 -0
- data/lib/facemock/fb_graph/application.rb +48 -0
- data/lib/facemock/fb_graph/user.rb +13 -0
- data/lib/facemock/fb_graph.rb +30 -0
- data/lib/facemock/version.rb +3 -0
- data/lib/facemock.rb +19 -0
- data/spec/facemock/config_spec.rb +185 -0
- data/spec/facemock/database/application_spec.rb +73 -0
- data/spec/facemock/database/permission_spec.rb +52 -0
- data/spec/facemock/database/tables_spec.rb +728 -0
- data/spec/facemock/database/user_spec.rb +169 -0
- data/spec/facemock/database_spec.rb +270 -0
- data/spec/facemock/errors_spec.rb +9 -0
- data/spec/facemock/fb_graph/application/test_users_spec.rb +155 -0
- data/spec/facemock/fb_graph/application/user_spec.rb +208 -0
- data/spec/facemock/fb_graph/application_spec.rb +132 -0
- data/spec/facemock/fb_graph/user_spec.rb +36 -0
- data/spec/facemock/fb_graph_spec.rb +47 -0
- data/spec/facemock_spec.rb +74 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/tables_helper.rb +46 -0
- metadata +64 -3
@@ -0,0 +1,340 @@
|
|
1
|
+
require 'facemock/database'
|
2
|
+
require 'sqlite3'
|
3
|
+
require 'hashie'
|
4
|
+
|
5
|
+
module Facemock
|
6
|
+
class Database
|
7
|
+
class Table
|
8
|
+
# 以下は継承先でオーバーライド必須
|
9
|
+
# * TABLE_NAME, COLUMN_NAMES
|
10
|
+
# * initialize()
|
11
|
+
TABLE_NAME = :tables
|
12
|
+
COLUMN_NAMES = [:id, :text, :active, :number, :created_at]
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
opts = Hashie::Mash.new(options)
|
16
|
+
self.id = opts.id
|
17
|
+
self.text = opts.text
|
18
|
+
self.active = opts.active || false
|
19
|
+
self.number = opts.number
|
20
|
+
self.created_at = opts.created_at
|
21
|
+
end
|
22
|
+
|
23
|
+
def save!(options={})
|
24
|
+
persisted? ? update!(options) : insert!(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_attributes!(options)
|
28
|
+
# カラムに含まれるかどうかの確認。なければNoMethodError
|
29
|
+
options.each_key {|key| self.send(key) }
|
30
|
+
if persisted?
|
31
|
+
update!(options)
|
32
|
+
else
|
33
|
+
insert!(options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy
|
38
|
+
raise unless persisted?
|
39
|
+
execute "DELETE FROM #{table_name} WHERE ID = #{self.id};"
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def fetch
|
44
|
+
if persisted?
|
45
|
+
sql = "SELECT * FROM #{table_name} WHERE ID = #{self.id} LIMIT 1;"
|
46
|
+
records = execute sql
|
47
|
+
return nil unless record = records.first
|
48
|
+
set_attributes_from_record(record)
|
49
|
+
self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(name, *args)
|
54
|
+
method_name = name.to_s.include?("=") ? name.to_s[0...-1].to_sym : name
|
55
|
+
case name
|
56
|
+
when :identifier then return send(:id)
|
57
|
+
when :identifier= then return send(:id=, *args)
|
58
|
+
else
|
59
|
+
if column_names.include?(method_name) && args.size <= 1
|
60
|
+
if !name.to_s.include?("=") && args.empty?
|
61
|
+
define_column_getter(name)
|
62
|
+
return send(name)
|
63
|
+
else
|
64
|
+
define_column_setter(name)
|
65
|
+
return send(name, args.first)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.all
|
74
|
+
records = execute "SELECT * FROM #{table_name};"
|
75
|
+
records_to_objects(records)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.first
|
79
|
+
records = execute "SELECT * FROM #{table_name} LIMIT 1;"
|
80
|
+
record_to_object(records.first)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.last
|
84
|
+
records = execute "SELECT * FROM #{table_name} ORDER BY ID DESC LIMIT 1 ;"
|
85
|
+
record_to_object(records.first)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.where(column)
|
89
|
+
column_name = column.keys.first
|
90
|
+
value = column.values.first
|
91
|
+
column_value = (value.kind_of?(String)) ? "'" + value + "'" : value.to_s
|
92
|
+
|
93
|
+
records = execute "SELECT * FROM #{table_name} WHERE #{column_name} = #{column_value};"
|
94
|
+
records_to_objects(records)
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.method_missing(name, *args)
|
98
|
+
if name =~ /^find_by_(.+)/ || name =~ /^find_all_by_(.+)/
|
99
|
+
column_name = $1
|
100
|
+
else
|
101
|
+
super
|
102
|
+
end
|
103
|
+
super unless column_names.include?(column_name.to_sym)
|
104
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" unless args.size == 1
|
105
|
+
super unless define_find_method(name, column_name)
|
106
|
+
send(name, args.first)
|
107
|
+
end
|
108
|
+
|
109
|
+
def table_name
|
110
|
+
self.class.table_name
|
111
|
+
end
|
112
|
+
|
113
|
+
def column_names
|
114
|
+
self.class.column_names
|
115
|
+
end
|
116
|
+
|
117
|
+
def persisted?
|
118
|
+
!!(self.id && !(self.class.find_by_id(self.id).nil?))
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.table_name
|
122
|
+
self::TABLE_NAME
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.column_names
|
126
|
+
self::COLUMN_NAMES
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.column_type(column_name)
|
130
|
+
return nil unless column_names.include?(column_name.to_s.to_sym)
|
131
|
+
table_info.send(column_name).type
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.table_info
|
135
|
+
sql = "PRAGMA TABLE_INFO(#{table_name});"
|
136
|
+
records = execute sql
|
137
|
+
info = Hashie::Mash.new
|
138
|
+
records.each do |record|
|
139
|
+
column_info = Hashie::Mash.new(
|
140
|
+
{ cid: record[0],
|
141
|
+
name: record[1].to_sym,
|
142
|
+
type: record[2],
|
143
|
+
notnull: (record[3] == 1),
|
144
|
+
dflt_value: record[4],
|
145
|
+
pk: (record[5] == 1) }
|
146
|
+
)
|
147
|
+
info.send(record[1] + "=", column_info)
|
148
|
+
end
|
149
|
+
info
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def execute(sql)
|
155
|
+
self.class.execute(sql)
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.execute(sql)
|
159
|
+
database = Facemock::Database.new
|
160
|
+
records = database.connection.execute sql
|
161
|
+
if records.empty? && sql =~ /^INSERT /
|
162
|
+
records = database.connection.execute <<-SQL
|
163
|
+
SELECT * FROM #{table_name} WHERE ROWID = last_insert_rowid();
|
164
|
+
SQL
|
165
|
+
end
|
166
|
+
database.disconnect!
|
167
|
+
records
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.record_to_object(record)
|
171
|
+
return nil unless record
|
172
|
+
self.new(record_to_hash(record))
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.records_to_objects(records)
|
176
|
+
records.inject([]) do |objects, record|
|
177
|
+
objects << record_to_object(record)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def record_to_hash(record)
|
182
|
+
self.class.record_to_hash(record)
|
183
|
+
end
|
184
|
+
|
185
|
+
# 以下の形式のHashが返される
|
186
|
+
# { id: x, ..., created_at: yyyy-mm-dd :hh:mm +xxxx }
|
187
|
+
def self.record_to_hash(record)
|
188
|
+
hash = Hashie::Mash.new
|
189
|
+
column_names.each_with_index do |column_name, index|
|
190
|
+
value = (record[index] == "") ? nil : record[index]
|
191
|
+
parsed_value = case column_type(column_name)
|
192
|
+
when "BOOLEAN" then eval(value)
|
193
|
+
when "DATETIME" then Time.parse(value)
|
194
|
+
else value
|
195
|
+
end
|
196
|
+
hash.send(column_name.to_s + "=", parsed_value)
|
197
|
+
end
|
198
|
+
hash
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.define_find_method(method_name, column_name)
|
202
|
+
case method_name
|
203
|
+
when /^find_by_(.+)/ then define_find_by_column(column_name)
|
204
|
+
when /^find_all_by_(.+)/ then define_find_all_by_column(column_name)
|
205
|
+
else false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.define_find_by_column(column_name)
|
210
|
+
self.class_eval <<-EOF
|
211
|
+
def self.find_by_#{column_name}(value)
|
212
|
+
column_value = case value
|
213
|
+
when String then "'" + value + "'"
|
214
|
+
when Time then "'" + value.to_s + "'"
|
215
|
+
else value.to_s
|
216
|
+
end
|
217
|
+
|
218
|
+
sql = "SELECT * FROM #{table_name} WHERE #{column_name} = "
|
219
|
+
sql += column_value + " LIMIT 1;"
|
220
|
+
records = execute sql
|
221
|
+
record_to_object(records.first)
|
222
|
+
end
|
223
|
+
EOF
|
224
|
+
true
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.define_find_all_by_column(column_name)
|
228
|
+
self.class_eval <<-EOF
|
229
|
+
def self.find_all_by_#{column_name}(value)
|
230
|
+
column_value = case value
|
231
|
+
when String then "'" + value + "'"
|
232
|
+
when Time then "'" + value.to_s + "'"
|
233
|
+
else value.to_s
|
234
|
+
end
|
235
|
+
|
236
|
+
sql = "SELECT * FROM #{table_name} WHERE #{column_name} = "
|
237
|
+
sql += column_value + ";"
|
238
|
+
records = execute sql
|
239
|
+
records_to_objects(records)
|
240
|
+
end
|
241
|
+
EOF
|
242
|
+
true
|
243
|
+
end
|
244
|
+
|
245
|
+
def define_column_getter(name)
|
246
|
+
self.class.class_eval <<-EOF
|
247
|
+
def #{name}
|
248
|
+
self.instance_variable_get(:@#{name})
|
249
|
+
end
|
250
|
+
EOF
|
251
|
+
end
|
252
|
+
|
253
|
+
def define_column_setter(name)
|
254
|
+
self.class.class_eval <<-EOF
|
255
|
+
def #{name}(value)
|
256
|
+
instance_variable_set(:@#{name.to_s.gsub("=", "")}, value)
|
257
|
+
end
|
258
|
+
EOF
|
259
|
+
end
|
260
|
+
|
261
|
+
# DatabaseへのINSERTが成功してからインスタンスのフィールド値を更新する
|
262
|
+
def insert!(options={})
|
263
|
+
opts = Hashie::Mash.new(options)
|
264
|
+
instance = self.class.new
|
265
|
+
column_names.each do |column_name|
|
266
|
+
if column_name != :created_at
|
267
|
+
if self.class.column_notnull(column_name) && column_is_empty?(column_name)
|
268
|
+
raise Facemock::Errors::ColumnTypeNotNull, "#{column_name} is null"
|
269
|
+
end
|
270
|
+
instance.send(column_name.to_s + "=", self.send(column_name))
|
271
|
+
if opts.send(column_name)
|
272
|
+
instance.send(column_name.to_s + "=", opts.send(column_name))
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
target_column_names = if instance.id
|
278
|
+
column_names
|
279
|
+
else
|
280
|
+
column_names.select{|name| name != :id}
|
281
|
+
end
|
282
|
+
instance.created_at = Time.now
|
283
|
+
target_column_values = target_column_names.inject([]) do |ary, column_name|
|
284
|
+
ary << "'#{instance.send(column_name)}'"
|
285
|
+
end
|
286
|
+
values = target_column_values.join(", ")
|
287
|
+
columns = target_column_names.join(', ')
|
288
|
+
|
289
|
+
sql = "INSERT INTO #{table_name}(#{columns}) VALUES ( #{values} );"
|
290
|
+
records = execute sql
|
291
|
+
set_attributes_from_record(records.first)
|
292
|
+
true
|
293
|
+
end
|
294
|
+
|
295
|
+
def update!(options={})
|
296
|
+
if options.empty?
|
297
|
+
column_names.each do |column_name|
|
298
|
+
if (value = self.send(column_name)) && column_name != :id
|
299
|
+
options[column_name] = value unless options.nil?
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
unless options.empty?
|
305
|
+
target_key_values = options.inject([]) do |ary, (key, value)|
|
306
|
+
ary << (value.kind_of?(Integer) ? "#{key} = #{value}" : "#{key} = '#{value}'")
|
307
|
+
end
|
308
|
+
sql = "UPDATE #{table_name} SET #{target_key_values.join(', ')} WHERE ID = #{self.id};"
|
309
|
+
execute sql
|
310
|
+
end
|
311
|
+
fetch
|
312
|
+
true
|
313
|
+
end
|
314
|
+
|
315
|
+
def set_attributes_from_record(record)
|
316
|
+
hash = record_to_hash(record)
|
317
|
+
column_names.each do |column_name|
|
318
|
+
method_name = column_name.to_s + "="
|
319
|
+
self.send(method_name, hash.send(column_name))
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def column_is_empty?(column_name)
|
324
|
+
return true if self.send(column_name).nil?
|
325
|
+
|
326
|
+
return case self.class.column_type(column_name)
|
327
|
+
when "TEXT", "DATETIME", "BOOLEAN"
|
328
|
+
true if self.send(column_name) == ""
|
329
|
+
else
|
330
|
+
false
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def self.column_notnull(column_name)
|
335
|
+
return nil unless column_names.include?(column_name.to_s.to_sym)
|
336
|
+
table_info.send(column_name).notnull
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'facemock/database'
|
2
|
+
require 'facemock/database/table'
|
3
|
+
require 'sqlite3'
|
4
|
+
require 'hashie'
|
5
|
+
|
6
|
+
module Facemock
|
7
|
+
class Database
|
8
|
+
class User < Table
|
9
|
+
TABLE_NAME = :users
|
10
|
+
COLUMN_NAMES = [:id, :name, :email, :password, :installed, :access_token, :application_id, :created_at]
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
opts = Hashie::Mash.new(options)
|
14
|
+
@id = (opts.id.to_i > 0) ? opts.id.to_i : ("10000" + (0..9).to_a.shuffle[0..10].join).to_i
|
15
|
+
@name = opts.name || rand(36**10).to_s(36)
|
16
|
+
@email = opts.email || name.gsub(" ", "_") + "@example.com"
|
17
|
+
@password = opts.password || rand(36**10).to_s(36)
|
18
|
+
@installed = opts.installed || false
|
19
|
+
@access_token = opts.access_token || Digest::SHA512.hexdigest(identifier.to_s)
|
20
|
+
app_id = opts.application_id.to_i
|
21
|
+
@application_id = (app_id > 0) ? app_id : nil
|
22
|
+
@created_at = opts.created_at
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
require 'facemock/database/table'
|
3
|
+
require 'facemock/database/application'
|
4
|
+
require 'facemock/database/user'
|
5
|
+
require 'facemock/database/permission'
|
6
|
+
|
7
|
+
module Facemock
|
8
|
+
class Database
|
9
|
+
ADAPTER = "sqlite3"
|
10
|
+
DB_DIRECTORY = File.expand_path("../../../db", __FILE__)
|
11
|
+
DEFAULT_DB_NAME = "facemock"
|
12
|
+
TABLE_NAMES = [:applications, :users, :permissions]
|
13
|
+
|
14
|
+
attr_reader :name
|
15
|
+
attr_reader :connection
|
16
|
+
|
17
|
+
def initialize(name=nil)
|
18
|
+
@name = DEFAULT_DB_NAME
|
19
|
+
connect
|
20
|
+
create_tables
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect
|
24
|
+
@connection = SQLite3::Database.new filepath
|
25
|
+
@state = :connected
|
26
|
+
@connection
|
27
|
+
end
|
28
|
+
|
29
|
+
def disconnect!
|
30
|
+
@connection.close
|
31
|
+
@state = :disconnected
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def connected?
|
36
|
+
@state == :connected
|
37
|
+
end
|
38
|
+
|
39
|
+
def drop
|
40
|
+
disconnect!
|
41
|
+
File.delete(filepath) if File.exist?(filepath)
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def clear
|
46
|
+
drop_tables
|
47
|
+
create_tables
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_tables
|
51
|
+
TABLE_NAMES.each do |table_name|
|
52
|
+
self.send "create_#{table_name}_table" unless table_exists?(table_name)
|
53
|
+
end
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def drop_table(table_name)
|
58
|
+
return false unless File.exist?(filepath) && table_exists?(table_name)
|
59
|
+
@connection.execute "drop table #{table_name};"
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def drop_tables
|
64
|
+
return false unless File.exist?(filepath)
|
65
|
+
TABLE_NAMES.each{|table_name| drop_table(table_name) }
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def filepath
|
70
|
+
name ||= @name
|
71
|
+
File.join(DB_DIRECTORY, "#{@name}.#{ADAPTER}")
|
72
|
+
end
|
73
|
+
|
74
|
+
def table_exists?(table_name)
|
75
|
+
tables = @connection.execute "select * from sqlite_master"
|
76
|
+
tables.each do |table|
|
77
|
+
return true if table[1].to_s == table_name.to_s
|
78
|
+
end
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def create_applications_table
|
85
|
+
@connection.execute <<-SQL
|
86
|
+
CREATE TABLE applications (
|
87
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
88
|
+
secret TEXT NOT NULL,
|
89
|
+
created_at DATETIME NOT NULL,
|
90
|
+
UNIQUE(secret)
|
91
|
+
);
|
92
|
+
SQL
|
93
|
+
end
|
94
|
+
|
95
|
+
def create_users_table
|
96
|
+
@connection.execute <<-SQL
|
97
|
+
CREATE TABLE users (
|
98
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
99
|
+
name TEXT NOT NULL,
|
100
|
+
email TEXT NOT NULL,
|
101
|
+
password TEXT NOT NULL,
|
102
|
+
installed BOOLEAN NOT NULL,
|
103
|
+
access_token TEXT NOT NULL,
|
104
|
+
application_id INTEGER NOT NULL,
|
105
|
+
created_at DATETIME NOT NULL,
|
106
|
+
UNIQUE(access_token));
|
107
|
+
SQL
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_permissions_table
|
111
|
+
@connection.execute <<-SQL
|
112
|
+
CREATE TABLE permissions (
|
113
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
114
|
+
name TEXT NOT NULL,
|
115
|
+
user_id INTEGER NOT NULL,
|
116
|
+
created_at DATETIME NOT NULL
|
117
|
+
);
|
118
|
+
SQL
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'facemock/fb_graph/application/user'
|
2
|
+
|
3
|
+
module Facemock
|
4
|
+
module FbGraph
|
5
|
+
class Application
|
6
|
+
class TestUsers < Array
|
7
|
+
DEFAULT_LIMIT = 50
|
8
|
+
DEFAULT_AFTER = 0
|
9
|
+
|
10
|
+
def initialize(application_id, options={})
|
11
|
+
@limit = limit = (options[:limit] && options[:limit] > 0) ? options[:limit] : DEFAULT_LIMIT
|
12
|
+
@after = after = (options[:after] && options[:after] > 0) ? options[:after] : DEFAULT_AFTER
|
13
|
+
@application_id = application_id
|
14
|
+
st = after
|
15
|
+
ed = after + limit - 1
|
16
|
+
users = User.find_all_by_application_id(application_id).sort_by{|u| u.created_at}
|
17
|
+
users = users.reverse[st..ed] || []
|
18
|
+
super(users)
|
19
|
+
end
|
20
|
+
|
21
|
+
def collection
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def next
|
26
|
+
options = { limit: @limit, after: @after + @limit }
|
27
|
+
TestUsers.new(@application_id, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def select
|
31
|
+
{ limit: DEFAULT_LIMIT, after: DEFAULT_AFTER }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'facemock/fb_graph/application/user/permission'
|
3
|
+
|
4
|
+
module Facemock
|
5
|
+
module FbGraph
|
6
|
+
class Application
|
7
|
+
class User < Facemock::Database::User
|
8
|
+
attr_reader :permission_objects
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
opts = Hashie::Mash.new(options)
|
12
|
+
if opts.identifier
|
13
|
+
opts[:id] = opts.identifier
|
14
|
+
opts.delete(:identifier)
|
15
|
+
end
|
16
|
+
super(opts)
|
17
|
+
|
18
|
+
@permission_objects = User::Permission.find_all_by_user_id(self.id)
|
19
|
+
set_permissions(opts.permissions) if opts.permissions
|
20
|
+
end
|
21
|
+
|
22
|
+
def permissions
|
23
|
+
@permission_objects.inject([]) do |names, perm|
|
24
|
+
names << perm.name.to_sym
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def save!
|
29
|
+
super
|
30
|
+
@permission_objects.each do |permission|
|
31
|
+
permission.save!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch
|
36
|
+
@permission_objects = User::Permission.find_all_by_user_id(self.id)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@permission_objects.each do |permission|
|
42
|
+
permission.destroy
|
43
|
+
end
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
def revoke!
|
48
|
+
@permission_objects.each do |permission|
|
49
|
+
permission.destroy
|
50
|
+
end
|
51
|
+
@permission_objects = []
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def set_permissions(permissions_string)
|
57
|
+
permissions_string.gsub(/\s/, "").split(",").uniq.each do |permission_name|
|
58
|
+
unless @permission_objects.find{|perm| perm.name == permission_name}
|
59
|
+
@permission_objects << User::Permission.new(
|
60
|
+
name: permission_name,
|
61
|
+
user_id: self.id
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'facemock/config'
|
3
|
+
require 'facemock/fb_graph/application/user'
|
4
|
+
require 'facemock/fb_graph/application/test_users'
|
5
|
+
require 'facemock/database/application'
|
6
|
+
|
7
|
+
module Facemock
|
8
|
+
module FbGraph
|
9
|
+
class Application
|
10
|
+
attr_reader :identifier
|
11
|
+
attr_reader :secret
|
12
|
+
|
13
|
+
def initialize(identifier, options={})
|
14
|
+
opts = Hashie::Mash.new(options)
|
15
|
+
if (identifier == :app && opts.access_token)
|
16
|
+
identifier = (0..9).to_a.shuffle[0..15].join
|
17
|
+
secret = opts.access_token
|
18
|
+
else
|
19
|
+
secret = opts.secret || rand(36**32).to_s(36)
|
20
|
+
end
|
21
|
+
|
22
|
+
@record = Facemock::Database::Application.new({id: identifier, secret: secret})
|
23
|
+
@record.save! unless Facemock::Database::Application.find_by_id(identifier)
|
24
|
+
@identifier = identifier.to_i
|
25
|
+
@secret = secret
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch
|
29
|
+
if @record = Facemock::Database::Application.find_by_id(@identifier)
|
30
|
+
@identifier = @record.id
|
31
|
+
@secret = @record.secret
|
32
|
+
end
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_user!(options={})
|
37
|
+
options.merge!({application_id: self.identifier})
|
38
|
+
user = User.new(options)
|
39
|
+
user.save!
|
40
|
+
user
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_users(options={})
|
44
|
+
TestUsers.new(self.identifier, options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'fb_graph'
|
2
|
+
require 'facemock/config'
|
3
|
+
require 'facemock/fb_graph/user'
|
4
|
+
require 'facemock/fb_graph/application'
|
5
|
+
|
6
|
+
module Facemock
|
7
|
+
module FbGraph
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def on(options={})
|
11
|
+
if ::FbGraph != Facemock::FbGraph
|
12
|
+
Object.const_set(:SourceFbGraph, ::FbGraph)
|
13
|
+
Object.send(:remove_const, :FbGraph) if Object.constants.include?(:FbGraph)
|
14
|
+
Object.const_set(:FbGraph, Facemock::FbGraph)
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def off
|
20
|
+
if ::FbGraph == Facemock::FbGraph
|
21
|
+
Object.send(:remove_const, :FbGraph) if Object.constants.include?(:FbGraph)
|
22
|
+
Object.const_set(:FbGraph, ::SourceFbGraph)
|
23
|
+
Object.send(:remove_const, :SourceFbGraph) if Object.constants.include?(:FbGraph)
|
24
|
+
end
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
class InvalidToken < ::FbGraph::InvalidToken; end
|
29
|
+
end
|
30
|
+
end
|