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

例として、1 つのソースのみを作成しました。

@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

更新: 1 月のソリューションと Dave Newton の要求instance_variable_setからのアイデアを使用してリファクタリングされたソリューション。

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 に答える