Home > Blockchain >  nil can't be coerced
nil can't be coerced

Time:01-29

I'm trying to return the 12 monthly data, however I keep getting that nil can't be coerced into Integer, this happen when starting with mapping from 0..11 because I use months.ago to group the data which it starts to count from the current month.

def yearly_results
    return [] unless user.results.order(id: :desc).where('created_at >= ?', 30.days.ago)

    attributes = [:skin_age, :skin_age_adjusted, :skin_tightness, :purity, :hyperpigmentation_face_score]

    results = []
    #  We create a Hash with every months attributes and values

    (0..11).map do |months_ago|
      month_results = grouped_by_months[months_ago.months.ago.strftime('%Y%m')] || []

      months_with_attr = month_results.reduce({}) do |key, value|
   
        attributes.each do |attr_name|
          key[attr_name] ||= 0
          key[attr_name]  = value.send(attr_name)
        end
        key
      end

      if months_with_attr.present?
        months_with_attr.transform_values do |value|
          value.to_f / month_results.count
        end
      end
      results << months_with_attr.presence
    end
    results.reverse
  end

This is the error that I keep getting.

*** TypeError Exception: nil can't be coerced into Integer

nil

CodePudding user response:

Given you want to use as little SQL as possible i´d propose the following:

attributes = [:skin_age, :skin_age_adjusted, :skin_tightness, :purity, :hyperpigmentation_face_score]

user.results.order(id: :desc).where('created_at >= ?', 30.days.ago)
.group_by{|result| result.created_at.month }
.transform_values{|results_per_month| attributes.map{|attr| [attr, results_per_month.map(&attr).reduce(&: ).to_f / results_per_month.count] }.to_h }

CodePudding user response:

So if i get this right, you want to calculate the average per month.

I´d suggest to do this with SQL:

attributes = [:skin_age, :skin_age_adjusted, :skin_tightness, :purity, :hyperpigmentation_face_score]

# Get the average with SQL (for Postgres)
averages = user.results.order(id: :desc).where('created_at >= ?', 30.days.ago)
.group("date_trunc('month', created_at)").select("date_trunc('month', created_at) AS month", attributes.map{|attr| "AVG(#{attr}) AS average_#{attr}" })

# Then group by month
averages.group_by{|res| res['month'].month }
.transform_values{|results_per_month| results_per_month.map{|result_per_month| result_per_month.without('id', 'month') }  }
# => {1 => [{"average_skin_age" => 30, ...}], 2 => [{"average_skin_age" => 32, ...}],}
  •  Tags:  
  • Related