首页 > 解决方案 > Symbol 与 100 的比较失败

问题描述

我正在为新版本的 Ruby on Rails 重写一个名为 Emissions Gateway 的程序。

我有一个使用名为 Squeel 的 gem 的语法编写的方法,我很难重新编写它。我已经失败了4个多小时,似乎无法弄清楚。

这就是这里的方法,它位于名为 datalogger.rb 的模型中,以及 datalogger.rb 模型的模式信息。

# == Schema Information
#
# Table name: dataloggers
#
#  id                    :integer          not null, primary key
#  project_id            :integer
#  created_at            :datetime         not null
#  updated_at            :datetime         not null
#  original_file_name    :string(255)
#  original_content_type :string(255)
#  original_file_size    :integer
#  original_updated_at   :datetime
#  status                :string(255)      default("incomplete")
#  hours                 :integer
#  readings_total        :integer
#  readings_start        :datetime
#  readings_stop         :datetime
#  direct_upload_url     :string(255)
#  version               :string(255)
#  comments              :string(255)
#  bypass                :boolean          default(FALSE)
#  device_id             :integer
#  device_name           :string(255)
#  device_description    :string(255)
#  device_serial         :integer
#  md5                   :string(255)
#  user_id               :integer
#  reported_at           :datetime
#  user_reported_id      :integer
#  reported              :boolean

def stats(temperatures)
    unless bypass
      @temperatures = temperatures
      @stats = {}

      @cumulative_percent_at = 0
      @cumulative_readings = 0

      @temperatures.each_cons(2) do |current_n, next_n|
        # puts "Evaluating #{current_n} and #{next_n}"
        @stats["#{next_n}"] = {}

        # CHANGED v0.009 9/27/2021 Scott Milella
        # readings_at = readings.where{(temperature.gt current_n) & (temperature.lteq next_n)}.sum(:frequency)
        readings_at = Reading.where(:temperature > current_n).and(:temperature <= next_n).sum(:frequency)
        @stats["#{next_n}"][:readings] = readings_at
        # puts "Readings at: #{readings_at}"

        # @cumulative_readings = @stats.map{|_, v| v[:readings] }.sum
        # puts "Cumulative Readings: #{cumulative_readings}"

        percent_at = ((readings_at.to_f / readings_total) * 100 )
        @stats["#{next_n}"][:time_at] = percent_at
        @cumulative_percent_at += percent_at
        # puts "Percent at: #{percent_at}%"

        # puts "Cumulative Percent at: #{@cumulative_percent_at}"

        percent_over = 100 - @cumulative_percent_at
        @stats["#{next_n}"][:over] = percent_over
        # puts "Percent Over: #{percent_over}%"

        # puts "Progress: #{@cumulative_readings}/#{readings_total} readings"
      end
    end

这是我改变的方法:

readings_at = Reading.where(:temperature > current_n)
.and(:temperature <= next_n).sum(:frequency)      

您可以看到我在上面的方法中所做的更改以及我用# CHANGED 表示的内容。它给了我这个错误,称为符号与 100 的比较失败,这对我来说毫无意义,因为 :symbol 是来自另一个名为 Reading 的模型的整数。

这是那个模型:

# == Schema Information
#
# Table name: readings
#
#  id            :integer          not null, primary key
#  temperature   :integer
#  frequency     :integer
#  datalogger_id :integer
#

class Reading < ActiveRecord::Base
  belongs_to :datalogger
  attr_accessible :frequency, :temperature, :datalogger_id

  validates_presence_of :frequency, :temperature, :datalogger_id
end

我不明白为什么我不能将整数与整数进行比较,无论它是否在符号中?我有语法错误还是什么?它没有给我语法错误。我已经尝试了大约 1000 种其他方法来编写它,并且我从 > not found in Array 到各种其他事情中得到了各种错误。如果有人想查看整个 datalogger.rb 模型,我会发布它,它相当长,而且似乎正是这种方法存在问题。

这是我从当前版本的 Emissions Gateway 的 SQL 中捕获的一行代码:您可以看到数字 272 应该是 current_n 而 150 是 next_n 我可以在 better_errors 控制台上验证这些值。所以我不明白我哪里出错了。我猜它可能与 each_cons 方法有关,也许我不明白。

我对其进行了修改,以便您可以在一个地方看到所有 SQL,否则它会显示为一长行。我会在之后显示它以防万一它令人困惑:

2021-09-27T18:50:49.173173+00:00 app[web.1]:  (1.5ms)  SELECT SUM("readings"."frequency") 
AS sum_id FROM "readings" 
WHERE "readings"."datalogger_id" = 272 
AND (("readings"."temperature" > 100 
AND "readings"."temperature" <= 150))

出现的 SQL

2021-09-27T18:50:49.173173+00:00 app[web.1]:  (1.5ms)  SELECT SUM("readings"."frequency") AS sum_id FROM "readings" WHERE "readings"."datalogger_id" = 272 AND (("readings"."temperature" > 100 AND "readings"."temperature" <= 150))

如果有人能指出我需要如何重新编写这种方法,我将不胜感激,我已经尝试了几个小时,但没有成功。

这是 squeel 的说明,以防有人需要查看说明。

https://github.com/activerecord-hackery/squeel

我希望这颗宝石从未被写过,给我带来了如此多的痛苦,这是不真实的!

谢谢你,

斯科特

标签: ruby-on-railsrubyactiverecord

解决方案


好的,让我们深入研究一下您的查询:

readings_at = Reading.where(:temperature > current_n).and(:temperature <= next_n).sum(:frequency)

两者:temperature > current_n:temperature <= next_m将符号(左侧)与整数(右侧)进行比较。这就是为什么你得到一个ArgumentError.

实现您正在做的事情的 Rails 语法是:

readings_at = Reading.where('temperature > ? AND temperature <= ?', current_n, next_n).sum(:frequency)

或者,如果您愿意,添加倍数where将为AND您的查询添加一个子句。所以下面是等价的:

readings_at = Reading.where('temperature > ?', current_n).where('temperature <= ?', next_n).sum(:frequency)

使用?保证 Rails 将为您“清理”此输入以防止 SQL 注入。


推荐阅读