I have a Rails API project.
I am trying to implement a counter on the number of times a file is requested, say, the number of times an audio file is played.
This is my model
class Post < ApplicationRecord
has_one_attached :audio_file
end
The frontend gets the file URL and makes a GET request to play the file:
GET localhost:3001/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--75d7e21e4e3727c21cb0e26a86c7366dea1bc36a/test_audio.mp3
When the request is performed, rails logs this:
Started GET "/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--75d7e21e4e3727c21cb0e26a86c7366dea1bc36a/test_audio.mp3" for ::1 at 2020-05-13 20:29:15 -0400
(28.4ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ /home/david/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by ActiveStorage::BlobsController#show as MP3
Parameters: {"signed_id"=>"eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--75d7e21e4e3727c21cb0e26a86c7366dea1bc36a", "filename"=>"test_audio"}
ActiveStorage::Blob Load (45.5ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ /home/david/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Disk Storage (18882.5ms) Generated URL for file at key: XoA9L6bBFrEeBuGMRPzHx6Wn (http://localhost:3001/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSWRXRzlCT1V3MllrSkdja1ZsUW5WSFRWSlFla2g0TmxkdUJqb0dSVlE2RUdScGMzQnZjMmwwYVc5dVNTSkxZWFIwWVdOb2JXVnVkRHNnWm1sc1pXNWhiV1U5SW5SbGMzUmZZWFZrYVc4dWJYQXpJanNnWm1sc1pXNWhiV1VxUFZWVVJpMDRKeWQwWlhOMFgyRjFaR2x2TG0xd013WTdCa1k2RVdOdmJuUmxiblJmZEhsd1pVa2lEMkYxWkdsdkwyMXdaV2NHT3daVSIsImV4cCI6IjIwMjAtMDUtMTRUMDA6MzQ6NDUuMDMyWiIsInB1ciI6ImJsb2Jfa2V5In19--b7120a24370e1afd709601363c463950bbb6ad22/test_audio.mp3?content_type=audio%2Fmpeg&disposition=attachment%3B+filename%3D%22test_audio.mp3%22%3B+filename%2A%3DUTF-8%27%27test_audio.mp3)
Redirected to http://localhost:3001/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSWRXRzlCT1V3MllrSkdja1ZsUW5WSFRWSlFla2g0TmxkdUJqb0dSVlE2RUdScGMzQnZjMmwwYVc5dVNTSkxZWFIwWVdOb2JXVnVkRHNnWm1sc1pXNWhiV1U5SW5SbGMzUmZZWFZrYVc4dWJYQXpJanNnWm1sc1pXNWhiV1VxUFZWVVJpMDRKeWQwWlhOMFgyRjFaR2x2TG0xd013WTdCa1k2RVdOdmJuUmxiblJmZEhsd1pVa2lEMkYxWkdsdkwyMXdaV2NHT3daVSIsImV4cCI6IjIwMjAtMDUtMTRUMDA6MzQ6NDUuMDMyWiIsInB1ciI6ImJsb2Jfa2V5In19--b7120a24370e1afd709601363c463950bbb6ad22/test_audio.mp3?content_type=audio%2Fmpeg&disposition=attachment%3B+filename%3D%22test_audio.mp3%22%3B+filename%2A%3DUTF-8%27%27test_audio.mp3
Completed 302 Found in 21681ms (ActiveRecord: 54.2ms)
Started GET "/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSWRXRzlCT1V3MllrSkdja1ZsUW5WSFRWSlFla2g0TmxkdUJqb0dSVlE2RUdScGMzQnZjMmwwYVc5dVNTSkxZWFIwWVdOb2JXVnVkRHNnWm1sc1pXNWhiV1U5SW5SbGMzUmZZWFZrYVc4dWJYQXpJanNnWm1sc1pXNWhiV1VxUFZWVVJpMDRKeWQwWlhOMFgyRjFaR2x2TG0xd013WTdCa1k2RVdOdmJuUmxiblJmZEhsd1pVa2lEMkYxWkdsdkwyMXdaV2NHT3daVSIsImV4cCI6IjIwMjAtMDUtMTRUMDA6MzQ6NDUuMDMyWiIsInB1ciI6ImJsb2Jfa2V5In19--b7120a24370e1afd709601363c463950bbb6ad22/test_audio.mp3?content_type=audio%2Fmpeg&disposition=attachment%3B+filename%3D%22test_audio.mp3%22%3B+filename%2A%3DUTF-8%27%27test_audio.mp3" for ::1 at 2020-05-13 20:29:46 -0400
Processing by ActiveStorage::DiskController#show as MP3
Parameters: {"content_type"=>"audio/mpeg", "disposition"=>"attachment; filename=\"test_audio.mp3\"; filename*=UTF-8''test_audio.mp3", "encoded_key"=>"eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSWRXRzlCT1V3MllrSkdja1ZsUW5WSFRWSlFla2g0TmxkdUJqb0dSVlE2RUdScGMzQnZjMmwwYVc5dVNTSkxZWFIwWVdOb2JXVnVkRHNnWm1sc1pXNWhiV1U5SW5SbGMzUmZZWFZrYVc4dWJYQXpJanNnWm1sc1pXNWhiV1VxUFZWVVJpMDRKeWQwWlhOMFgyRjFaR2x2TG0xd013WTdCa1k2RVdOdmJuUmxiblJmZEhsd1pVa2lEMkYxWkdsdkwyMXdaV2NHT3daVSIsImV4cCI6IjIwMjAtMDUtMTRUMDA6MzQ6NDUuMDMyWiIsInB1ciI6ImJsb2Jfa2V5In19--b7120a24370e1afd709601363c463950bbb6ad22", "filename"=>"test_audio"}
Completed 200 OK in 1ms (ActiveRecord: 0.0ms)
I was thinking of adding a callback to ActiveStorage::Blob Load, that +1 a counter attribute in the Post model. My idea was to use after_find but I am not sure where I should add it.
Any other suggestions are very much appreciated.
How about providing new member action for posts_controller
and use rails_blob_path
helper?
in routes.rb definition
resources :posts do
member do
get :download
end
end
in controller
class PostsController::ApplicationController
def download
post = Post.find params[:id]
# counter business logic here
post.increment(:download_counter)
rails_blob_path(post.audio_file, disposition: "attachment")
end
end