vote_fu 0.0.11 → 2.0.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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +78 -0
  3. data/README.md +265 -0
  4. data/app/assets/stylesheets/vote_fu/votes.css +391 -0
  5. data/app/channels/vote_fu/application_cable/channel.rb +8 -0
  6. data/app/channels/vote_fu/application_cable/connection.rb +39 -0
  7. data/app/channels/vote_fu/votes_channel.rb +99 -0
  8. data/app/components/vote_fu/like_button_component.rb +136 -0
  9. data/app/components/vote_fu/reaction_bar_component.rb +208 -0
  10. data/app/components/vote_fu/star_rating_component.rb +199 -0
  11. data/app/components/vote_fu/vote_widget_component.rb +181 -0
  12. data/app/controllers/vote_fu/application_controller.rb +49 -0
  13. data/app/controllers/vote_fu/votes_controller.rb +223 -0
  14. data/app/helpers/vote_fu/votes_helper.rb +176 -0
  15. data/app/javascript/vote_fu/channels/consumer.js +3 -0
  16. data/app/javascript/vote_fu/channels/index.js +2 -0
  17. data/app/javascript/vote_fu/channels/votes_channel.js +93 -0
  18. data/app/javascript/vote_fu/controllers/application.js +9 -0
  19. data/app/javascript/vote_fu/controllers/index.js +9 -0
  20. data/app/javascript/vote_fu/controllers/vote_fu_controller.js +148 -0
  21. data/app/javascript/vote_fu/controllers/vote_fu_reactions_controller.js +92 -0
  22. data/app/javascript/vote_fu/controllers/vote_fu_stars_controller.js +77 -0
  23. data/app/models/vote_fu/application_record.rb +7 -0
  24. data/app/models/vote_fu/vote.rb +90 -0
  25. data/app/views/vote_fu/votes/_count.html.erb +29 -0
  26. data/app/views/vote_fu/votes/_downvote_button.html.erb +40 -0
  27. data/app/views/vote_fu/votes/_error.html.erb +9 -0
  28. data/app/views/vote_fu/votes/_like_button.html.erb +67 -0
  29. data/app/views/vote_fu/votes/_upvote_button.html.erb +40 -0
  30. data/app/views/vote_fu/votes/_widget.html.erb +85 -0
  31. data/config/importmap.rb +6 -0
  32. data/config/routes.rb +9 -0
  33. data/lib/generators/vote_fu/install/install_generator.rb +56 -0
  34. data/lib/generators/vote_fu/install/templates/initializer.rb +42 -0
  35. data/lib/generators/vote_fu/install/templates/migration.rb.erb +41 -0
  36. data/lib/generators/vote_fu/migration/migration_generator.rb +29 -0
  37. data/lib/generators/vote_fu/migration/templates/create_vote_fu_votes.rb.erb +40 -0
  38. data/lib/vote_fu/algorithms/hacker_news.rb +54 -0
  39. data/lib/vote_fu/algorithms/reddit_hot.rb +55 -0
  40. data/lib/vote_fu/algorithms/wilson_score.rb +69 -0
  41. data/lib/vote_fu/concerns/karmatic.rb +320 -0
  42. data/lib/vote_fu/concerns/voteable.rb +291 -0
  43. data/lib/vote_fu/concerns/voter.rb +275 -0
  44. data/lib/vote_fu/configuration.rb +53 -0
  45. data/lib/vote_fu/engine.rb +54 -0
  46. data/lib/vote_fu/errors.rb +34 -0
  47. data/lib/vote_fu/version.rb +5 -0
  48. data/lib/vote_fu.rb +22 -9
  49. metadata +215 -63
  50. data/CHANGELOG.markdown +0 -31
  51. data/README.markdown +0 -220
  52. data/examples/routes.rb +0 -7
  53. data/examples/users_controller.rb +0 -76
  54. data/examples/voteable.html.erb +0 -8
  55. data/examples/voteable.rb +0 -10
  56. data/examples/voteables_controller.rb +0 -117
  57. data/examples/votes/_voteable_vote.html.erb +0 -23
  58. data/examples/votes/create.rjs +0 -1
  59. data/examples/votes_controller.rb +0 -110
  60. data/generators/vote_fu/templates/migration.rb +0 -21
  61. data/generators/vote_fu/vote_fu_generator.rb +0 -8
  62. data/init.rb +0 -1
  63. data/lib/acts_as_voteable.rb +0 -114
  64. data/lib/acts_as_voter.rb +0 -75
  65. data/lib/controllers/votes_controller.rb +0 -96
  66. data/lib/has_karma.rb +0 -68
  67. data/lib/models/vote.rb +0 -17
  68. data/rails/init.rb +0 -10
  69. data/test/vote_fu_test.rb +0 -8
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f74a3d3c293097b15851db854588792c7c584eedc3b16cfc42cf924590564633
4
+ data.tar.gz: b6898c6f0216387b2381ef3ba34ce828db44b8f56bef0df833ff3d2d198b76a7
5
+ SHA512:
6
+ metadata.gz: 136d6018a10d186717a17f8af3efef0fc848a9017c73bad0ad474a24aecc9bb0d923a514e178bb531a60098aac8f85c160d33d6c18587f2d3d173aff8a4f58f7
7
+ data.tar.gz: db1fd3ead94e5038f15f5dc3dd0effe19972f601b49f7ef88c5738ff07aa6681a6aeec7a48f27c6336783920a09d85956e881c994b541da3e5cf41392867ef77
data/CHANGELOG.md ADDED
@@ -0,0 +1,78 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.0.0] - 2024-11-29
11
+
12
+ Complete rewrite of VoteFu for modern Rails applications.
13
+
14
+ ### Added
15
+
16
+ #### Core Voting
17
+ - Integer vote values (supports up/down, star ratings 1-5, weighted votes)
18
+ - Scoped voting - multiple independent vote contexts per voteable
19
+ - Counter cache support (`votes_count`, `votes_total`, `upvotes_count`, `downvotes_count`)
20
+ - `acts_as_voteable` and `acts_as_voter` concerns
21
+ - `votes_on` DSL for dynamic method generation
22
+ - `voteable_by` DSL for explicit voter relationships
23
+
24
+ #### Algorithms (Built-in, No External Dependencies)
25
+ - **Wilson Score Lower Bound** - Statistical confidence interval for quality ranking
26
+ - **Reddit Hot** - Time-decaying popularity ranking
27
+ - **Hacker News** - Heavily time-weighted ranking
28
+
29
+ #### Turbo/Hotwire Integration
30
+ - `VotesController` with full Turbo Stream responses
31
+ - View helpers: `vote_widget`, `like_button`, `upvote_button`, `downvote_button`, `vote_count`
32
+ - Turbo Stream partials for seamless DOM updates
33
+ - Stimulus controller for optimistic UI updates
34
+
35
+ #### ViewComponents
36
+ - `VoteWidgetComponent` - Reddit-style upvote/downvote (variants: default, compact, vertical, large)
37
+ - `StarRatingComponent` - 1-5 star rating with averages and counts
38
+ - `LikeButtonComponent` - Simple heart/like button
39
+ - `ReactionBarComponent` - Emoji reactions (Slack/GitHub style)
40
+
41
+ #### ActionCable Real-time Updates
42
+ - `VotesChannel` for live vote broadcasts
43
+ - JavaScript client for subscribing to vote updates
44
+ - Auto-subscribe functionality for widgets on page
45
+
46
+ #### Karma System
47
+ - `has_karma` DSL for reputation tracking
48
+ - Time decay with configurable half-life
49
+ - Weighted karma sources (upvotes vs downvotes)
50
+ - Karma levels with progress tracking (Newcomer -> Legend)
51
+ - Scoped karma calculation
52
+ - Karma caching support for performance
53
+ - `karma_level`, `karma_progress`, `recent_karma` methods
54
+
55
+ #### Styling
56
+ - Default CSS with dark mode support
57
+ - Size variants (compact, default, large, vertical)
58
+ - Fully customizable via CSS
59
+
60
+ ### Changed
61
+ - **BREAKING**: Minimum Ruby version is now 3.2
62
+ - **BREAKING**: Minimum Rails version is now 7.2
63
+ - **BREAKING**: Votes use integer `value` instead of boolean
64
+ - **BREAKING**: New namespace `VoteFu::Vote` (was just `Vote`)
65
+ - **BREAKING**: Counter cache columns renamed for clarity
66
+
67
+ ### Removed
68
+ - All legacy Rails 2/3/4 compatibility code
69
+ - `named_scope` usage (replaced with modern `scope`)
70
+ - `find(:all)` patterns
71
+ - External dependency on `statistics2` gem
72
+
73
+ ## [0.0.11] - 2009-02-11
74
+
75
+ ### Legacy
76
+ - Original VoteFu release for Rails 2.x
77
+ - Forked as ThumbsUp in 2010
78
+ - See https://github.com/peteonrails/vote_fu for historical code
data/README.md ADDED
@@ -0,0 +1,265 @@
1
+ # VoteFu
2
+
3
+ [![VoteFu - Modern Voting for Rails 8+](docs/og-image.png)](https://votefu.dev)
4
+
5
+ **The original Rails voting gem, reborn for the modern era.**
6
+
7
+ VoteFu was first released in 2008 for Rails 2. Over the years it was forked countless times—most notably as ThumbsUp—as the Rails ecosystem evolved and the original fell behind. While the forks kept pace with Rails 3, 4, and 5, none made the leap to embrace Hotwire.
8
+
9
+ VoteFu 2.0 changes that. This is a complete ground-up rewrite that leapfrogs every fork with first-class Turbo Streams, ViewComponents, Stimulus controllers, and ActionCable support. No more bolting modern UI onto legacy architecture. VoteFu is back, and it's ready for Rails 8.
10
+
11
+ ## Features
12
+
13
+ - **Flexible voting**: Up/down votes, star ratings (1-5), weighted votes
14
+ - **Scoped voting**: Multiple voting contexts per item (quality, helpfulness, etc.)
15
+ - **Counter caches**: Automatic vote count maintenance for performance
16
+ - **Ranking algorithms**: Wilson Score, Reddit Hot, Hacker News built-in
17
+ - **Karma system**: Calculate user reputation from votes on their content
18
+ - **Turbo-native**: Turbo Streams responses out of the box
19
+ - **Modern Rails**: Designed for Rails 8+, uses Concerns, no legacy patterns
20
+
21
+ ## Installation
22
+
23
+ Add to your Gemfile:
24
+
25
+ ```ruby
26
+ gem 'vote_fu', '~> 2.0'
27
+ ```
28
+
29
+ Run the installer:
30
+
31
+ ```bash
32
+ rails generate vote_fu:install
33
+ rails db:migrate
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ### Set up your models
39
+
40
+ ```ruby
41
+ # app/models/post.rb
42
+ class Post < ApplicationRecord
43
+ acts_as_voteable
44
+ end
45
+
46
+ # app/models/user.rb
47
+ class User < ApplicationRecord
48
+ acts_as_voter
49
+ end
50
+ ```
51
+
52
+ ### Cast votes
53
+
54
+ ```ruby
55
+ user.upvote(post) # +1 vote
56
+ user.downvote(post) # -1 vote
57
+ user.vote_on(post, value: 5) # 5-star rating
58
+ user.unvote(post) # Remove vote
59
+ user.toggle_vote(post) # Toggle on/off
60
+ ```
61
+
62
+ ### Query votes
63
+
64
+ ```ruby
65
+ # On voteables
66
+ post.votes_for # Upvote count
67
+ post.votes_against # Downvote count
68
+ post.plusminus # Net score
69
+ post.wilson_score # Ranking score (0.0-1.0)
70
+ post.voted_by?(user) # Did user vote?
71
+
72
+ # On voters
73
+ user.voted_on?(post) # Did user vote?
74
+ user.vote_value_for(post) # What value?
75
+ user.voted_items(Post) # All posts user voted on
76
+ ```
77
+
78
+ ### Rank items
79
+
80
+ ```ruby
81
+ Post.by_votes # Order by vote total
82
+ Post.by_wilson_score # Order by Wilson Score
83
+ Post.trending # Most votes in 24h
84
+ Post.with_positive_score # Net positive only
85
+ ```
86
+
87
+ ## Scoped Voting
88
+
89
+ Allow multiple independent votes per item:
90
+
91
+ ```ruby
92
+ # User can vote separately on quality and helpfulness
93
+ user.vote_on(review, value: 5, scope: :quality)
94
+ user.vote_on(review, value: 1, scope: :helpfulness)
95
+
96
+ review.plusminus(scope: :quality) # => 5
97
+ review.plusminus(scope: :helpfulness) # => 1
98
+ ```
99
+
100
+ ## Karma
101
+
102
+ Calculate user reputation:
103
+
104
+ ```ruby
105
+ class User < ApplicationRecord
106
+ has_many :posts
107
+
108
+ acts_as_voter
109
+ has_karma :posts, as: :author
110
+ end
111
+
112
+ user.karma # Sum of upvotes on user's posts
113
+ ```
114
+
115
+ ## Counter Caches
116
+
117
+ Add columns for performance:
118
+
119
+ ```ruby
120
+ # Migration
121
+ add_column :posts, :votes_count, :integer, default: 0
122
+ add_column :posts, :votes_total, :integer, default: 0
123
+ add_column :posts, :upvotes_count, :integer, default: 0
124
+ add_column :posts, :downvotes_count, :integer, default: 0
125
+ ```
126
+
127
+ Counters update automatically when `counter_cache: true` (default).
128
+
129
+ ## Ranking Algorithms
130
+
131
+ ### Wilson Score
132
+ Best for quality ranking. Accounts for statistical confidence.
133
+ ```ruby
134
+ post.wilson_score(confidence: 0.95)
135
+ ```
136
+
137
+ ### Reddit Hot
138
+ Balances popularity with recency.
139
+ ```ruby
140
+ post.hot_score(gravity: 1.8)
141
+ ```
142
+
143
+ ### Hacker News
144
+ Heavily favors recent content.
145
+ ```ruby
146
+ VoteFu::Algorithms::HackerNews.call(post, gravity: 1.8)
147
+ ```
148
+
149
+ ## Turbo Integration
150
+
151
+ VoteFu comes with Turbo Streams support out of the box.
152
+
153
+ ### View Helpers
154
+
155
+ ```erb
156
+ <%# Reddit-style upvote/downvote widget %>
157
+ <%= vote_widget @post %>
158
+
159
+ <%# Simple like button %>
160
+ <%= like_button @photo %>
161
+
162
+ <%# Scoped voting %>
163
+ <%= vote_widget @review, scope: :quality %>
164
+ <%= vote_widget @review, scope: :helpfulness %>
165
+ ```
166
+
167
+ ### ViewComponents
168
+
169
+ For more control, use the ViewComponents directly:
170
+
171
+ ```erb
172
+ <%# Vote widget with all options %>
173
+ <%= render VoteFu::VoteWidgetComponent.new(
174
+ voteable: @post,
175
+ voter: current_user,
176
+ variant: :vertical,
177
+ upvote_label: "👍",
178
+ downvote_label: "👎"
179
+ ) %>
180
+
181
+ <%# Star rating %>
182
+ <%= render VoteFu::StarRatingComponent.new(
183
+ voteable: @product,
184
+ voter: current_user,
185
+ show_average: true,
186
+ show_count: true
187
+ ) %>
188
+
189
+ <%# Emoji reactions (Slack/GitHub style) %>
190
+ <%= render VoteFu::ReactionBarComponent.new(
191
+ voteable: @comment,
192
+ voter: current_user,
193
+ reactions: [
194
+ { emoji: "👍", label: "Like", scope: "like" },
195
+ { emoji: "❤️", label: "Love", scope: "love" },
196
+ { emoji: "🎉", label: "Celebrate", scope: "celebrate" }
197
+ ]
198
+ ) %>
199
+ ```
200
+
201
+ ### Controller
202
+
203
+ VoteFu provides a complete controller for handling votes:
204
+
205
+ ```ruby
206
+ # config/routes.rb
207
+ Rails.application.routes.draw do
208
+ mount VoteFu::Engine => "/vote_fu"
209
+ end
210
+ ```
211
+
212
+ The controller responds to:
213
+ - `POST /vote_fu/votes` - Create/update a vote
214
+ - `POST /vote_fu/votes/toggle` - Toggle vote (upvote ↔ remove)
215
+ - `DELETE /vote_fu/votes/:id` - Remove a vote
216
+
217
+ All endpoints return Turbo Streams for seamless updates.
218
+
219
+ ## Styles
220
+
221
+ Import the default styles:
222
+
223
+ ```css
224
+ /* app/assets/stylesheets/application.css */
225
+ @import "vote_fu/votes";
226
+ ```
227
+
228
+ Or use CSS variables to customize:
229
+
230
+ ```css
231
+ :root {
232
+ --vote-fu-upvote-color: #ff6314;
233
+ --vote-fu-downvote-color: #7193ff;
234
+ --vote-fu-like-color: #e0245e;
235
+ }
236
+ ```
237
+
238
+ ## Configuration
239
+
240
+ ```ruby
241
+ # config/initializers/vote_fu.rb
242
+ VoteFu.configure do |config|
243
+ config.allow_recast = true # Change votes?
244
+ config.allow_duplicate_votes = false # Multiple votes per user?
245
+ config.allow_self_vote = false # Vote on yourself?
246
+ config.counter_cache = true # Auto-update counters?
247
+ config.turbo_broadcasts = true # Turbo Stream broadcasts?
248
+ config.default_ranking = :wilson_score
249
+ config.hot_ranking_gravity = 1.8
250
+ end
251
+ ```
252
+
253
+ ## History
254
+
255
+ VoteFu was created in 2008 when Rails 2 was cutting-edge. It became one of the go-to voting solutions for Rails applications, powering upvotes, ratings, and karma systems across thousands of apps.
256
+
257
+ When Rails 3 arrived with breaking changes, VoteFu fell behind. In 2010, it was forked as [ThumbsUp](https://github.com/bouchard/thumbs_up), which carried the torch through Rails 3, 4, 5, and beyond. Other forks emerged too—acts_as_votable, votable, and more—each taking the original idea in different directions.
258
+
259
+ But none of them embraced Hotwire. As Rails evolved toward Turbo and Stimulus, the voting gem ecosystem stayed stuck in the jQuery era, requiring manual JavaScript for real-time updates.
260
+
261
+ **VoteFu 2.0 is a complete rewrite.** Zero legacy code. Built from scratch for Rails 7.2+ with Turbo Streams, ViewComponents, and ActionCable baked in. The original is back—and it's leapfrogged every fork.
262
+
263
+ ## License
264
+
265
+ MIT License. See [LICENSE](MIT-LICENSE).