1

我试图避免由于 NilClass 导致的 NoMethod 错误。我的代码如下所示:

@branded, @nonbranded, @unknown, @affiliate, @social, @referral, @paid, @direct, @email = [], [], [], [], [], [], [], [], []

count = 0
while count < 6
    date = SDLW + count
    #TODO There has to be a better way than this.
    branded_check = Metric.first(start_date: date, end_date: date, source: 'branded')
    nonbranded_check = Metric.first(start_date: date, end_date: date, source: 'nonbranded')
    unknown_check = Metric.first(start_date: date, end_date: date, source: 'unknown')
    affiliate_check = Metric.first(start_date: date, end_date: date, source: 'affiliate')
    social_check = Metric.first(start_date: date, end_date: date, source: 'social')
    referral_check = Metric.first(start_date: date, end_date: date, source: 'referral')
    paid_check = Metric.first(start_date: date, end_date: date, source: 'paid')
    direct_check = Metric.first(start_date: date, end_date: date, source: 'direct')
    email_check = Metric.first(start_date: date, end_date: date, source: 'email')

    branded_check = branded_check.nil? ? 0 : branded_check.visits
    nonbranded_check = nonbranded_check.nil? ? 0 : nonbranded_check.visits
    unknown_check = unknown_check.nil? ? 0 : unknown_check.visits
    affiliate_check = affiliate_check.nil? ? 0 : affiliate_check.visits
    social_check = social_check.nil? ? 0 : social_check.visits
    referral_check = referral_check.nil? ? 0 : referral_check.visits
    paid_check = paid_check.nil? ? 0 : paid_check.visits
    direct_check = direct_check.nil? ? 0 : direct_check.visits
    email_check = email_check.nil? ? 0 : email_check.visits

    @branded        << branded_check
    @nonbranded << nonbranded_check
    @unknown        << unknown_check
    @affiliate  << affiliate_check
    @social         << social_check
    @referral   << referral_check
    @paid           << paid_check
    @direct         << direct_check
    @email          << email_check

    count += 1
end

我相信必须有一种更清洁、更简洁的方法来做到这一点。尽管谷歌搜索和阅读,我还是无法弄清楚。任何关于如何重构的想法都将不胜感激。

4

4 回答 4

3

当然,创造一种方法来避免重复自己

def visits(tag, date)
  check = Metric.first(start_date: date, end_date: date, source: tag)    
  check.present? ? check.visits : 0   # or 'check.nil? ? 0 : check.visits' if you prefer
end

在你的方法中

count = 0
while count < 6
  date = SDLW + count

  @branded << visits('branded', date)
  @nonbranded << visits('nonbranded', date)
  ...

  count += 1
end
于 2012-12-23T13:06:36.343 回答
2

让我们将调用Metric.first放在一个块中并使用instance_variable_set.

['branded', 'nonbranded', ...].each do |source|
  visits = 0.upto(5).map do |count|
    date = SDLW + count
    metric = Metric.first(start_date: date, end_date: date, source: source)
    if metric.nil? then 0 else metric.visits end
  end
  instance_variable_set "@#{source}".to_sym, visits
end
于 2012-12-23T13:08:35.570 回答
1

除了其他解决方案之外,while 循环可能可以替换为:

(SDLW...SDLW+6).each do |date|
  # date = SDLW + count #This line is superfluous
  @branded << visits('branded', date)
  #or one of the other solutions
  #etc
  # count += 1 # remove this line
end
于 2012-12-23T16:36:42.130 回答
0

例如,我只为一个来源制作。

@branded, @nonbranded, @unknown, @affiliate, @social, @referral, @paid, @direct, @email = [], [], [], [], [], [], [], [], []

class Metric < ActiveRecord::Base
  scope :dates, lambda { |start_date, end_date| where(:start_date => start_date, :end_date => end_date) }
  scope :branded, lambda { where(:source => "branded") }
  # ... other scopes
end

# ...

6.times do |count|
  date = SDLW + count
  by_date = Metric.dates(date, date)
  @branded << by_date.branded.try(:visits).to_i
  # ... other sources
end

更新instance_variable_set:使用Jan解决方案和 Dave Newton 请求中的想法重构解决方案。

6.times do |count|
  date = SDLW + count
  [:branded, :nonbranded, :unknown, :affiliate, :social, :referral, :paid, :direct, :email].each do |source|
    instance_variable_set :"@#{source}", [] unless instance_variable_get :"@#{source}"
    visits = Metric.first(start_date: date, end_date: date, source: source).try(:visits).to_i
    instance_variable_set :"@#{source}", instance_variable_get(:"@#{source}").push(visits)
  end
end
于 2012-12-23T13:09:28.043 回答