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.
Files changed (41) hide show
  1. data/.coveralls.yml +1 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +154 -0
  8. data/Rakefile +6 -0
  9. data/db/.gitkeep +0 -0
  10. data/facemock.gemspec +31 -0
  11. data/lib/facemock/config.rb +88 -0
  12. data/lib/facemock/database/application.rb +20 -0
  13. data/lib/facemock/database/permission.rb +21 -0
  14. data/lib/facemock/database/table.rb +340 -0
  15. data/lib/facemock/database/user.rb +26 -0
  16. data/lib/facemock/database.rb +121 -0
  17. data/lib/facemock/errors.rb +7 -0
  18. data/lib/facemock/fb_graph/application/test_users.rb +36 -0
  19. data/lib/facemock/fb_graph/application/user/permission.rb +10 -0
  20. data/lib/facemock/fb_graph/application/user.rb +69 -0
  21. data/lib/facemock/fb_graph/application.rb +48 -0
  22. data/lib/facemock/fb_graph/user.rb +13 -0
  23. data/lib/facemock/fb_graph.rb +30 -0
  24. data/lib/facemock/version.rb +3 -0
  25. data/lib/facemock.rb +19 -0
  26. data/spec/facemock/config_spec.rb +185 -0
  27. data/spec/facemock/database/application_spec.rb +73 -0
  28. data/spec/facemock/database/permission_spec.rb +52 -0
  29. data/spec/facemock/database/tables_spec.rb +728 -0
  30. data/spec/facemock/database/user_spec.rb +169 -0
  31. data/spec/facemock/database_spec.rb +270 -0
  32. data/spec/facemock/errors_spec.rb +9 -0
  33. data/spec/facemock/fb_graph/application/test_users_spec.rb +155 -0
  34. data/spec/facemock/fb_graph/application/user_spec.rb +208 -0
  35. data/spec/facemock/fb_graph/application_spec.rb +132 -0
  36. data/spec/facemock/fb_graph/user_spec.rb +36 -0
  37. data/spec/facemock/fb_graph_spec.rb +47 -0
  38. data/spec/facemock_spec.rb +74 -0
  39. data/spec/spec_helper.rb +18 -0
  40. data/spec/support/tables_helper.rb +46 -0
  41. 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,7 @@
1
+ module Facemock
2
+ module Errors
3
+ class Error < StandardError; end
4
+ class IncorrectDataFormat < Error; end
5
+ class ColumnTypeNotNull < Error; end
6
+ end
7
+ 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,10 @@
1
+ module Facemock
2
+ module FbGraph
3
+ class Application
4
+ class User < Facemock::Database::User
5
+ class Permission < Facemock::Database::Permission
6
+ end
7
+ end
8
+ end
9
+ end
10
+ 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,13 @@
1
+ require 'facemock/fb_graph/application/user'
2
+
3
+ module Facemock
4
+ module FbGraph
5
+ module User
6
+ extend self
7
+
8
+ def me(access_token)
9
+ Application::User.find_by_access_token(access_token)
10
+ end
11
+ end
12
+ end
13
+ 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