自定义 Rails 仪表板,如何优化数据检索以显示在视图中?
Custom Rails Dashboard, how to optimize data retrieval to display in view?
我正在为需要我计算一些 KPI 的学校应用程序制作自定义仪表板,我现在的做法是从 class 中的机会 class 调用几个 class 方法=23=] 来自控制器的操作,并将每个方法结果存储在一个将在图块中使用的变量中。所以每个变量都是仪表板的不同磁贴。
这些方法属于机会 class,如下所示:
class Opportunity < ApplicationRecord
belongs_to :organization
belongs_to :opportunity_status
has_many :tasks, dependent: :destroy
has_many :opportunity_status_logs, dependent: :destroy
before_create :create_status_log
after_update :create_status_log, if: :opportunity_status_id_changed?
validates :name, :description, :revenue, :opportunity_status_id, :closing_date, presence: true
validates :name, :description, format: { with: /\A[[:alpha:]a-zA-Z0-9ñÑ#()\-.,\s]+\z/ }
validates :revenue, numericality: true
validates :closing_date, inclusion: { in: (Time.zone.today..Time.zone.today+5.years) }
def create_status_log
OpportunityStatusLog.create(opportunity_id: self.id, opportunity_status_id: self.opportunity_status_id)
end
def status_updated_by(user)
@status_log = self.opportunity_status_logs.last
@status_log.user_id = user.id
@status_log.save!
end
def self.actives
self.where.not(opportunity_status_id: [11,12])
end
def self.won
self.where(opportunity_status_id: 11)
end
def self.lost
self.where(opportunity_status_id: 12)
end
def self.average_revenue
self.won.average(:revenue)
end
def self.minimum_revenue
self.won.minimum(:revenue)
end
def self.maximum_revenue
self.won.maximum(:revenue)
end
def self.filter_by_status(status_id)
self.where(opportunity_status: status_id)
end
def self.relative_percentage(item_amount, total)
item_amount * 100 / total
end
def self.conversion_rate
self.won.count / self.all.count.to_f * 100
end
def self.potential_revenue
self.actives.sum(:revenue)
end
end
控制器的结构是这样的:
class DashboardController < ApplicationController
before_action :authenticate_user!
def index
@opportunities = Opportunity.includes(:opportunity_status).all
@actives = Opportunity.actives.count
@won = Opportunity.won.count
@lost = Opportunity.lost.count
@average_revenue = Opportunity.average_revenue
@minimum_revenue = Opportunity.minimum_revenue
@maximum_revenue = Opportunity.maximum_revenue
@in_appreciation = Opportunity.filter_by_status(6).count
@in_value_proposition = Opportunity.filter_by_status(7).count
@in_management_analysis = Opportunity.filter_by_status(8).count
@in_proposal = Opportunity.filter_by_status(9).count
@in_review = Opportunity.filter_by_status(10).count
@app_perc = Opportunity.relative_percentage(@in_appreciation, @opportunities.count)
@vp_perc = Opportunity.relative_percentage(@in_value_proposition, @opportunities.count)
@ma_perc = Opportunity.relative_percentage(@in_management_analysis, @opportunities.count)
@pp_perc = Opportunity.relative_percentage(@in_proposal, @opportunities.count)
@rw_perc = Opportunity.relative_percentage(@in_review, @opportunities.count)
@conversion_rate = '%.2f' % [Opportunity.conversion_rate]
@potential_revenue = Opportunity.potential_revenue
end
end
尽管它按预期工作,但看起来控制器有点太胖了,我觉得如果应用程序缩放当前方法,由于正在完成的查询量,它会非常慢。那么,有没有办法重构它以优化数据检索和 KPI 的显示?
提前致谢
您可以尝试实施 Facade Pattern in Rails。它会让你的控制器变瘦,但在查询部分你仍然需要进行这些查询,没有办法跳过它。
您可以尝试通过添加索引和创建 sql 视图来优化数据库,当您以后遇到性能滞后时,这时候就像过早优化一样
我正在为需要我计算一些 KPI 的学校应用程序制作自定义仪表板,我现在的做法是从 class 中的机会 class 调用几个 class 方法=23=] 来自控制器的操作,并将每个方法结果存储在一个将在图块中使用的变量中。所以每个变量都是仪表板的不同磁贴。
这些方法属于机会 class,如下所示:
class Opportunity < ApplicationRecord
belongs_to :organization
belongs_to :opportunity_status
has_many :tasks, dependent: :destroy
has_many :opportunity_status_logs, dependent: :destroy
before_create :create_status_log
after_update :create_status_log, if: :opportunity_status_id_changed?
validates :name, :description, :revenue, :opportunity_status_id, :closing_date, presence: true
validates :name, :description, format: { with: /\A[[:alpha:]a-zA-Z0-9ñÑ#()\-.,\s]+\z/ }
validates :revenue, numericality: true
validates :closing_date, inclusion: { in: (Time.zone.today..Time.zone.today+5.years) }
def create_status_log
OpportunityStatusLog.create(opportunity_id: self.id, opportunity_status_id: self.opportunity_status_id)
end
def status_updated_by(user)
@status_log = self.opportunity_status_logs.last
@status_log.user_id = user.id
@status_log.save!
end
def self.actives
self.where.not(opportunity_status_id: [11,12])
end
def self.won
self.where(opportunity_status_id: 11)
end
def self.lost
self.where(opportunity_status_id: 12)
end
def self.average_revenue
self.won.average(:revenue)
end
def self.minimum_revenue
self.won.minimum(:revenue)
end
def self.maximum_revenue
self.won.maximum(:revenue)
end
def self.filter_by_status(status_id)
self.where(opportunity_status: status_id)
end
def self.relative_percentage(item_amount, total)
item_amount * 100 / total
end
def self.conversion_rate
self.won.count / self.all.count.to_f * 100
end
def self.potential_revenue
self.actives.sum(:revenue)
end
end
控制器的结构是这样的:
class DashboardController < ApplicationController
before_action :authenticate_user!
def index
@opportunities = Opportunity.includes(:opportunity_status).all
@actives = Opportunity.actives.count
@won = Opportunity.won.count
@lost = Opportunity.lost.count
@average_revenue = Opportunity.average_revenue
@minimum_revenue = Opportunity.minimum_revenue
@maximum_revenue = Opportunity.maximum_revenue
@in_appreciation = Opportunity.filter_by_status(6).count
@in_value_proposition = Opportunity.filter_by_status(7).count
@in_management_analysis = Opportunity.filter_by_status(8).count
@in_proposal = Opportunity.filter_by_status(9).count
@in_review = Opportunity.filter_by_status(10).count
@app_perc = Opportunity.relative_percentage(@in_appreciation, @opportunities.count)
@vp_perc = Opportunity.relative_percentage(@in_value_proposition, @opportunities.count)
@ma_perc = Opportunity.relative_percentage(@in_management_analysis, @opportunities.count)
@pp_perc = Opportunity.relative_percentage(@in_proposal, @opportunities.count)
@rw_perc = Opportunity.relative_percentage(@in_review, @opportunities.count)
@conversion_rate = '%.2f' % [Opportunity.conversion_rate]
@potential_revenue = Opportunity.potential_revenue
end
end
尽管它按预期工作,但看起来控制器有点太胖了,我觉得如果应用程序缩放当前方法,由于正在完成的查询量,它会非常慢。那么,有没有办法重构它以优化数据检索和 KPI 的显示?
提前致谢
您可以尝试实施 Facade Pattern in Rails。它会让你的控制器变瘦,但在查询部分你仍然需要进行这些查询,没有办法跳过它。
您可以尝试通过添加索引和创建 sql 视图来优化数据库,当您以后遇到性能滞后时,这时候就像过早优化一样