acts_as_favoritor 2.0.1 → 2.1.0

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.
@@ -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