punching_bag
Punching Bag
A Crystal shard for tracking and analyzing hit counts, trending items, time and location analytics for PostgreSQL.
Features
- Timezone-aware tracking using PostgreSQL's TIMESTAMPTZ
- Location-based analytics support
- Configurable hit counting
- Time-based popularity tracking
- Efficient indexing for fast queries
- Lightweight and fast
Requirements
- Crystal >= 1.0.0
Installation
- Add Punching Bag to your
shard.yml
:
dependencies:
punching_bag:
github: dcalixto/punching_bag
- Install dependencies:
shards install
- Run the setup command:
crystal run bin/micrate.cr -- up
If the setup has already been completed, you will see the following message in your terminal:
Setup already completed.
Usage
Import the library
require "punching_bag"
Then in your application code, you can set it up like:
Initialize database connection
PunchingBag.configure do |config|
config.database_url = "postgres://localhost/your_database"
end
Initialize the tracker
# Initialize tracker
tracker = PunchingBag::Tracker.new(PunchingBag.db)
Record a hit
tracker.punch("Article", 1)
Track hits with custom timestamp and timezone
timestamp = Time.local(timezone: Time::Location.load("America/New_York"))
tracker.punch("Article", 1, hits: 1, timestamp: timestamp)
Record multiple hits
tracker.punch("Article", 1, hits: 5)
Record hit with timestamp
tracker.punch("Article", 1, timestamp: Time.utc - 1.day)
Analytics
Get total hits for an item
total = tracker.total_hits("Article", 1)
Get most hit items since last week
trending = tracker.most_hit(Time.utc - 1.week)
Get top 10 most hit items since last month
top_items = tracker.most_hit(Time.utc - 1.month, limit: 10)
Get average time for hits
avg_time = tracker.average_time("Article", 1)
Clear all recorded hits
tracker.clear
Example Integration
Here’s an example of integrating Punching Bag into an application.
require "punching_bag"
require "db/serializable"
class Article
include DB::Serializable
property id : Int64
property title : String
def self.db=(database : DB::Database)
@@db = database
end
def self.db
@@db.not_nil!
end
def track_view
tracker = PunchingBag.new(@@db.not_nil!)
tracker.punch("Article", id.not_nil!)
end
def total_views
tracker = PunchingBag.new(@@db.not_nil!)
tracker.total_hits("Article", id.not_nil!)
end
def self.trending(since = Time.utc - 1.week, limit = 10)
tracker = PunchingBag.new(@@db.not_nil!)
tracker.most_hit(since, limit: limit)
end
end
The Routes
get "/articles/:id" do |env|
if article = Article.find(env.params.url["id"].to_i64)
article.track_view
render "article/show.ecr"
else
env.redirect "/articles"
end
end
View
To display the total view count in your view, use the following HTML:
<div class="views-count">
Views: <%= article.total_views %>
</div>
Development
crystal spec
Contributing
- Fork it (https://github.com/dcalixto/punching_bag/fork)
- Create your feature branch (
git checkout -b my-feature
) - Commit your changes (
git commit -am 'Add feature'
) - Push to the branch (
git push origin my-feature
) - Create a new Pull Request
Contributors
Daniel Calixto - creator and maintainer
License
MIT License. See LICENSE for details.
punching_bag
- 1
- 0
- 0
- 0
- 4
- 4 days ago
- November 30, 2024
Sat, 21 Dec 2024 21:26:26 GMT