Ruby on rails 重构!如何在数据库查询中重用变量来检索Rails控制器中的数据

Ruby on rails 重构!如何在数据库查询中重用变量来检索Rails控制器中的数据,ruby-on-rails,ruby,database,postgresql,refactoring,Ruby On Rails,Ruby,Database,Postgresql,Refactoring,我正在尝试重构rails API中的代码,该API发送图表分析数据(目前正在运行)。因为我在1号上执行了相同的代码。书签,2。期刊,3。进球了,天气也不是很干燥 我正在尝试创建一个数据库查询(使用PostgreSQL),它可以接收类型(书签、目标、日志)作为参数。。。我试过使用[:type]和硬编码“type”,比如书签过去常去的地方 我要重构的现有(工作)代码: class AnalyticsController < ApplicationController before_acti

我正在尝试重构rails API中的代码,该API发送图表分析数据(目前正在运行)。因为我在1号上执行了相同的代码。书签,2。期刊,3。进球了,天气也不是很干燥

我正在尝试创建一个数据库查询(使用PostgreSQL),它可以接收类型(书签、目标、日志)作为参数。。。我试过使用[:type]和硬编码“type”,比如书签过去常去的地方

我要重构的现有(工作)代码:

class AnalyticsController < ApplicationController
  before_action :authenticate_user

  def entries_by_date
    bookmarks = current_user.bookmarks.group_by_day(
      :created_at,
      format: '%Y-%m-%d',
      range: 4.weeks.ago.midnight..Time.zone.now
    ).count
    journals = current_user.journals.group_by_day(
      :created_at,
      format: '%Y-%m-%d',
      range: 4.weeks.ago.midnight..Time.zone.now
    ).count
    goals = current_user.goals.group_by_day(
      :created_at,
      format: '%Y-%m-%d',
      range: 4.weeks.ago.midnight..Time.zone.now
    ).count

    entries_array = []
    entries_array.push(@bookmarks)
    entries_array.push(goals)
    entries_array.push(journals)

    total_entries_by_date = entries_array.inject { |memo, el| memo.merge(el) { |_k, old_v, new_v| old_v + new_v } }

    render json: {
      total_entries_by_date: total_entries_by_date,
      bookmarks: bookmarks,
      goals: goals,
      journals: journals
    }
  end
end
我已尝试当前用户。键入…>>未定义的局部变量或方法书签

我已尝试当前用户。[:键入]…>>语法错误,未知[“

我已经尝试过当前用户[:type]…>>NameError(未定义的局部变量或方法'bookmarks'

我已尝试当前用户。%{type}…&当前用户。{type}…&当前用户。${type}


任何指导都将不胜感激:)我是Ruby on Rails的新手,希望在我更好地理解如何重用传递到数据库查询中的变量后,我的代码会更枯燥一些。您已经非常接近解决方案了。只需使用并传递您要调用的方法的名称作为字符串或符号即可

def entries_by_date
  @bookmarks = fetch_activity(:bookmarks)
  @goals = fetch_activity(:goals)
  @journals = fetch_activity(:journals) 

  # ...
end

private

def fetch_activity(type)
  current_user.public_send(type).group_by_day(
    :created_at,
    format: '%Y-%m-%d',
    range: 4.weeks.ago.midnight..Time.zone.now
  ).count
end

@bookmarks = fetch_activity(bookmarks)
@goals = fetch_activity(goals)
@journals = fetch_activity(journals) 

您与解决方案非常接近。只需使用并传递要调用的方法的名称作为字符串或符号即可

def entries_by_date
  @bookmarks = fetch_activity(:bookmarks)
  @goals = fetch_activity(:goals)
  @journals = fetch_activity(:journals) 

  # ...
end

private

def fetch_activity(type)
  current_user.public_send(type).group_by_day(
    :created_at,
    format: '%Y-%m-%d',
    range: 4.weeks.ago.midnight..Time.zone.now
  ).count
end

@bookmarks = fetch_activity(bookmarks)
@goals = fetch_activity(goals)
@journals = fetch_activity(journals) 

为了改进Spickerman的答案,你应该考虑从控制器中提取Buiess逻辑并把它放在它所属的模型中:

class User < ApplicationRecord
  # Gets a single activity 
  def fetch_activity(type)
    public_send(type).group_by_day(
      :created_at,
      format: '%Y-%m-%d',
      range: 4.weeks.ago.midnight..Time.zone.now
    ).count
  end

  # Gets a hash containing the counts of the users activities and total 
  def fetch_activities(*types)
    types.each_with_object({}) do |key, hash|
      hash[key] = fetch_activity(key)
    end.then do |hash|
      hash.merge(total_entries_by_date: hash.values.sum)
    end
  end
  # ... 
end
class用户
模型比控制器更容易测试,因为您可以直接在对象上设置模型并调用方法,而不是通过HTTP和解析响应-这是控制器应尽可能精简的一个关键原因:

class AnalyticsController < ApplicationController
  before_action :authenticate_user

  def entries_by_date
    render json: current_user.fetch_activities(:bookmarks, :goals, :journals)
  end
end
class AnalyticsController为了提高Spickerman的答案,你应该考虑从控制器中提取Buiess逻辑,并把它放在它所属的模型中:

class User < ApplicationRecord
  # Gets a single activity 
  def fetch_activity(type)
    public_send(type).group_by_day(
      :created_at,
      format: '%Y-%m-%d',
      range: 4.weeks.ago.midnight..Time.zone.now
    ).count
  end

  # Gets a hash containing the counts of the users activities and total 
  def fetch_activities(*types)
    types.each_with_object({}) do |key, hash|
      hash[key] = fetch_activity(key)
    end.then do |hash|
      hash.merge(total_entries_by_date: hash.values.sum)
    end
  end
  # ... 
end
class用户
模型比控制器更容易测试,因为您可以直接在对象上设置模型并调用方法,而不是通过HTTP和解析响应-这是控制器应尽可能精简的一个关键原因:

class AnalyticsController < ApplicationController
  before_action :authenticate_user

  def entries_by_date
    render json: current_user.fetch_activities(:bookmarks, :goals, :journals)
  end
end
class AnalyticsController
Hi Spickermann,非常感谢!我非常接近,但是非常接近:)我现在要做一些关于公共发送语法的研究。感谢你花时间:)这是我第一个堆栈溢出问题Hi Spickermann,非常感谢!我非常接近,但是非常接近:)我现在要做一些关于公共发送语法的研究。感谢您抽出时间:)这是我有史以来第一个堆栈溢出问题是的,如果没有,在开始任何重构之前编写测试将是重构的一个伟大步骤。谢谢@max!我最近刚刚阅读了关于瘦控制器和“胖”模型的概念。我将花一些时间重构我的控件(非常有用,谢谢:)没问题。
Object#然后在Ruby 2.6中引入了/yeild_self
,因此您可能需要稍微调整代码以使其在旧版本中运行。是的,如果没有任何重构,那么在开始任何重构之前编写测试将是重构的一个伟大步骤。谢谢@max!我刚刚有了r最近,我开始讨论瘦控制器和“胖”模型的概念。我也将花一些时间以这种方式重构我的控制器。非常有用,谢谢:)没问题。
Object\n然后/yeild\u self
在Ruby 2.6中引入,因此您可能需要稍微调整代码,使其在旧版本中运行。