acts_as_favoritor 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,63 +1,70 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsFavoritor
2
- module FavoriteScopes
3
-
4
- # Allows magic names on send(scope + '_list') - returns favorite records of certain scope
5
- # e.g. favoritors == favoritors.send('favorite_list')
6
- def method_missing m, *args
7
- if m.to_s[/(.+)_list/]
8
- where scope: $1.singularize.classify
9
- else
10
- super
11
- end
12
- end
13
-
14
- def respond_to? m, include_private = false
15
- super || m.to_s[/(.+)_list/]
16
- end
17
-
18
- def all_list
19
- all
20
- end
21
-
22
- # returns favorite records where favoritor is the record passed in.
23
- def for_favoritor favoritor
24
- where favoritor_id: favoritor.id, favoritor_type: parent_class_name(favoritor)
25
- end
26
-
27
- # returns favorite records where favoritable is the record passed in.
28
- def for_favoritable favoritable
29
- where favoritable_id: favoritable.id, favoritable_type: parent_class_name(favoritable)
30
- end
31
-
32
- # returns favorite records where favoritor_type is the record passed in.
33
- def for_favoritor_type favoritor_type
34
- where favoritor_type: favoritor_type
35
- end
36
-
37
- # returns favorite records where favoritable_type is the record passed in.
38
- def for_favoritable_type favoritable_type
39
- where favoritable_type: favoritable_type
40
- end
41
-
42
- # returns favorite records from past 2 weeks with default parameter.
43
- def recent from
44
- where ['created_at > ?', (from || 2.weeks.ago).to_s(:db)]
45
- end
46
-
47
- # returns favorite records in descending order.
48
- def descending
49
- order 'favorites.created_at desc'
50
- end
51
-
52
- # returns unblocked favorite records.
53
- def unblocked
54
- where blocked: false
55
- end
56
-
57
- # returns blocked favorite records.
58
- def blocked
59
- where blocked: true
60
- end
4
+ module FavoriteScopes
5
+ # Allows magic names on send(scope + '_list') - returns favorite records of
6
+ # certain scope.
7
+ # e.g. favoritors == favoritors.send('favorite_list')
8
+ def method_missing(method, *args)
9
+ if method.to_s[/(.+)_list/]
10
+ where(scope: $1.singularize)
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def respond_to_missing?(method, include_private = false)
17
+ super || method.to_s[/(.+)_list/]
18
+ end
19
+
20
+ def all_list
21
+ all
22
+ end
23
+
24
+ # returns favorite records where favoritor is the record passed in.
25
+ def for_favoritor(favoritor)
26
+ where(
27
+ favoritor_id: favoritor.id,
28
+ favoritor_type: parent_class_name(favoritor)
29
+ )
30
+ end
31
+
32
+ # returns favorite records where favoritable is the record passed in.
33
+ def for_favoritable(favoritable)
34
+ where(
35
+ favoritable_id: favoritable.id,
36
+ favoritable_type: parent_class_name(favoritable)
37
+ )
38
+ end
39
+
40
+ # returns favorite records where favoritor_type is the record passed in.
41
+ def for_favoritor_type(favoritor_type)
42
+ where(favoritor_type: favoritor_type)
43
+ end
44
+
45
+ # returns favorite records where favoritable_type is the record passed in.
46
+ def for_favoritable_type(favoritable_type)
47
+ where(favoritable_type: favoritable_type)
48
+ end
49
+
50
+ # returns favorite records from past 2 weeks with default parameter.
51
+ def recent(from)
52
+ where('created_at > ?', (from || 2.weeks.ago).to_s(:db))
53
+ end
54
+
55
+ # returns favorite records in descending order.
56
+ def descending
57
+ order('favorites.created_at desc')
58
+ end
59
+
60
+ # returns unblocked favorite records.
61
+ def unblocked
62
+ where(blocked: false)
63
+ end
61
64
 
65
+ # returns blocked favorite records.
66
+ def blocked
67
+ where(blocked: true)
62
68
  end
69
+ end
63
70
  end
@@ -1,425 +1,551 @@
1
- module ActsAsFavoritor
2
- module Favoritor
3
-
4
- def self.included base
5
- base.extend ClassMethods
6
- end
7
-
8
- module ClassMethods
9
- def acts_as_favoritor
10
- has_many :favorites, as: :favoritor, dependent: :destroy
11
- include ActsAsFavoritor::Favoritor::InstanceMethods
12
- include ActsAsFavoritor::FavoritorLib
13
-
14
- serialize :favoritor_cache, Hash if ActsAsFavoritor.configuration&.cache
15
- end
16
- end
17
-
18
- module InstanceMethods
19
-
20
- # Returns true if this instance has favorited the object passed as an argument.
21
- def favorited? favoritable, options = {}
22
- if options.has_key?(:multiple_scopes) == false
23
- options[:parameter] = favoritable
24
- validate_scopes __method__, options
25
- elsif options[:multiple_scopes]
26
- results = {}
27
- options[:scope].each do |scope|
28
- results[scope] = 0 < Favorite.unblocked.send(scope + '_list').for_favoritor(self).for_favoritable(favoritable).count
29
- end
30
- return results
31
- else
32
- return 0 < Favorite.unblocked.send(options[:scope] + '_list').for_favoritor(self).for_favoritable(favoritable).count
33
- end
34
- end
35
-
36
- # Returns true if this instance has blocked the object passed as an argument.
37
- def blocked? favoritable, options = {}
38
- if options.has_key?(:multiple_scopes) == false
39
- options[:parameter] = favoritable
40
- validate_scopes __method__, options
41
- elsif options[:multiple_scopes]
42
- results = {}
43
- options[:scope].each do |scope|
44
- results[scope] = 0 < Favorite.blocked.send(scope + '_list').for_favoritor(self).for_favoritable(favoritable).count
45
- end
46
- return results
47
- else
48
- return 0 < Favorite.blocked.send(options[:scope] + '_list').for_favoritor(self).for_favoritable(favoritable).count
49
- end
50
- end
51
-
52
- # Returns true if this instance has favorited the object passed as an argument.
53
- # Returns nil if this instance has not favorited the object passed as an argument.
54
- # Returns false if this instance has blocked the object passed as an argument.
55
- def favorited_type favoritable, options = {}
56
- if options.has_key?(:multiple_scopes) == false
57
- options[:parameter] = favoritable
58
- validate_scopes __method__, options
59
- elsif options[:multiple_scopes]
60
- results = {}
61
- options[:scope].each do |scope|
62
- if Favorite.unblocked.send(scope + '_list').for_favoritor(self).for_favoritable(favoritable).count > 0
63
- results[scope] = true
64
- elsif Favorite.blocked.send(scope + '_list').for_favoritor(self).for_favoritable(favoritable).count > 0
65
- results[scope] = false
66
- else
67
- results[scope] = nil
68
- end
69
- end
70
- return results
71
- else
72
- if Favorite.unblocked.send(options[:scope] + '_list').for_favoritor(self).for_favoritable(favoritable).count > 0
73
- return true
74
- elsif Favorite.blocked.send(options[:scope] + '_list').for_favoritor(self).for_favoritable(favoritable).count > 0
75
- return false
76
- else
77
- return nil
78
- end
79
- end
80
- end
81
-
82
- # Returns the number of objects this instance has favorited.
83
- def favorites_count options = {}
84
- if options.has_key?(:multiple_scopes) == false
85
- validate_scopes __method__, options
86
- elsif options[:multiple_scopes]
87
- results = {}
88
- options[:scope].each do |scope|
89
- results[scope] = Favorite.unblocked.send(scope + '_list').for_favoritor(self).count
90
- end
91
- return results
92
- else
93
- return Favorite.unblocked.send(options[:scope] + '_list').for_favoritor(self).count
94
- end
95
- end
96
-
97
- # Creates a new favorite record for this instance to favorite the passed object.
98
- # Does not allow duplicate records to be created.
99
- def favorite favoritable, options = {}
100
- if options.has_key?(:multiple_scopes) == false
101
- options[:parameter] = favoritable
102
- validate_scopes __method__, options
103
- elsif options[:multiple_scopes]
104
- results = {}
105
- options[:scope].each do |scope|
106
- if ActsAsFavoritor.configuration.cache
107
- self.favoritor_score[scope] = self.favoritor_score[scope] + 1 || 1
108
- self.favoritor_total[scope] = self.favoritor_total[scope] + 1 || 1
109
- self.save!
110
- favoritable.favoritable_score[scope] = favoritable.favoritable_score[scope] + 1 || 1
111
- favoritable.favoritable_total[scope] = favoritable.favoritable_total[scope] + 1 || 1
112
- favoritable.save!
113
- end
114
- if self != favoritable && scope != 'all'
115
- params = {favoritable_id: favoritable.id, favoritable_type: parent_class_name(favoritable), scope: scope}
116
- results[scope] = favorites.where(params).first_or_create!
117
- end
118
- end
119
- return results
120
- else
121
- if ActsAsFavoritor.configuration.cache
122
- self.favoritor_score[options[:scope]] = self.favoritor_score[options[:scope]] + 1 || 1
123
- self.favoritor_total[options[:scope]] = self.favoritor_total[options[:scope]] + 1 || 1
124
- self.save!
125
- favoritable.favoritable_score[options[:scope]] = favoritable.favoritable_score[options[:scope]] + 1 || 1
126
- favoritable.favoritable_total[options[:scope]] = favoritable.favoritable_total[options[:scope]] + 1 || 1
127
- favoritable.save!
128
- end
129
- if self != favoritable && options[:scope] != 'all'
130
- params = {favoritable_id: favoritable.id, favoritable_type: parent_class_name(favoritable), scope: options[:scope]}
131
- return favorites.where(params).first_or_create!
132
- end
133
- end
134
- end
135
-
136
- # Deletes the favorite record if it exists.
137
- def remove_favorite favoritable, options = {}
138
- if options.has_key?(:multiple_scopes) == false
139
- options[:parameter] = favoritable
140
- validate_scopes __method__, options
141
- elsif options[:multiple_scopes]
142
- results = {}
143
- options[:scope].each do |scope|
144
- if ActsAsFavoritor.configuration.cache
145
- self.favoritor_score[scope] = self.favoritor_score[scope] - 1
146
- self.favoritor_score.delete(scope) unless self.favoritor_score[scope] > 0
147
- self.save!
148
- favoritable.favoritable_score[scope] = favoritable.favoritable_score[scope] - 1
149
- favoritable.favoritable_score.delete(scope) unless favoritable.favoritable_score[scope] > 0
150
- favoritable.save!
151
- end
152
- if favorite = get_favorite(favoritable, scope: scope, multiple_scopes: false)
153
- results[scope] = favorite.destroy
154
- end
155
- end
156
- return results
157
- else
158
- if ActsAsFavoritor.configuration.cache
159
- self.favoritor_score[options[:scope]] = self.favoritor_score[options[:scope]] - 1
160
- self.favoritor_score.delete(options[:scope]) unless self.favoritor_score[options[:scope]] > 0
161
- self.save!
162
- favoritable.favoritable_score[options[:scope]] = favoritable.favoritable_score[options[:scope]] - 1
163
- favoritable.favoritable_score.delete(options[:scope]) unless favoritable.favoritable_score[options[:scope]] > 0
164
- favoritable.save!
165
- end
166
- if favorite = get_favorite(favoritable, scope: options[:scope], multiple_scopes: false)
167
- return favorite.destroy
168
- end
169
- end
170
- end
171
-
172
- # returns the favorite records to the current instance
173
- def favorites_scoped options = {}
174
- if options.has_key?(:multiple_scopes) == false
175
- validate_scopes __method__, options
176
- elsif options[:multiple_scopes]
177
- results = {}
178
- options[:scope].each do |scope|
179
- results[scope] = favorites.unblocked.send(scope + '_list').includes :favoritable
180
- end
181
- return results
182
- else
183
- return favorites.unblocked.send(options[:scope] + '_list').includes :favoritable
184
- end
185
- end
186
-
187
- # Returns the favorite records related to this instance by type.
188
- def favorites_by_type favoritable_type, options = {}
189
- if options.has_key?(:multiple_scopes) == false
190
- options[:parameter] = favoritable_type
191
- validate_scopes __method__, options
192
- elsif options[:multiple_scopes]
193
- results = {}
194
- options[:scope].each do |scope|
195
- favorites_scope = favorites_scoped(scope: scope, multiple_scopes: false).for_favoritable_type favoritable_type
196
- results[scope] = favorites_scope = apply_options_to_scope favorites_scope, options
197
- end
198
- return results
199
- else
200
- favorites_scope = favorites_scoped(scope: options[:scope], multiple_scopes: false).for_favoritable_type favoritable_type
201
- return favorites_scope = apply_options_to_scope(favorites_scope, options)
202
- end
203
- end
204
-
205
- # Returns the favorite records related to this instance with the favoritable included.
206
- def all_favorites options = {}
207
- if options.has_key?(:multiple_scopes) == false
208
- validate_scopes __method__, options
209
- elsif options[:multiple_scopes]
210
- results = {}
211
- options[:scope].each do |scope|
212
- favorites_scope = favorites_scoped scope: scope, multiple_scopes: false
213
- results[scope] = favorites_scope = apply_options_to_scope favorites_scope, options
214
- end
215
- return results
216
- else
217
- favorites_scope = favorites_scoped scope: options[:scope], multiple_scopes: false
218
- return favorites_scope = apply_options_to_scope(favorites_scope, options)
219
- end
220
- end
221
-
222
- # Returns the actual records which this instance has favorited.
223
- def all_favorited options = {}
224
- if options.has_key?(:multiple_scopes) == false
225
- validate_scopes __method__, options
226
- elsif options[:multiple_scopes]
227
- results = {}
228
- options[:scope].each do |scope|
229
- results[scope] = all_favorites(options).collect{ |f| f.favoritable }
230
- end
231
- return results
232
- else
233
- return all_favorites(options).collect{ |f| f.favoritable }
234
- end
235
- end
236
-
237
- # Returns the actual records of a particular type which this record has fovarited.
238
- def favorited_by_type favoritable_type, options = {}
239
- if options.has_key?(:multiple_scopes) == false
240
- options[:parameter] = favoritable_type
241
- validate_scopes __method__, options
242
- elsif options[:multiple_scopes]
243
- results = {}
244
- options[:scope].each do |scope|
245
- favoritables = favoritable_type.constantize.joins(:favorited).where('favorites.blocked': false,
246
- 'favorites.favoritor_id': id,
247
- 'favorites.favoritor_type': parent_class_name(self),
248
- 'favorites.favoritable_type': favoritable_type,
249
- 'favorites.scope': scope)
250
- if options.has_key? :limit
251
- favoritables = favoritables.limit options[:limit]
252
- end
253
- if options.has_key? :includes
254
- favoritables = favoritables.includes options[:includes]
255
- end
256
- results[scope] = favoritables
257
- end
258
- return results
259
- else
260
- favoritables = favoritable_type.constantize.joins(:favorited).where('favorites.blocked': false,
261
- 'favorites.favoritor_id': id,
262
- 'favorites.favoritor_type': parent_class_name(self),
263
- 'favorites.favoritable_type': favoritable_type,
264
- 'favorites.scope': options[:scope])
265
- if options.has_key? :limit
266
- favoritables = favoritables.limit options[:limit]
267
- end
268
- if options.has_key? :includes
269
- favoritables = favoritables.includes options[:includes]
270
- end
271
- return favoritables
272
- end
273
- end
274
-
275
- def favorited_by_type_count favoritable_type, options = {}
276
- if options.has_key?(:multiple_scopes) == false
277
- options[:parameter] = favoritable_type
278
- validate_scopes __method__, options
279
- elsif options[:multiple_scopes]
280
- results = {}
281
- options[:scope].each do |scope|
282
- results[scope] = favorites.unblocked.send(scope + '_list').for_favoritable_type(favoritable_type).count
283
- end
284
- return results
285
- else
286
- return favorites.unblocked.send(options[:scope] + '_list').for_favoritable_type(favoritable_type).count
287
- end
288
- end
289
-
290
- # Allows magic names on favorited_by_type
291
- # e.g. favorited_users == favorited_by_type 'User'
292
- # Allows magic names on favorited_by_type_count
293
- # e.g. favorited_users_count == favorited_by_type_count 'User'
294
- def method_missing m, *args
295
- if m.to_s[/favorited_(.+)_count/]
296
- favorited_by_type_count $1.singularize.classify
297
- elsif m.to_s[/favorited_(.+)/]
298
- favorited_by_type $1.singularize.classify
299
- elsif m.to_s[/favoritor_(.+)_score/]
300
- favoritor_score[$1.singularize.classify] if ActsAsFavoritor.configuration.cache
301
- elsif m.to_s[/favoritor_(.+)_total/]
302
- favoritor_total[$1.singularize.classify] if ActsAsFavoritor.configuration.cache
303
- else
304
- super
305
- end
306
- end
307
-
308
- def respond_to? m, include_private = false
309
- super || m.to_s[/favorited_(.+)_count/] || m.to_s[/favorited_(.+)/]
310
- end
311
-
312
- # Returns a favorite record for the current instance and favoritable object.
313
- def get_favorite favoritable, options = {}
314
- if options.has_key?(:multiple_scopes) == false
315
- options[:parameter] = favoritable
316
- validate_scopes __method__, options
317
- elsif options[:multiple_scopes]
318
- results = {}
319
- options[:scope].each do |scope|
320
- results[scope] = favorites.unblocked.send(scope + '_list').for_favoritable(favoritable).first
321
- end
322
- return results
323
- else
324
- return favorites.unblocked.send(options[:scope] + '_list').for_favoritable(favoritable).first
325
- end
326
- end
327
-
328
- def blocks options = {}
329
- if options.has_key?(:multiple_scopes) == false
330
- validate_scopes __method__, options
331
- elsif options[:multiple_scopes]
332
- results = {}
333
- options[:scope].each do |scope|
334
- blocked_favoritors_scope = favoritables_scoped(scope: scope, multiple_scopes: false).blocked
335
- blocked_favoritors_scope = apply_options_to_scope blocked_favoritors_scope, options
336
- results[scope] = blocked_favoritors_scope.to_a.collect{ |f| f.favoritable }
337
- end
338
- return results
339
- else
340
- blocked_favoritors_scope = favoritors_scoped(scope: options[:scope], multiple_scopes: false).blocked
341
- blocked_favoritors_scope = apply_options_to_scope blocked_favoritors_scope, options
342
- return blocked_favoritors_scope.to_a.collect{ |f| f.favoritable }
343
- end
344
- end
345
-
346
- def block favoritable, options = {}
347
- if options.has_key?(:multiple_scopes) == false
348
- options[:parameter] = favoritable
349
- validate_scopes __method__, options
350
- elsif options[:multiple_scopes]
351
- results = {}
352
- options[:scope].each do |scope|
353
- results[scope] = get_favorite(favoritable, scope: scope, multiple_scopes: false) ? block_existing_favorite(favoritable, scope: scope, multiple_scopes: false) : block_future_favorite(favoritable, scope: scope, multiple_scopes: false)
354
- end
355
- return results
356
- else
357
- return get_favorite(favoritable, scope: options[:scope], multiple_scopes: false) ? block_existing_favorite(favoritable, scope: options[:scope], multiple_scopes: false) : block_future_favorite(favoritable, scope: options[:scope], multiple_scopes: false)
358
- end
359
- end
360
-
361
- def unblock favoritable, options = {}
362
- if options.has_key?(:multiple_scopes) == false
363
- options[:parameter] = favoritable
364
- validate_scopes __method__, options
365
- elsif options[:multiple_scopes]
366
- results = {}
367
- options[:scope].each do |scope|
368
- results[scope] = get_favorite(favoritable, scope: scope, multiple_scopes: false)&.update_attribute :blocked, false
369
- end
370
- return results
371
- else
372
- return get_favorite(favoritable, scope: options[:scope], multiple_scopes: false)&.update_attribute :blocked, false
373
- end
374
- end
375
-
376
- def blocked_favoritables_count options = {}
377
- if options.has_key?(:multiple_scopes) == false
378
- validate_scopes __method__, options
379
- elsif options[:multiple_scopes]
380
- results = {}
381
- options[:scope].each do |scope|
382
- results[scope] = favorites.blocked.send(scope + '_list').count
383
- end
384
- return results
385
- else
386
- return favorites.blocked.send(options[:scope] + '_list').count
387
- end
388
- end
389
-
390
- private
391
-
392
- def block_future_favorite favoritable, options = {}
393
- if options.has_key?(:multiple_scopes) == false
394
- options[:parameter] = favoritable
395
- validate_scopes __method__, options
396
- elsif options[:multiple_scopes]
397
- results = {}
398
- options[:scope].each do |scope|
399
- results[scope] = Favorite.create favoritable: favoritable, favoritor: self, blocked: true, scope: scope
400
- end
401
- return results
402
- else
403
- return Favorite.create favoritable: favoritable, favoritor: self, blocked: true, scope: options[:scope]
404
- end
405
- end
406
-
407
- def block_existing_favorite favoritable, options = {}
408
- if options.has_key?(:multiple_scopes) == false
409
- options[:parameter] = favoritable
410
- validate_scopes __method__, options
411
- elsif options[:multiple_scopes]
412
- results = {}
413
- options[:scope].each do |scope|
414
- results[scope] = get_favorite(favoritable, scope: scope, multiple_scopes: false).block!
415
- end
416
- return results
417
- else
418
- return get_favorite(favoritable, scope: options[:scope], multiple_scopes: false).block!
419
- end
420
- end
421
-
422
- end
423
-
424
- end
425
- end
1
+ # frozen_string_literal: true
2
+
3
+ module ActsAsFavoritor
4
+ module Favoritor
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def acts_as_favoritor
11
+ has_many :favorites, as: :favoritor, dependent: :destroy
12
+ include ActsAsFavoritor::Favoritor::InstanceMethods
13
+ include ActsAsFavoritor::FavoritorLib
14
+
15
+ return unless ActsAsFavoritor.configuration&.cache
16
+ serialize :favoritor_score, Hash
17
+ serialize :favoritor_total, Hash
18
+ end
19
+ end
20
+
21
+ module InstanceMethods
22
+ # Returns true if this instance has favorited the object passed as an
23
+ # argument.
24
+ def favorited?(favoritable, options = {})
25
+ if options.key?(:multiple_scopes) == false
26
+ options[:parameter] = favoritable
27
+ validate_scopes(__method__, options)
28
+ elsif options[:multiple_scopes]
29
+ results = {}
30
+ options[:scope].each do |scope|
31
+ results[scope] = Favorite.unblocked.send(scope + '_list')
32
+ .for_favoritor(self)
33
+ .for_favoritable(favoritable).count
34
+ .positive?
35
+ end
36
+ results
37
+ else
38
+ Favorite.unblocked.send(options[:scope] + '_list').for_favoritor(self)
39
+ .for_favoritable(favoritable).count.positive?
40
+ end
41
+ end
42
+
43
+ # Returns true if this instance has blocked the object passed as an
44
+ # argument.
45
+ def blocked?(favoritable, options = {})
46
+ if options.key?(:multiple_scopes) == false
47
+ options[:parameter] = favoritable
48
+ validate_scopes(__method__, options)
49
+ elsif options[:multiple_scopes]
50
+ results = {}
51
+ options[:scope].each do |scope|
52
+ results[scope] = Favorite.blocked.send(scope + '_list')
53
+ .for_favoritor(self)
54
+ .for_favoritable(favoritable).count
55
+ .positive?
56
+ end
57
+ results
58
+ else
59
+ Favorite.blocked.send(options[:scope] + '_list').for_favoritor(self)
60
+ .for_favoritable(favoritable).count.positive?
61
+ end
62
+ end
63
+
64
+ # Returns true if this instance has favorited the object passed as an
65
+ # argument. Returns nil if this instance has not favorited the object
66
+ # passed as an argument. Returns false if this instance has blocked the
67
+ # object passed as an argument.
68
+ def favorited_type(favoritable, options = {})
69
+ if options.key?(:multiple_scopes) == false
70
+ options[:parameter] = favoritable
71
+ validate_scopes(__method__, options)
72
+ elsif options[:multiple_scopes]
73
+ results = {}
74
+ options[:scope].each do |scope|
75
+ if Favorite.unblocked.send(scope + '_list').for_favoritor(self)
76
+ .for_favoritable(favoritable).count.positive?
77
+ results[scope] = true
78
+ elsif Favorite.blocked.send(scope + '_list').for_favoritor(self)
79
+ .for_favoritable(favoritable).count.positive?
80
+ results[scope] = false
81
+ else
82
+ results[scope] = nil
83
+ end
84
+ end
85
+ results
86
+ elsif Favorite.unblocked.send(options[:scope] + '_list')
87
+ .for_favoritor(self).for_favoritable(favoritable).count
88
+ .positive?
89
+ true
90
+ elsif Favorite.blocked.send(options[:scope] + '_list')
91
+ .for_favoritor(self).for_favoritable(favoritable).count
92
+ .positive?
93
+ false
94
+ end
95
+ end
96
+
97
+ # Returns the number of objects this instance has favorited.
98
+ def favorites_count(options = {})
99
+ if options.key?(:multiple_scopes) == false
100
+ validate_scopes(__method__, options)
101
+ elsif options[:multiple_scopes]
102
+ results = {}
103
+ options[:scope].each do |scope|
104
+ results[scope] = Favorite.unblocked.send(scope + '_list')
105
+ .for_favoritor(self).count
106
+ end
107
+ results
108
+ else
109
+ Favorite.unblocked.send(options[:scope] + '_list')
110
+ .for_favoritor(self).count
111
+ end
112
+ end
113
+
114
+ # Creates a new favorite record for this instance to favorite the passed
115
+ # object. Does not allow duplicate records to be created.
116
+ def favorite(favoritable, options = {})
117
+ if options.key?(:multiple_scopes) == false
118
+ options[:parameter] = favoritable
119
+ validate_scopes(__method__, options)
120
+ elsif options[:multiple_scopes]
121
+ results = {}
122
+ options[:scope].each do |scope|
123
+ if ActsAsFavoritor.configuration.cache
124
+ favoritor_score[scope] = (favoritor_score[scope] || 0) + 1
125
+ favoritor_total[scope] = (favoritor_total[scope] || 0) + 1
126
+ save!
127
+ favoritable.favoritable_score[scope] =
128
+ (favoritable.favoritable_score[scope] || 0) + 1
129
+ favoritable.favoritable_total[scope] =
130
+ (favoritable.favoritable_total[scope] || 0) + 1
131
+ favoritable.save!
132
+ end
133
+ next unless self != favoritable && scope != 'all'
134
+ params = {
135
+ favoritable_id: favoritable.id,
136
+ favoritable_type: parent_class_name(favoritable),
137
+ scope: scope
138
+ }
139
+ results[scope] = favorites.where(params).first_or_create!
140
+ end
141
+ results
142
+ else
143
+ if ActsAsFavoritor.configuration.cache
144
+ favoritor_score[options[:scope]] =
145
+ (favoritor_score[options[:scope]] || 0) + 1
146
+ favoritor_total[options[:scope]] =
147
+ (favoritor_total[options[:scope]] || 0) + 1
148
+ save!
149
+ favoritable.favoritable_score[options[:scope]] =
150
+ (favoritable.favoritable_score[options[:scope]] || 0) + 1
151
+ favoritable.favoritable_total[options[:scope]] =
152
+ (favoritable.favoritable_total[options[:scope]] || 0) + 1
153
+ favoritable.save!
154
+ end
155
+ if self != favoritable && options[:scope] != 'all'
156
+ params = {
157
+ favoritable_id: favoritable.id,
158
+ favoritable_type: parent_class_name(favoritable),
159
+ scope: options[:scope]
160
+ }
161
+ favorites.where(params).first_or_create!
162
+ end
163
+ end
164
+ end
165
+
166
+ # Deletes the favorite record if it exists.
167
+ def remove_favorite(favoritable, options = {})
168
+ if options.key?(:multiple_scopes) == false
169
+ options[:parameter] = favoritable
170
+ validate_scopes(__method__, options)
171
+ elsif options[:multiple_scopes]
172
+ results = {}
173
+ options[:scope].each do |scope|
174
+ if ActsAsFavoritor.configuration.cache
175
+ favoritor_score[scope] = favoritor_score[scope] - 1
176
+ unless favoritor_score[scope].positive?
177
+ favoritor_score.delete(scope)
178
+ end
179
+ save!
180
+ favoritable.favoritable_score[scope] =
181
+ favoritable.favoritable_score[scope] - 1
182
+ unless favoritable.favoritable_score[scope].positive?
183
+ favoritable.favoritable_score.delete(scope)
184
+ end
185
+ favoritable.save!
186
+ end
187
+ favorite = get_favorite(
188
+ favoritable, scope: scope, multiple_scopes: false
189
+ )
190
+ results[scope] = favorite.destroy if favorite
191
+ end
192
+ results
193
+ else
194
+ if ActsAsFavoritor.configuration.cache
195
+ favoritor_score[options[:scope]] =
196
+ favoritor_score[options[:scope]] - 1
197
+ unless favoritor_score[options[:scope]].positive?
198
+ favoritor_score.delete(options[:scope])
199
+ end
200
+ save!
201
+ favoritable.favoritable_score[options[:scope]] =
202
+ favoritable.favoritable_score[options[:scope]] - 1
203
+ unless favoritable.favoritable_score[options[:scope]].positive?
204
+ favoritable.favoritable_score.delete(options[:scope])
205
+ end
206
+ favoritable.save!
207
+ end
208
+ favorite = get_favorite(
209
+ favoritable, scope: options[:scope], multiple_scopes: false
210
+ )
211
+ favorite&.destroy
212
+ end
213
+ end
214
+
215
+ # returns the favorite records to the current instance
216
+ def favorites_scoped(options = {})
217
+ if options.key?(:multiple_scopes) == false
218
+ validate_scopes(__method__, options)
219
+ elsif options[:multiple_scopes]
220
+ results = {}
221
+ options[:scope].each do |scope|
222
+ results[scope] = favorites.unblocked.send(scope + '_list')
223
+ .includes(:favoritable)
224
+ end
225
+ results
226
+ else
227
+ favorites.unblocked.send(options[:scope] + '_list')
228
+ .includes(:favoritable)
229
+ end
230
+ end
231
+
232
+ # Returns the favorite records related to this instance by type.
233
+ def favorites_by_type(favoritable_type, options = {})
234
+ if options.key?(:multiple_scopes) == false
235
+ options[:parameter] = favoritable_type
236
+ validate_scopes(__method__, options)
237
+ elsif options[:multiple_scopes]
238
+ results = {}
239
+ options[:scope].each do |scope|
240
+ favorites_scope = favorites_scoped(
241
+ scope: scope, multiple_scopes: false
242
+ ).for_favoritable_type(favoritable_type)
243
+ results[scope] = apply_options_to_scope(
244
+ favorites_scope, options
245
+ )
246
+ end
247
+ results
248
+ else
249
+ favorites_scope = favorites_scoped(
250
+ scope: options[:scope], multiple_scopes: false
251
+ ).for_favoritable_type(favoritable_type)
252
+ apply_options_to_scope(
253
+ favorites_scope, options
254
+ )
255
+ end
256
+ end
257
+
258
+ # Returns the favorite records related to this instance with the
259
+ # favoritable included.
260
+ def all_favorites(options = {})
261
+ if options.key?(:multiple_scopes) == false
262
+ validate_scopes(__method__, options)
263
+ elsif options[:multiple_scopes]
264
+ results = {}
265
+ options[:scope].each do |scope|
266
+ favorites_scope = favorites_scoped(
267
+ scope: scope, multiple_scopes: false
268
+ )
269
+ results[scope] = apply_options_to_scope(
270
+ favorites_scope, options
271
+ )
272
+ end
273
+ results
274
+ else
275
+ favorites_scope = favorites_scoped(
276
+ scope: options[:scope], multiple_scopes: false
277
+ )
278
+ apply_options_to_scope(
279
+ favorites_scope, options
280
+ )
281
+ end
282
+ end
283
+
284
+ # Returns the actual records which this instance has favorited.
285
+ def all_favorited(options = {})
286
+ if options.key?(:multiple_scopes) == false
287
+ validate_scopes(__method__, options)
288
+ elsif options[:multiple_scopes]
289
+ results = {}
290
+ options[:scope].each do |scope|
291
+ results[scope] = all_favorites(options).collect(&:favoritable)
292
+ end
293
+ results
294
+ else
295
+ all_favorites(options).collect(&:favoritable)
296
+ end
297
+ end
298
+
299
+ # Returns the actual records of a particular type which this record has
300
+ # favorited.
301
+ def favorited_by_type(favoritable_type, options = {})
302
+ if options.key?(:multiple_scopes) == false
303
+ options[:parameter] = favoritable_type
304
+ validate_scopes(__method__, options)
305
+ elsif options[:multiple_scopes]
306
+ results = {}
307
+ options[:scope].each do |scope|
308
+ favoritables = favoritable_type.constantize.joins(:favorited)
309
+ favoritables = favoritables.where(
310
+ 'favorites.blocked': false,
311
+ 'favorites.favoritor_id': id,
312
+ 'favorites.favoritor_type': parent_class_name(self),
313
+ 'favorites.favoritable_type': favoritable_type,
314
+ 'favorites.scope': scope
315
+ )
316
+ if options.key?(:limit)
317
+ favoritables = favoritables.limit options[:limit]
318
+ end
319
+ if options.key?(:includes)
320
+ favoritables = favoritables.includes options[:includes]
321
+ end
322
+ results[scope] = favoritables
323
+ end
324
+ results
325
+ else
326
+ favoritables = favoritable_type.constantize.joins(:favorited)
327
+ favoritables = favoritables.where(
328
+ 'favorites.blocked': false,
329
+ 'favorites.favoritor_id': id,
330
+ 'favorites.favoritor_type': parent_class_name(self),
331
+ 'favorites.favoritable_type': favoritable_type,
332
+ 'favorites.scope': options[:scope]
333
+ )
334
+ if options.key? :limit
335
+ favoritables = favoritables.limit options[:limit]
336
+ end
337
+ if options.key? :includes
338
+ favoritables = favoritables.includes options[:includes]
339
+ end
340
+ favoritables
341
+ end
342
+ end
343
+
344
+ def favorited_by_type_count(favoritable_type, options = {})
345
+ if options.key?(:multiple_scopes) == false
346
+ options[:parameter] = favoritable_type
347
+ validate_scopes(__method__, options)
348
+ elsif options[:multiple_scopes]
349
+ results = {}
350
+ options[:scope].each do |scope|
351
+ results[scope] = favorites.unblocked
352
+ .send(scope + '_list')
353
+ .for_favoritable_type(favoritable_type)
354
+ .count
355
+ end
356
+ results
357
+ else
358
+ favorites.unblocked.send(options[:scope] + '_list')
359
+ .for_favoritable_type(favoritable_type).count
360
+ end
361
+ end
362
+
363
+ # Allows magic names on favorited_by_type
364
+ # e.g. favorited_users == favorited_by_type 'User'
365
+ # Allows magic names on favorited_by_type_count
366
+ # e.g. favorited_users_count == favorited_by_type_count 'User'
367
+ def method_missing(method, *args)
368
+ if method.to_s[/favorited_(.+)_count/]
369
+ favorited_by_type_count $1.singularize.classify
370
+ elsif method.to_s[/favorited_(.+)/]
371
+ favorited_by_type $1.singularize.classify
372
+ elsif ActsAsFavoritor.configuration.cache &&
373
+ method.to_s[/favoritor_(.+)_score/]
374
+ favoritor_score[$1.singularize.classify]
375
+ elsif ActsAsFavoritor.configuration.cache &&
376
+ method.to_s[/favoritor_(.+)_total/]
377
+ favoritor_total[$1.singularize.classify]
378
+ else
379
+ super
380
+ end
381
+ end
382
+
383
+ def respond_to_missing?(method, include_private = false)
384
+ super || method.to_s[/favorited_(.+)_count/] ||
385
+ method.to_s[/favorited_(.+)/]
386
+ end
387
+
388
+ # Returns a favorite record for the current instance and favoritable
389
+ # object.
390
+ def get_favorite(favoritable, options = {})
391
+ if options.key?(:multiple_scopes) == false
392
+ options[:parameter] = favoritable
393
+ validate_scopes(__method__, options)
394
+ elsif options[:multiple_scopes]
395
+ results = {}
396
+ options[:scope].each do |scope|
397
+ results[scope] = favorites.unblocked.send(scope + '_list')
398
+ .for_favoritable(favoritable).first
399
+ end
400
+ results
401
+ else
402
+ favorites.unblocked.send(options[:scope] + '_list')
403
+ .for_favoritable(favoritable).first
404
+ end
405
+ end
406
+
407
+ def blocks(options = {})
408
+ if options.key?(:multiple_scopes) == false
409
+ validate_scopes(__method__, options)
410
+ elsif options[:multiple_scopes]
411
+ results = {}
412
+ options[:scope].each do |scope|
413
+ blocked_favoritors_scope = favoritables_scoped(
414
+ scope: scope, multiple_scopes: false
415
+ ).blocked
416
+ blocked_favoritors_scope = apply_options_to_scope(
417
+ blocked_favoritors_scope, options
418
+ )
419
+ results[scope] = blocked_favoritors_scope.to_a
420
+ .collect(&:favoritable)
421
+ end
422
+ results
423
+ else
424
+ blocked_favoritors_scope = favoritors_scoped(
425
+ scope: options[:scope], multiple_scopes: false
426
+ ).blocked
427
+ blocked_favoritors_scope = apply_options_to_scope(
428
+ blocked_favoritors_scope, options
429
+ )
430
+ blocked_favoritors_scope.to_a.collect(&:favoritable)
431
+ end
432
+ end
433
+
434
+ def block(favoritable, options = {})
435
+ if options.key?(:multiple_scopes) == false
436
+ options[:parameter] = favoritable
437
+ validate_scopes(__method__, options)
438
+ elsif options[:multiple_scopes]
439
+ results = {}
440
+ options[:scope].each do |scope|
441
+ favorite = get_favorite(
442
+ favoritable, scope: scope, multiple_scopes: false
443
+ )
444
+ if favorite
445
+ results[scope] = block_existing_favorite(
446
+ favoritable, scope: scope, multiple_scopes: false
447
+ )
448
+ else
449
+ results[scope] = block_future_favorite(
450
+ favoritable, scope: scope, multiple_scopes: false
451
+ )
452
+ end
453
+ end
454
+ results
455
+ else
456
+ favorite = get_favorite(
457
+ favoritable, scope: options[:scope], multiple_scopes: false
458
+ )
459
+ if favorite
460
+ block_existing_favorite(
461
+ favoritable, scope: options[:scope], multiple_scopes: false
462
+ )
463
+ else
464
+ block_future_favorite(
465
+ favoritable, scope: options[:scope], multiple_scopes: false
466
+ )
467
+ end
468
+ end
469
+ end
470
+
471
+ def unblock(favoritable, options = {})
472
+ if options.key?(:multiple_scopes) == false
473
+ options[:parameter] = favoritable
474
+ validate_scopes(__method__, options)
475
+ elsif options[:multiple_scopes]
476
+ results = {}
477
+ options[:scope].each do |scope|
478
+ results[scope] = get_favorite(
479
+ favoritable, scope: scope, multiple_scopes: false
480
+ )&.update_attribute :blocked, false
481
+ end
482
+ results
483
+ else
484
+ get_favorite(
485
+ favoritable, scope: options[:scope], multiple_scopes: false
486
+ )&.update_attribute :blocked, false
487
+ end
488
+ end
489
+
490
+ def blocked_favoritables_count(options = {})
491
+ if options.key?(:multiple_scopes) == false
492
+ validate_scopes(__method__, options)
493
+ elsif options[:multiple_scopes]
494
+ results = {}
495
+ options[:scope].each do |scope|
496
+ results[scope] = favorites.blocked.send(scope + '_list').count
497
+ end
498
+ results
499
+ else
500
+ favorites.blocked.send(options[:scope] + '_list').count
501
+ end
502
+ end
503
+
504
+ private
505
+
506
+ def block_future_favorite(favoritable, options = {})
507
+ if options.key?(:multiple_scopes) == false
508
+ options[:parameter] = favoritable
509
+ validate_scopes(__method__, options)
510
+ elsif options[:multiple_scopes]
511
+ results = {}
512
+ options[:scope].each do |scope|
513
+ results[scope] = Favorite.create(
514
+ favoritable: favoritable,
515
+ favoritor: self,
516
+ blocked: true,
517
+ scope: scope
518
+ )
519
+ end
520
+ results
521
+ else
522
+ Favorite.create(
523
+ favoritable: favoritable,
524
+ favoritor: self,
525
+ blocked: true,
526
+ scope: options[:scope]
527
+ )
528
+ end
529
+ end
530
+
531
+ def block_existing_favorite(favoritable, options = {})
532
+ if options.key?(:multiple_scopes) == false
533
+ options[:parameter] = favoritable
534
+ validate_scopes(__method__, options)
535
+ elsif options[:multiple_scopes]
536
+ results = {}
537
+ options[:scope].each do |scope|
538
+ results[scope] = get_favorite(
539
+ favoritable, scope: scope, multiple_scopes: false
540
+ ).block!
541
+ end
542
+ results
543
+ else
544
+ get_favorite(
545
+ favoritable, scope: options[:scope], multiple_scopes: false
546
+ ).block!
547
+ end
548
+ end
549
+ end
550
+ end
551
+ end