【问题标题】:Custom Rails Dashboard, how to optimize data retrieval to display in view?自定义 Rails Dashboard,如何优化数据检索以显示在视图中?
【发布时间】:2017-03-21 15:41:28
【问题描述】:

我正在为一个需要我计算一些 KPI 的学校应用程序制作自定义仪表板,现在的方法是从控制器的仪表板/索引操作中的 Opportunity 类中调用几个类方法,并存储每个方法导致将在图块中使用的变量。因此,每个变量都是仪表板的不同磁贴。

这些方法属于如下所示的 Opportunity 类:

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 的显示?

提前致谢

【问题讨论】:

    标签: ruby-on-rails view model controller dashboard


    【解决方案1】:

    您可以尝试实现Facade Pattern in Rails。它会使你的控制器变瘦,但在查询部分你仍然需要进行这些查询,没有办法跳过它。

    以后遇到性能卡顿的时候可以尝试通过添加索引和创建sql视图来优化db,这时候就会像过早优化一样

    【讨论】:

    • 这正是我想要的,感谢您的快速响应和非常有用的资源,我一回到家就会实施它,绝对是我在说的。我认为避免大量查询是不可能的,但使用这种新方法,它肯定会看起来更干净,更适合测试。
    • 很高兴知道它有帮助:)
    猜你喜欢
    • 2017-12-15
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    相关资源
    最近更新 更多