统计特定用户通过 Active Storage 下载文件的次数
Count the number of times a specific user downloaded files through Active Storage
我的 Post 和 评论 模型都有 has_one_attached :file
。我想做的是计算特定用户下载 post 文件或评论文件的次数。在 User 模型上创建一种 download_counter_cache
,每当该用户下载文件时该模型就会递增。我怎样才能做到这一点?
根据 Max 的回答更新
这就是我目前所做的:
# Migration file
class CreateDownloads < ActiveRecord::Migration[6.0]
def change
create_table :downloads do |t|
t.references :user, null: false, foreign_key: true
t.references :resource, polymorphic: true
t.timestamps
end
end
end
# Routes.rb
concern :downloadable do
resources :downloads, only: :create
end
resources :posts, concerns: :downloadable do
[...] # Routes such as like/dislike
resources :comments, concerns: :downloadable do
[...] # Routes such as like/dislike
end
end
# In posts/_post.html.erb
<%= link_to([@post, :downloads], html_options = {class: 'file w-100'}, method: :post) do %>
[...]
<% end %>
我的 downloads_controller
与 Max 的回答中建议的完全相同,我的 Post、评论、用户和下载模型也是如此。
问题是,每当我尝试下载时,它都会将我重定向到显然不存在的 downloads#index
。我不确定我应该如何创建 resource
class.
您必须首先在用户和 comments/posts table 之间添加连接 table 或直接添加到 activesupport 附件 table.
class Download
belongs_to :user
belongs_to :resource, polymorphic: true
end
class Post
has_many :downloads, as: :resource
end
class Comment
has_many :downloads, as: :resource
end
class User
has_many :downloads
end
然后您必须创建一个 rails 控制器来代理下载,因为下载 ActiveSupport 附件通常会完全绕过您的 Rails 应用程序并直接从存储附件的服务(例如 S3)下载.
class DownloadsController < ApplicationController
before_action :authenticate_user! # I'm assuming you're using Devise
before_action :set_resource
def create
@download = @resource.downloads.create!(user: current_user)
redirect_to @resource.file.service_url
end
def set_resource
if params[:post_id]
@resource = Post.find(params[:post_id])
elsif params[:comment_id]
@resource = Comment.find(params[:comment_id])
end
end
end
# routes.rb
concern :downloadable do
resources :downloads, only: :create
end
resources :posts, concerns: :downloadable
resources :comments, concerns: :downloadable
<%= button_to "Download", [@post, :downloads], method: :post %>
然后您可以通过计算下载中的行数来计算下载量 table。
max 有一个很好的答案,但如果您只想在用户模型上只有一列来计算所有下载,则可以在没有多态连接的情况下完成 table。
让我们向用户模块添加一个属性来存储计数:
add_column :users, :download_count, :integer
然后添加一个控制器来处理计数并重定向到下载的文件:
class DownloadsController < ApplicationController
def create
# using find_by so it doesn't throw any errors
resource = Post.find_by_id(params[:post_id]) || Comment.find_by_id(params[:comment_id])
if resource
current_user.increment!(:download_count)
redirect_to rails_blob_path(resource.file, disposition: "attachment")
else
render nothing: true
end
end
end
路线如下:
resources :downloads, only: :create
下载 link 在视图中看起来像:
# for post file
<%= link_to 'download file', downloads_path(post_id: @post.id), method: :post %>
# for comment file
<%= link_to 'download file', downloads_path(comment_id: comment.id), method: :post %>
就这么简单。
更新:将方法从新方法更改为 post 以防止双重渲染。
我的 Post 和 评论 模型都有 has_one_attached :file
。我想做的是计算特定用户下载 post 文件或评论文件的次数。在 User 模型上创建一种 download_counter_cache
,每当该用户下载文件时该模型就会递增。我怎样才能做到这一点?
根据 Max 的回答更新
这就是我目前所做的:
# Migration file
class CreateDownloads < ActiveRecord::Migration[6.0]
def change
create_table :downloads do |t|
t.references :user, null: false, foreign_key: true
t.references :resource, polymorphic: true
t.timestamps
end
end
end
# Routes.rb
concern :downloadable do
resources :downloads, only: :create
end
resources :posts, concerns: :downloadable do
[...] # Routes such as like/dislike
resources :comments, concerns: :downloadable do
[...] # Routes such as like/dislike
end
end
# In posts/_post.html.erb
<%= link_to([@post, :downloads], html_options = {class: 'file w-100'}, method: :post) do %>
[...]
<% end %>
我的 downloads_controller
与 Max 的回答中建议的完全相同,我的 Post、评论、用户和下载模型也是如此。
问题是,每当我尝试下载时,它都会将我重定向到显然不存在的 downloads#index
。我不确定我应该如何创建 resource
class.
您必须首先在用户和 comments/posts table 之间添加连接 table 或直接添加到 activesupport 附件 table.
class Download
belongs_to :user
belongs_to :resource, polymorphic: true
end
class Post
has_many :downloads, as: :resource
end
class Comment
has_many :downloads, as: :resource
end
class User
has_many :downloads
end
然后您必须创建一个 rails 控制器来代理下载,因为下载 ActiveSupport 附件通常会完全绕过您的 Rails 应用程序并直接从存储附件的服务(例如 S3)下载.
class DownloadsController < ApplicationController
before_action :authenticate_user! # I'm assuming you're using Devise
before_action :set_resource
def create
@download = @resource.downloads.create!(user: current_user)
redirect_to @resource.file.service_url
end
def set_resource
if params[:post_id]
@resource = Post.find(params[:post_id])
elsif params[:comment_id]
@resource = Comment.find(params[:comment_id])
end
end
end
# routes.rb
concern :downloadable do
resources :downloads, only: :create
end
resources :posts, concerns: :downloadable
resources :comments, concerns: :downloadable
<%= button_to "Download", [@post, :downloads], method: :post %>
然后您可以通过计算下载中的行数来计算下载量 table。
max 有一个很好的答案,但如果您只想在用户模型上只有一列来计算所有下载,则可以在没有多态连接的情况下完成 table。
让我们向用户模块添加一个属性来存储计数:
add_column :users, :download_count, :integer
然后添加一个控制器来处理计数并重定向到下载的文件:
class DownloadsController < ApplicationController
def create
# using find_by so it doesn't throw any errors
resource = Post.find_by_id(params[:post_id]) || Comment.find_by_id(params[:comment_id])
if resource
current_user.increment!(:download_count)
redirect_to rails_blob_path(resource.file, disposition: "attachment")
else
render nothing: true
end
end
end
路线如下:
resources :downloads, only: :create
下载 link 在视图中看起来像:
# for post file
<%= link_to 'download file', downloads_path(post_id: @post.id), method: :post %>
# for comment file
<%= link_to 'download file', downloads_path(comment_id: comment.id), method: :post %>
就这么简单。
更新:将方法从新方法更改为 post 以防止双重渲染。