Module: Recommendable::ActsAsRecommendedTo::RecommendationMethods
- Defined in:
- lib/recommendable/acts_as_recommended_to.rb
Instance Method Summary collapse
-
#common_dislikes_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects the sets of dislikes belonging to self and rater.
-
#common_likes_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects the sets of likes belonging to self and rater.
-
#completely_unrecommend(object) ⇒ Object
Used internally during liking/disliking/stashing/ignoring objects.
-
#disagreements_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects self’s set of likes with rater’s set of dislikes and vise versa.
-
#probability_of_disliking(object) ⇒ Float
Return the negation of the value calculated by #predict on self for a passed object.
-
#probability_of_liking(object) ⇒ Float
Return the value calculated by #predict on self for a passed object.
-
#rated?(object) ⇒ Boolean
Checks to see if self has already liked or disliked a passed object.
-
#rated_anything? ⇒ Boolean
Checks to see if self has liked or disliked any objects yet.
-
#recommendations(options = {}) ⇒ Array
Get a list of recommendations for self.
-
#recommendations_for(klass, options = {}) ⇒ Array
Get a list of recommendations for self on a single recommendable type.
-
#similar_raters(options = {}) ⇒ Array
Get a list of raters that have been found to be the most similar to self.
Instance Method Details
#common_dislikes_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects the sets of dislikes belonging to self and rater.
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 436 def common_dislikes_with(rater, = {}) defaults = { :class => nil, :return_records => true } = defaults.merge() create_recommended_to_sets and rater.create_recommended_to_sets if [:return_records] if [:class] in_common = Recommendable.redis.sinter dislikes_set_for([:class]), rater.dislikes_set_for([:class]) in_common = [:class].to_s.classify.constantize.find in_common if [:return_records] else in_common = Recommendable.recommendable_classes.flat_map do |klass| things = Recommendable.redis.sinter(dislikes_set_for(klass), rater.dislikes_set_for(klass)) if [:return_records] klass.to_s.classify.constantize.find(things) else things.map {|id| "#{klass.to_s.classify}:#{id}"} end end end destroy_recommended_to_sets and rater.destroy_recommended_to_sets if [:return_records] in_common end |
#common_likes_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects the sets of likes belonging to self and rater.
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 403 def common_likes_with(rater, = {}) defaults = { :class => nil, :return_records => true } = defaults.merge() create_recommended_to_sets and rater.create_recommended_to_sets if [:return_records] if [:class] in_common = Recommendable.redis.sinter likes_set_for([:class]), rater.likes_set_for([:class]) in_common = [:class].to_s.classify.constantize.find in_common if [:return_records] else in_common = Recommendable.recommendable_classes.flat_map do |klass| things = Recommendable.redis.sinter(likes_set_for(klass), rater.likes_set_for(klass)) if [:return_records] klass.to_s.classify.constantize.find(things) else things.map {|id| "#{klass.to_s.classify}:#{id}"} end end end destroy_recommended_to_sets and rater.destroy_recommended_to_sets if [:return_records] in_common end |
#completely_unrecommend(object) ⇒ Object
Used internally during liking/disliking/stashing/ignoring objects. This will prep an object to be liked, disliked, etc. by making sure that self doesn’t already have this item in their list of likes, dislikes, stashed items or ignored items.
param [Object] object the object to destroy Recommendable models for
505 506 507 508 509 510 511 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 505 def completely_unrecommend(object) unlike(object) undislike(object) unstash(object) unignore(object) unpredict(object) end |
#disagreements_with(rater, options = {}) ⇒ Array
Makes a call to Redis and intersects self’s set of likes with rater’s set of dislikes and vise versa. The idea here is that if self likes an object that rater dislikes, it is a disagreement and should count negatively towards their similarity.
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 471 def disagreements_with(rater, = {}) defaults = { :class => nil, :return_records => true } = defaults.merge() create_recommended_to_sets and rater.create_recommended_to_sets if [:return_records] if [:class] disagreements = Recommendable.redis.sinter(likes_set_for([:class]), rater.dislikes_set_for([:class])) disagreements += Recommendable.redis.sinter(dislikes_set_for([:class]), rater.likes_set_for([:class])) disagreements = [:class].to_s.classify.constantize.find disagreements if [:return_records] else disagreements = Recommendable.recommendable_classes.flat_map do |klass| things = Recommendable.redis.sinter(likes_set_for(klass), rater.dislikes_set_for(klass)) things += Recommendable.redis.sinter(dislikes_set_for(klass), rater.likes_set_for(klass)) if [:return_records] klass.to_s.classify.constantize.find(things) else things.map {|id| "#{[:class].to_s.classify}:#{id}"} end end end destroy_recommended_to_sets and rater.destroy_recommended_to_sets if [:return_records] disagreements end |
#probability_of_disliking(object) ⇒ Float
Return the negation of the value calculated by #predict on self for a passed object.
391 392 393 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 391 def probability_of_disliking(object) -probability_of_liking(object) end |
#probability_of_liking(object) ⇒ Float
Return the value calculated by #predict on self for a passed object.
381 382 383 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 381 def probability_of_liking(object) Recommendable.redis.zscore predictions_set_for(object.class), object.redis_key end |
#rated?(object) ⇒ Boolean
Checks to see if self has already liked or disliked a passed object.
295 296 297 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 295 def rated?(object) likes?(object) || dislikes?(object) end |
#rated_anything? ⇒ Boolean
Checks to see if self has liked or disliked any objects yet.
302 303 304 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 302 def rated_anything? likes.count > 0 || dislikes.count > 0 end |
#recommendations(options = {}) ⇒ Array
Get a list of recommendations for self. The whole point of this gem! Recommendations are returned in a descending order with the first index being the object that self has been found most likely to enjoy.
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 333 def recommendations( = {}) defaults = { :count => 10 } = defaults.merge return [] if likes.count + dislikes.count == 0 unioned_predictions = "#{self.class}:#{id}:predictions" Recommendable.redis.zunionstore unioned_predictions, Recommendable.recommendable_classes.map {|klass| predictions_set_for(klass)} recommendations = Recommendable.redis.zrevrange(unioned_predictions, 0, [:count]).map do |object| klass, id = object.split(":") klass.constantize.find(id) end Recommendable.redis.del(unioned_predictions) and return recommendations end |
#recommendations_for(klass, options = {}) ⇒ Array
Get a list of recommendations for self on a single recommendable type. Recommendations are returned in a descending order with the first index being the object that self has been found most likely to enjoy.
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 357 def recommendations_for(klass, = {}) defaults = { :count => 10 } = defaults.merge return [] if likes_for(klass).count + dislikes_for(klass).count == 0 || Recommendable.redis.zcard(predictions_set_for(klass)) == 0 recommendations = [] i = 0 until recommendations.size == [:count] prediction = Recommendable.redis.zrevrange(predictions_set_for(klass), i, i).first return recommendations unless prediction # User might not have enough recommendations to return object = klass.to_s.classify.constantize.find(prediction.split(":")[1]) recommendations << object i += 1 end return recommendations end |
#similar_raters(options = {}) ⇒ Array
Get a list of raters that have been found to be the most similar to self. They are sorted in a descending fashion with the most similar rater in the first index.
313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/recommendable/acts_as_recommended_to.rb', line 313 def similar_raters( = {}) defaults = { :count => 10 } = defaults.merge() rater_ids = Recommendable.redis.zrevrange(similarity_set, 0, [:count] - 1).map(&:to_i) raters = Recommendable.user_class.where("ID IN (?)", rater_ids) # The query loses the ordering, so... return raters.sort do |x, y| rater_ids.index(x.id) <=> rater_ids.index(y.id) end end |