【问题标题】:Best way to refactor a Rails app using Rubocop使用 Rubocop 重构 Rails 应用程序的最佳方法
【发布时间】:2019-10-26 04:58:19
【问题描述】:

我正在处理一项奖学金申请,人们可以通过捐款来支持他们想要参与的不同计划。我需要一些帮助来帮助我在 Rails 中进行 Rubocop 重构。

我有以下问题;

  1. 控制器动作只调用一个模型方法而不是初始 找到或新的。在模型中创建自定义 .new 或 .update 方法 所有必要的。
  2. 索引的分配分支条件大小太大 高
  3. 方法行数过多

我已经尝试重构代码,但我仍然面临与代码相同的问题。

我的代码是;

仪表板控制器(初始*)

class DashboardController < ApplicationController
  def index
    #Paid Donations in Chart
    @paid_donations = Donation.where(payment: true).count
    #Unpaid Donations in Chart
    @unpaid_donations = Donation.where(payment: false).count
    #Total Donations Sum
    @total_donations_sum = Donation.where(payment: true).sum(:amount)
    #Deployed Donations
    @deployed_donations = Donation.where(deployment: true).sum(:amount)
    #Not Deployed Donations
    @not_deployed_donations = Donation.where(deployment: false,  payment: true).sum(:amount)
    #Deployed Donations Percentage
    @deployed_donations_percentage = (@deployed_donations.to_f / @total_donations_sum.to_f) * 100
    #Not Deployed Donations Percentage
    @not_deployed_donations_percentage = (@not_deployed_donations.to_f / @total_donations_sum.to_f) * 100

    #Total Donations
    @total_donations = Donation.count
    #Paid Donations
    @paid_donations = Donation.where(payment: true).count
    #Unpaid Donations
    @unpaid_donations = Donation.where(payment: false).count

    #All Programs
    @programs = Program.all
  end
end

仪表板控制器(重构)

class DashboardController < ApplicationController    
  def index
    # Paid Donations in Chart
    @paid_donations = Donation.paid_count
    # Unpaid Donations in Chart
    @unpaid_donations = Donation.unpaid_count
    # Total Donations Sum
    @total_donations_sum = Donation.paid_sum
    # Deployed Donations
    @deployed_donations = Donation.deployed_sum
    # Not Deployed Donations
    @not_deployed_donations = Donation.not_deployed_sum
    # Deployed Donations Percentage
    @deployed_donations_percentage = percentage(@deployed_donations, @total_donations_sum)
    # Not Deployed Donations Percentage
    @not_deployed_donations_percentage = (@not_deployed_donations.to_f / @total_donations_sum.to_f) * 100

    # Total Donations
    @total_donations = Donation.count
    # Paid Donations
    @paid_donations = Donation.paid_count
    # Unpaid Donations
    @unpaid_donations = Donation.unpaid_count

    # All Programs
    @programs = Program.all
  end
end

捐赠模式(初始)

class Donation < ApplicationRecord
  belongs_to :program
end

捐赠模型(重构)

Class Donation < ApplicationRecord
  belongs_to :program
  scope :paid_count, -> { where(payment: true).count }
  scope :unpaid_count, -> { where(payment: false).count }
  scope :paid_sum, -> { where(payment: true).sum(:amount) }
  scope :paid_sum, -> { where(payment: true).sum(:amount) }
  scope :deployed_sum, -> { where(deployment: true).sum(:amount) }
  scope :not_deployed_sum, -> { where(deployment: false).sum(:amount) }

  def percentage(donate, total)
    (donate.to_f / total.to_f) * 100
  end
end

我需要一些关于 Rails 最佳实践的帮助来解决这些问题,遵循瘦模型和瘦控制器 Rails 原则。

【问题讨论】:

    标签: ruby-on-rails rubocop


    【解决方案1】:

    我认为在这种情况下,您可以在模型 Donation 中创建方法以返回所有值以显示在 1 个哈希中。

    Class Donation < ApplicationRecord
      belongs_to :program
      scope :paid_count, -> { where(payment: true).count }
      scope :unpaid_count, -> { where(payment: false).count }
      scope :paid_sum, -> { where(payment: true).sum(:amount) }
      scope :deployed_sum, -> { where(deployment: true).sum(:amount) }
      scope :not_deployed_sum, -> { where(deployment: false).sum(:amount) }
    
      def self.deployed_donations_percentage
        (deployed_sum / size) * 100
      end
    
      def self.not_deployed_donations_percentage
        (not_deployed_sum / size) * 100
      end
    
      def self.info
        {}.tap do |info|
          info[:paid_donations] = paid_count
          info[:unpaid_donations] = unpaid_count
          info[:total_donations_sum] = paid_count
          info[:deployed_donations_percentage] = deployed_donations_percentage
          info[:not_deployed_donations_percentage] = not_deployed_donations_percentage
          #...anything you want to show
        end
    
      end
    end
    

    在你的控制器中

    class DashboardController < ApplicationController    
      def index
        # donations info
        @donations_info = Donation.info
        # All Programs
        @programs = Program.all
      end
    end
    

    在您看来,您可以使用

    <%= @donations_info[:paid_donations] %>
    

    【讨论】:

    • 这太酷了。很抱歉没有及早回复,我没有及早收到通知。我如何还重构控制器上的这些其他项目? # 已部署的捐款百分比 @deployed_donations_percentage = percentage(@deployed_donations, @total_donations_sum)# 未部署的捐款百分比 @not_deployed_donations_percentage = (@not_deployed_donations.to_f / @total_donations_sum.to_f) * 100。我在模型上使用了def percentage(donate, total) (donate.to_f / total.to_f) * 100 end,但不知道如何在控制器上实现
    • @PromisePreston 不客气,我已经更新了答案
    • 非常感谢。我刚刚注意到您使用了def self.deployed_donations_percentage (deployed_sum / size) * 100 end。我知道在方法定义期间使用 self.a_method 会使该方法成为类方法,但我想问为什么你必须在那里使用类方法而不是实例方法然后调用该方法控制器。另外,我想知道你为什么使用 size,因为我真的不明白它的最佳用法(何时以及如何使用 .size 方法)。请多多包涵。我的问题似乎很多。我还不是 ruby​​ on rails 方面的专家。谢谢。
    • @PromisePreston 在我们不关心对象或实例值时使用类方法。您可以看到 deploy_sum 和 size 不是任何一个实例的属性,也 deploy_donations_percentage 也是,所以这是类方法。 - count 将执行 SQL COUNT 查询 - length 将计算结果数组的长度 - size 将尝试选择两者中最合适的一个以避免过多查询
    • 感谢 Van 的明确解释。我已经尝试了您的解决方案,但我似乎遇到了障碍。当我尝试查看仪表板时,没有显示有关捐赠的信息。我认为原因是我们将业务逻辑移至 Donations Model,然后我们在 Dashboard Controller 上调用所有这些逻辑,这似乎无法从捐赠模型访问数据。 请问如何将我们在捐赠模型上定义的业务逻辑公开给仪表板控制器,因为它们是不同的控制器和模型?谢谢。
    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    • 2012-03-14
    相关资源
    最近更新 更多