0

TL;博士

我需要一种方法来重构包含多个对象和一些复杂数据的复杂用户仪表板以显示会计图表。我的模型和控制器很乱,所以如果有人有一些提示或建议,我真的很感激:)!

长版:

我目前正在开发一个帮助用户协调晚餐俱乐部和所有相关会计的应用程序。(晚餐俱乐部是一群人,轮流为其余的人做饭,然后您支付少量费用参加。这在我所在的宿舍和大学中很正常)。当您登录时,您会看到一个仪表板,其中包含所有重要信息,分为三个部分:下一次晚餐和注册选项,下一次您必须做饭的晚餐,以及当前债务、支出等会计概览。

这变得非常混乱:我的控制器中有很多实例变量,还有很多方法可以在我的模型中呈现这个视图。

所以现在真正的问题是:谁能告诉我任何好的提示、设计模式或一般建议来帮助我重构这段代码?我已经阅读了有关演示者、服务对象、装饰器等的信息,但我不确定使用哪个以及如何使用?

下面是一些现在看起来有多糟糕的例子(厨房是一群人一起吃晚饭):

# app/controllers/dashboard_controller.rb
def index
  @user = current_user
  @kitchen = @user.kitchen

  @upcoming_dinner_clubs = @user.upcoming_dinner_clubs # The next dinner clubs where the current user have to cook
  @users_next_dinner_club = @user.next_dinner_club # The first of upcoming_dinner_clubs
  @unpriced_dinner_clubs = @user.unpriced_dinner_clubs # Old dinner clubs where the user haven't specified a price yet

  # The next dinner club in the kitchen
  @next_dinner_club = @kitchen.next_dinner_club if @kitchen.next_dinner_club
  @todays_dinner_club = @next_dinner_club if @next_dinner_club && @next_dinner_club.date.today?
end

下面的视图显示了一些通过 javascript 呈现的用户费用和支出的图表。我的观点是在haml。

# app/views/dashboard/_expenses.html.haml
%h2 Dit forbrug
  %p
    = t '.usage_html', expenses: number_to_currency(@user.last_month_expenses), spendings: number_to_currency(@user.last_month_spendings), results: number_to_currency(@user.last_month_results)
    = content_tag :div, "", id: "revenue_chart", class: "chart dashboard-chart", data: { chart: @user.usage_chart_data }
    = t '.results_html', results: number_to_currency(@user.total_results)
    = content_tag :div, "", id: "result_chart", class: "chart dashboard-chart", data: { chart: @user.result_chart_data }

不希望您对所有细节以及方法的工作方式感到厌烦,但这是我拥有的方法,仅用于在视图中显示费用和支出数据:

# app/models/user.rb
def last_month_expenses
  expenses_for((1.month + 1.day).ago, 1.day.ago)
end

def last_month_spendings
  spendings_for((1.month + 1.day).ago, 1.day.ago)
end

def last_month_results
  results_for((1.month + 1.day).ago, 1.day.ago)
end

def spendings_for(start_date, end_date, kitchen)
end

def expenses_for(start_date, end_date, kitchen)
end

def fee_for(start_date, end_date, kitchen)
end

def accounting_query_conditions(start_date, end_date, kitchen)
  {date: start_date..end_date, kitchen_id: kitchen.id}
end

def results_for(start_date, end_date)
  spendings_for(start_date, end_date) - expenses_for(start_date, end_date)
end

def total_fee(date = Date.today, kitchen = primary_kitchen)
end

def total_spendings(date = Date.today, kitchen = primary_kitchen)
end

def total_used_on_dinner_clubs(date = Date.today, kitchen = primary_kitchen)
end

def total_expenses(date = Date.today, kitchen = primary_kitchen)
end

def total_results(date = Date.today, kitchen = primary_kitchen)
  total_expenses(date, kitchen) - total_spendings(date, kitchen)
end
4

1 回答 1

3

让我们从一个规则开始,看看它需要我们多远:

控制器中只有 1 个实例变量

为了遵循此规则,我认为您可能希望创建一个 UserDashboard 对象

class UserDashboard

  attr_reader :user
  def initialize(user)
    @user = user
  end

  def kitchen
    user.kitchen
  end

  def todays_club
    next_dinner_club if next_dinner_club && next_dinner_club.date.today?
  end

end

所以,在你的控制器中:

def index
  @dashboard = UserDashboard.new current_user
end

通过这种方式,您将所有关于球杆的逻辑和任何东西都放在仪表板对象上,而不是放在控制器或用户对象中。这是一个类似演示者的模式。

于 2013-06-09T22:39:39.307 回答