как сравнить запись с предыдущим - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть таблица потребления

  create_table "consumptions", force: :cascade do |t|
    t.float "kilometers"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "user_id"
  end

Вот список расходов для пользователя 1

 #<Consumption:0x007f8654895080     
  id: 1,
  kilometers: 10000.0,
  created_at: Wed, 07 Nov 2018 15:23:21 UTC +00:00,
  updated_at: Wed, 07 Nov 2018 15:23:21 UTC +00:00,
  user_id: 1>,
 #<Consumption:0x007f865489c268
  id: 4,
  kilometers: 10800.0,
  created_at: Wed, 24 Oct 2018 14:30:23 UTC +00:00,
  updated_at: Thu, 08 Nov 2018 12:35:37 UTC +00:00,
  user_id: 1>,
 #<Consumption:0x007f8654893f50
  id: 6,
  kilometers: 11400.0,
  created_at: Thu, 08 Nov 2018 11:56:52 UTC +00:00,
  updated_at: Thu, 08 Nov 2018 12:36:42 UTC +00:00,
  user_id: 1>,

Я хочу сравнить разницу километров между каждым расходом ...

consumptions

id |   km  | 
1  | 10000 | 
4  | 10800 | 
6  | 11400 | 

Результат между id 1 и 4 должен быть 800

Результат от 4 до 6 должен быть 600

Ответы [ 4 ]

0 голосов
/ 12 ноября 2018

Я нашел более простой способ:

Итак, я добавил атрибут difference, установленный по умолчанию для 0 в consumptions

class Consumption < ApplicationRecord
    belongs_to :user

    before_save :count_difference

    def count_difference
        if Consumption.any?
            if Consumption.last.user_id == self.user_id
                self.difference = Consumption.last.kilometers - self.kilometers
            end
        end
    end

end
0 голосов
/ 08 ноября 2018

Я бы порекомендовал вам взглянуть на https://github.com/geokit/geokit-rails Вам просто нужно добавить acts_as_mappable к вашей модели (решите, конфигурируете ли вы значения по умолчанию или поместите их в вашу модель, я думаю, что лучше всего было бы сделать это в файле конфигурации).

Тогда вы просто используете метод by_distance, и ваш код будет выглядеть так здорово:)

0 голосов
/ 08 ноября 2018

Чтобы дать больше ответа 'ruby':

def difference_in_km(obj_1, obj_2)
  (obj1.kilometers - obj2.kilometers).abs
end

Для обработки отрицательных чисел используется abs, например, вместо -400 возвращается 400.

Это позволяет вам:

con_1 = Consumption.find(1)
con_2 = Consumption.find(4)

difference_in_km(con_1, con_2)

Другой подход заключается в добавлении метода экземпляра в ваш класс потребления:

class Consumption < ApplicationRecord
  ....
  ....

  def distance_from(other_consumption)
    (kilometers - other_consumption.kilometers).abs
  end
end

Это позволит вам сделать:

con_1.distance_from(con_2)
0 голосов
/ 08 ноября 2018

Какую базу данных вы используете?

По сути, вы хотите использовать оконную функцию:

например. для PostgreSQL:

select id, kilometers - lag(kilometers) over (order by id) as difference? from consumptions;

Справочник PostgreSQL

Справочник по MySQL

Другой пример SO

Затем можно использовать find_by_sql для извлечения значения в качестве модели ActiveRecord, здесь предлагается .

Результаты будут возвращены в виде массива с запрошенными столбцами инкапсулированы как атрибуты модели, из которой вы вызываете этот метод.

Я не пробовал, но ваш будет выглядеть так:

Consumptions.find_by_sql('select id, kilometers - lag(kilometers) over (order by id) as difference? from consumptions')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...