Ruby как вернуть экземпляр вылеченного массива - PullRequest
2 голосов
/ 13 февраля 2020

У меня есть метод в моей модели rails, который возвращает анонимный класс:

def today_earnings
Class.new do
  def initialize(user)
    @user = user
  end

  def all
    @user.store_credits.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day)
  end

  def unused
    all.map { |el| el.amount - el.amount_used }.instance_eval do
      def to_f
        reduce(:+)
      end
    end
  end

  def used
    all.map(&:amount_used).instance_eval do
      def to_f
        reduce(:+)
      end
    end
  end
end.new(self)

end

Я хочу добиться возможности цепочки результатов таким образом user.today_earning.unused.to_f, и у меня есть некоторые проблемы с экземпляром eval, потому что когда я вызываю to_f для результата, это неопределенный метод, я предполагаю, что это связано с ruby копированием возвращенного значения, поэтому экземпляр изменяется, это правда? И если я прав, как я могу изменить код, чтобы он работал. Также мне интересно, может ли создание новой модели быть лучшим решением, чем аномный класс, поэтому мне нужен совет, если анонимный класс элегантен в этом случае, и если да, то как я могу добавить метод to_f к возвращаемым значениям

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Это выглядит как «умный», но нелепо сложный способ сделать что-то, что можно просто и эффективно сделать в базе данных.

User.joins(:store_credits)
    .select(
       'users.*',
       'SUM(store_credits.amount_used) AS amount_used',
       'SUM(store_credits.amount) - amount_used AS unused',
    )
    .where(store_credits: { created_at: Time.current.beginning_of_day..Time.current.end_of_day })
    .group(:id)
1 голос
/ 13 февраля 2020

Да, класс Anonymous делает код намного сложнее. Я бы предложил отдельный класс. Здесь будут решены 2 проблемы.

  1. определение некоторого анонимного класса снова и снова, когда мы вызываем метод today_earnings.
  2. Читаемость кода.

Теперь, перейдя к актуальному вопросу, вы можете попробовать что-то похожее на hash_with_indifferent_access. Код выглядит следующим образом.

class NumericArray < Array
   def to_f
     reduce(:+)
   end
end

Array.class_eval do
   def with_numeric_operations
      NumericArray.new(self)
   end
end

Использование будет:

Class Earnings
  def initialize(user)
    @user = user
  end

  def all
    @user.store_credits.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day)
  end

  def unused
    all.map { |el| el.amount - el.amount_used }.with_numeric_operations
  end

  def used
    all.map(&:amount_used).with_numeric_operations
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...