vote_fu 0.0.11 → 2.0.1

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 +84 -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 +217 -60
  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: e41c3bb095fcc59bd760c22b9acce429e4668bee7268eb17c6a086ccb83ce1db
4
+ data.tar.gz: 894cea50b6ddd38d3d8205ffdd5d1be742e9dfa11d9d9fe27870a17ee0f81974
5
+ SHA512:
6
+ metadata.gz: 7766ba6429c7d0fa87b197ca2e1bfb4c01184c55ab66ef12393e0c64e9d8017f9f01ec6e907c48d98028b306b66da38e538ebd0555e229afd477692ea7f20fb4
7
+ data.tar.gz: f056f0301d450ab894bb9a24174707364f3628484ecb8dfc8b4b004148dfe5e8cba26976a9bdfa0023ef3c4e8b2f51397f7c80240cff65622d0345f466819b36
data/CHANGELOG.md ADDED
@@ -0,0 +1,84 @@
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.1] - 2024-11-30
11
+
12
+ ### Changed
13
+ - Added legacy VoteFu contributors to gem authors
14
+ - Fixed gemspec homepage to point to votefu.dev
15
+
16
+ ## [2.0.0] - 2024-11-29
17
+
18
+ Complete rewrite of VoteFu for modern Rails applications.
19
+
20
+ ### Added
21
+
22
+ #### Core Voting
23
+ - Integer vote values (supports up/down, star ratings 1-5, weighted votes)
24
+ - Scoped voting - multiple independent vote contexts per voteable
25
+ - Counter cache support (`votes_count`, `votes_total`, `upvotes_count`, `downvotes_count`)
26
+ - `acts_as_voteable` and `acts_as_voter` concerns
27
+ - `votes_on` DSL for dynamic method generation
28
+ - `voteable_by` DSL for explicit voter relationships
29
+
30
+ #### Algorithms (Built-in, No External Dependencies)
31
+ - **Wilson Score Lower Bound** - Statistical confidence interval for quality ranking
32
+ - **Reddit Hot** - Time-decaying popularity ranking
33
+ - **Hacker News** - Heavily time-weighted ranking
34
+
35
+ #### Turbo/Hotwire Integration
36
+ - `VotesController` with full Turbo Stream responses
37
+ - View helpers: `vote_widget`, `like_button`, `upvote_button`, `downvote_button`, `vote_count`
38
+ - Turbo Stream partials for seamless DOM updates
39
+ - Stimulus controller for optimistic UI updates
40
+
41
+ #### ViewComponents
42
+ - `VoteWidgetComponent` - Reddit-style upvote/downvote (variants: default, compact, vertical, large)
43
+ - `StarRatingComponent` - 1-5 star rating with averages and counts
44
+ - `LikeButtonComponent` - Simple heart/like button
45
+ - `ReactionBarComponent` - Emoji reactions (Slack/GitHub style)
46
+
47
+ #### ActionCable Real-time Updates
48
+ - `VotesChannel` for live vote broadcasts
49
+ - JavaScript client for subscribing to vote updates
50
+ - Auto-subscribe functionality for widgets on page
51
+
52
+ #### Karma System
53
+ - `has_karma` DSL for reputation tracking
54
+ - Time decay with configurable half-life
55
+ - Weighted karma sources (upvotes vs downvotes)
56
+ - Karma levels with progress tracking (Newcomer -> Legend)
57
+ - Scoped karma calculation
58
+ - Karma caching support for performance
59
+ - `karma_level`, `karma_progress`, `recent_karma` methods
60
+
61
+ #### Styling
62
+ - Default CSS with dark mode support
63
+ - Size variants (compact, default, large, vertical)
64
+ - Fully customizable via CSS
65
+
66
+ ### Changed
67
+ - **BREAKING**: Minimum Ruby version is now 3.2
68
+ - **BREAKING**: Minimum Rails version is now 7.2
69
+ - **BREAKING**: Votes use integer `value` instead of boolean
70
+ - **BREAKING**: New namespace `VoteFu::Vote` (was just `Vote`)
71
+ - **BREAKING**: Counter cache columns renamed for clarity
72
+
73
+ ### Removed
74
+ - All legacy Rails 2/3/4 compatibility code
75
+ - `named_scope` usage (replaced with modern `scope`)
76
+ - `find(:all)` patterns
77
+ - External dependency on `statistics2` gem
78
+
79
+ ## [0.0.11] - 2009-02-11
80
+
81
+ ### Legacy
82
+ - Original VoteFu release for Rails 2.x
83
+ - Forked as ThumbsUp in 2010
84
+ - 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).