A Rails gem to track likes between two ActiveModel
compliant models. A common use case might be that a User likes a Post.
Installation
Add this line to your application's Gemfile:
gem 'likes_tracker'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install likes_tracker
Dependencies
- redis
- ruby 1.9+ (it uses some 1.9's syntax)
Usage
First of all, you need a $redis
in your app, you might achieve this using an initializer:
# config/initializers/redis.rb
$redis = Redis.new(host: 'localhost', port: '6379', db: '1')
Given you have two models, say User and Post, and you want to track the likes a given Post receives by User(s). Include the LikesTracker module and use the methods it offers to setup models as liker and liked:
# app/models/post.rb
class Post < ActiveRecord::Base
include LikesTracker
acts_as_liked_by :users
# rest of the code
end
# app/models/user.rb
class User < ActiveRecord::Base
include LikesTracker
acts_as_liker_for :posts
# rest of the code
end
Now your models will have some methods to manage the likes a model gives to another. Following the above example:
> user.likes_post? post
=> false
> user.liked_posts
=> []
> post.likes_users_count
=> 0
> user.like_post! post
=> [true, true, 1.0]
> user.likes_post? post
=> true
As you can see, the methods' names reflect model names (and they'll be properly namespaced on Redis). This means, that the same models can like several others, for example User might like another model called Photo or Comment, so you'll have methods like #like_comment!
or #likes_photo?
and so on.
How to find Posts liked by a User? There's a method for this, of course ;-)
> user.liked_posts
=> [#<Post id: 1, ...>]
It returns a relation, such as ActiveRecord::Relation
. Even if I haven't tested it yet, this should work with other ORMs like Mongoid.
# a silly example to show how it works
> user.liked_posts {|model, ids| p [model, ids] }
=> [Post(id: integer, ...), ["1"]]
# the query executed by default
> user.liked_posts {|model, ids| model.where(id: ids) }
=> [#<Post id: 1, ...>]
Last but not least, here there're the remaining methods and examples:
# you can provide a *limit* parameter, if omitted it defaults to 5
> Post.most_liked(5)
=> [#<Post id: 1, ...>]
# and it also accepts an *offset* parameter, if omitted it defaults to 0
> Post.most_liked(5, 0)
=> [#<Post id: 1, ...>]
# last but not least, it accepts a block, like you've already seen in above examples
> Post.most_liked(5, 0) {|model, ids| p [model, ids] }
=> [Post(id: integer, ...), ["1"]]
> post.likes_users_count
=> 1
> user.unlike_post! post
=> [true, true, 0.0]
> user.likes_post? post
=> false
> user.liked_posts
=> []
> post.likes_users_count
=> 0
Contributing
- Fork it!
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Testing
- clone this repo
- run
bundle install
- run
rspec spec
License
Copyright (c) 2012 Andrea Pavoni http://andreapavoni.com