VoteFu brings first-class Turbo Streams, ViewComponents, and view helpers to your voting system. Built-in ranking algorithms. Zero external dependencies.
# Gemfile
gem 'vote_fu', '~> 2.0'
# Then run:
rails generate vote_fu:install
rails db:migrate
Not a port from 2010. Designed from the ground up for Rails 8, Hotwire, and modern patterns.
Every vote action returns Turbo Stream responses by default. Mount the engine and get seamless updates with zero JavaScript.
Drop-in components for vote widgets, star ratings, and emoji reaction bars. Fully customizable with CSS variables.
Up/down votes, star ratings (1-5), weighted votes, or emoji reactions. One gem handles all voting patterns.
Wilson Score, Reddit Hot, and Hacker News ranking built-in. No external gems required.
Same user can cast multiple independent votes in different contexts. Rate helpfulness AND quality on the same item.
Calculate user reputation from votes on their content. Built-in support for author karma across multiple models.
The voting gem landscape hasn't kept up with Rails. We're changing that.
| Feature | ThumbsUp | Votable | VoteFu 2.0 |
|---|---|---|---|
| Rails 8 Support | No | No | Yes |
| Vote Values | Boolean | Integer | Integer |
| Turbo Streams | No | No | Native |
| ViewComponents | No | No | Included |
| View Helpers | No | No | Included |
| Counter Cache | No | Running total | Both |
| Scoped Voting | No | Yes | Yes |
| Karma System | No | No | Built-in |
| Wilson Score | External gem | No | Built-in |
| Hot Ranking | No | No | Built-in |
Everything you need, nothing you don't.
class Post < ApplicationRecord
acts_as_voteable
end
class User < ApplicationRecord
acts_as_voter
has_karma :posts, as: :author
end
# Simple voting
user.upvote(post)
user.downvote(post)
user.toggle_vote(post)
user.unvote(post)
# Star ratings
user.vote_on(post, value: 5)
# Scoped voting
user.vote_on(review, value: 5, scope: :quality)
user.vote_on(review, value: 1, scope: :helpfulness)
# On voteables
post.votes_for # Upvotes
post.votes_against # Downvotes
post.plusminus # Net score
post.wilson_score # Ranking (0.0-1.0)
post.voted_by?(user)
# On voters
user.voted_on?(post)
user.vote_value_for(post)
user.karma
# Order by votes
Post.by_votes
Post.by_wilson_score
Post.trending # Last 24h
Post.with_positive_score
# Scoped queries
review.plusminus(scope: :quality)
review.plusminus(scope: :helpfulness)
<%# Reddit-style widget %>
<%= vote_widget @post %>
<%# Simple like button %>
<%= like_button @photo %>
<%# Scoped voting %>
<%= vote_widget @review, scope: :quality %>
<%= vote_widget @review, scope: :helpfulness %>
<%# Star rating %>
<%= render VoteFu::StarRatingComponent.new(
voteable: @product,
voter: current_user,
show_average: true,
show_count: true
) %>
<%# Emoji reactions (Slack/GitHub style) %>
<%= render VoteFu::ReactionBarComponent.new(
voteable: @comment,
voter: current_user,
reactions: [
{ emoji: "👍", scope: "like" },
{ emoji: "❤️", scope: "love" },
{ emoji: "🎉", scope: "celebrate" }
]
) %>
Configure behavior and style with simple APIs.
# config/initializers/vote_fu.rb
VoteFu.configure do |config|
config.allow_recast = true
config.allow_self_vote = false
config.counter_cache = true
config.turbo_broadcasts = true
config.default_ranking = :wilson_score
config.hot_ranking_gravity = 1.8
end
# config/routes.rb
Rails.application.routes.draw do
mount VoteFu::Engine => "/vote_fu"
end
# Turbo Stream endpoints:
# POST /vote_fu/votes
# POST /vote_fu/votes/toggle
# DELETE /vote_fu/votes/:id
/* Import default styles */
@import "vote_fu/votes";
/* Customize colors */
:root {
--vote-fu-upvote-color: #ff6314;
--vote-fu-downvote-color: #7193ff;
--vote-fu-like-color: #e0245e;
}
# Migration
add_column :posts, :votes_count, :integer, default: 0
add_column :posts, :votes_total, :integer, default: 0
add_column :posts, :upvotes_count, :integer, default: 0
add_column :posts, :downvotes_count, :integer, default: 0
# Counters update automatically
VoteFu 2.0 is available now. Install it and start building.