README.markdown in acts_as_votable-0.10.0 vs README.markdown in acts_as_votable-0.11.0

- old
+ new

@@ -1,8 +1,9 @@ # Acts As Votable (aka Acts As Likeable) [![Build Status](https://travis-ci.org/ryanto/acts_as_votable.png)](https://travis-ci.org/ryanto/acts_as_votable) +[![Code Climate](https://codeclimate.com/github/ryanto/acts_as_votable.png)](https://codeclimate.com/github/ryanto/acts_as_votable) Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models. The main goals of this gem are: - Allow any model to be voted on, like/dislike, upvote/downvote, etc. @@ -13,18 +14,17 @@ ## Installation ### Supported Ruby and Rails versions -* Ruby 1.8.7, 1.9.2, 1.9.3 -* Ruby 2.0.0, 2.1.0 -* Rails 3.0, 3.1, 3.2 +* Ruby 2.2.0, 2.3.0 and 2.4.0 * Rails 4.0, 4.1+ +* Rails 5.0, 5.1 ### Install -Just add the following to your Gemfile. +Just add the following to your Gemfile to install the latest release. ```ruby gem 'acts_as_votable', '~> 0.10.0' ``` @@ -94,24 +94,26 @@ @post.downvote_from @user2 @post.vote_by :voter => @user2, :vote => 'bad' # tally them up! @post.votes_for.size # => 5 +@post.weighted_total => 5 @post.get_likes.size # => 3 @post.get_upvotes.size # => 3 @post.get_dislikes.size # => 2 @post.get_downvotes.size # => 2 +@post.weighted_score => 1 ``` Active Record scopes are provided to make life easier. ```ruby @post.votes_for.up.by_type(User) @post.votes_for.down @user1.votes.up @user1.votes.down -@user1.votes.up.by_type(Post) +@user1.votes.up.for_type(Post) ``` Once scoping is complete, you can also trigger a get for the voter/votable @@ -135,11 +137,11 @@ Unvoting works for both positive and negative votes. ### Examples with scopes -You can add an scope to your vote +You can add a scope to your vote ```ruby # positive votes @post.liked_by @user1, :vote_scope => 'rank' @post.vote_by :voter => @user3, :vote_scope => 'rank' @@ -213,13 +215,13 @@ @user.voted_for? @comment1 # => true @user.voted_for? @comment2 # => true @user.voted_for? @comment3 # => false -@user.voted_as_when_voted_for @comment1 # => true, he liked it -@user.voted_as_when_voted_for @comment2 # => false, he didnt like it -@user.voted_as_when_voted_for @comment3 # => nil, he has yet to vote +@user.voted_as_when_voted_for @comment1 # => true, user liked it +@user.voted_as_when_voted_for @comment2 # => false, user didnt like it +@user.voted_as_when_voted_for @comment3 # => nil, user has yet to vote ``` You can also check whether the voter has voted up or down. ```ruby @@ -315,16 +317,18 @@ add_column :posts, :cached_votes_score, :integer, :default => 0 add_column :posts, :cached_votes_up, :integer, :default => 0 add_column :posts, :cached_votes_down, :integer, :default => 0 add_column :posts, :cached_weighted_score, :integer, :default => 0 add_column :posts, :cached_weighted_total, :integer, :default => 0 + add_column :posts, :cached_weighted_average, :float, :default => 0.0 add_index :posts, :cached_votes_total add_index :posts, :cached_votes_score add_index :posts, :cached_votes_up add_index :posts, :cached_votes_down add_index :posts, :cached_weighted_score add_index :posts, :cached_weighted_total + add_index :posts, :cached_weighted_average # Uncomment this line to force caching of existing votes # Post.find_each(&:update_cached_votes) end @@ -333,14 +337,78 @@ remove_column :posts, :cached_votes_score remove_column :posts, :cached_votes_up remove_column :posts, :cached_votes_down remove_column :posts, :cached_weighted_score remove_column :posts, :cached_weighted_total + remove_column :posts, :cached_weighted_average end end ``` +If you have a scope for your vote, let's say `subscribe`, your migration will be slightly different like below: + +```ruby +class AddCachedVotesToPosts < ActiveRecord::Migration + def self.up + add_column :posts, :cached_scoped_subscribe_votes_total, :integer, :default => 0 + add_column :posts, :cached_scoped_subscribe_votes_score, :integer, :default => 0 + add_column :posts, :cached_scoped_subscribe_votes_up, :integer, :default => 0 + add_column :posts, :cached_scoped_subscribe_votes_down, :integer, :default => 0 + add_column :posts, :cached_weighted_subscribe_score, :integer, :default => 0 + add_column :posts, :cached_weighted_subscribe_total, :integer, :default => 0 + add_column :posts, :cached_weighted_subscribe_average, :float, :default => 0.0 + add_index :posts, :cached_scoped_subscribe_votes_total + add_index :posts, :cached_scoped_subscribe_votes_score + add_index :posts, :cached_scoped_subscribe_votes_up + add_index :posts, :cached_scoped_subscribe_votes_down + add_index :posts, :cached_weighted_subscribe_score + add_index :posts, :cached_weighted_subscribe_total + add_index :posts, :cached_weighted_subscribe_average + end + + def self.down + remove_column :posts, :cached_scoped_subscribe_votes_total + remove_column :posts, :cached_scoped_subscribe_votes_score + remove_column :posts, :cached_scoped_subscribe_votes_up + remove_column :posts, :cached_scoped_subscribe_votes_down + remove_column :posts, :cached_weighted_subscribe_score + remove_column :posts, :cached_weighted_subscribe_total + remove_column :posts, :cached_weighted_subscribe_average + end +end +``` + +`cached_weighted_average` can be helpful for a rating system, e.g.: + +Order by average rating: + +```ruby +Post.order(:cached_weighted_average => :desc) +``` + +Display average rating: + +```erb +<%= post.weighted_average.round(2) %> / 5 +<!-- 3.5 / 5 --> +``` +## updated_at at Votable model + +You can control whether `updated_at` column of votable model will be touched or +not by passing `cacheable_strategy` option to `acts_as_votable` method. + +By default, `update_attributes` strategy is used. Pass `:update_columns` as +`cacheable_strategy` if you don't want to touch model's `updated_at` column. +```ruby +class Post < ActiveRecord::Base + acts_as_votable cacheable_strategy: :update_columns +end +``` + +NOTE: this option does not work for ActiveRecord < 3.1 + + ## Testing All tests follow the RSpec format and are located in the spec directory. They can be run with: @@ -350,11 +418,11 @@ ## Changes ### Fixes for votable voter model -In version 0.8.0, there is bugs for a model that is both votable and voter. +In version 0.8.0, there are bugs for a model that is both votable and voter. Some name-conflicting methods are renamed: + Renamed Votable.votes to votes_for + Renamed Votable.vote to vote_by, + Removed Votable.vote_by alias (was an alias for :vote_up) + Renamed Votable.unvote_for to unvote_by @@ -368,19 +436,18 @@ ## License Acts as votable is released under the [MIT License](http://www.opensource.org/licenses/MIT). -## TODO +## Next steps - Pass in a block of options when creating acts_as. Allow for things like disabling the aliasing - Smarter language syntax. Example: `@user.likes` will return all of the votables that the user likes, while `@user.likes @model` will cast a vote for @model by @user. - - The aliased methods are referred to by using the terms 'up/down' and/or -'true/false'. Need to come up with guidelines for naming these methods. +'true/false'. Need to come up with guidelines for naming these methods. - Create more aliases. Specifically for counting votes and finding votes.