如何向 Rails 中的 ActiveRecord 对象添加 property/use method_missing 方法?

How to add a property/use method_missing approach to an ActiveRecord object in Rails?

我正在查询 mysql 数据库并返回由联接创建的对象数组。据我了解,ActiveRecord select 命令 returns 一个新对象数组,每个对象都具有连接中两个表的属性。

我想对这些对象中的每一个执行一些计算,并将一些属性与对象相关联。我明白,如果这是我的 class,我可以使用 method_missing 方法,如 here 所示。但是,由于此对象是由 select 命令创建的,因此我没有可以定义 add_attrs 函数的 class 代码。这可能吗?使用 method_missing 是正确的方法吗?如果是,我该如何实施?

这是初始查询,其中 returns ActiveRecord 对象数组。

def self.select_with_location
    select("advertisements.id, advertisements.weight, locations.latitude, locations.longitude")
end

如果我转到 ruby 控制台并键入命令

advertisements = Advertisement.joins(:locations).select_with_location
puts advertisements[0].inspect

我应该得到类似的东西:

{id: 0, weight: 5, locations.latitude: 49.03030, locations.longitude: 50.5050}

现在,我想要遍历广告并对每个权重执行计算。我想将该计算的结果存储到广告的新属性中,我想将其称为 weight_multiplier。计算完成后,如果我转到 ruby 控制台并键入以下命令:

puts advertisements[0].inspect

我想得到结果

{id:0, weight: 5, locations.latitude: 49.03030, locations.longitude: 50.5050, weight_multiplier: 0.446003}

在此示例中,数字本身并不重要,我只想将 weight_multiplier 属性添加到数组中的每个广告。

我知道下面的代码不正确,但这是该函数的要点:

def self.assign_weight_multiplier advertisements
    totalWeights = advertisements.inject(0){|sum,advertisement| sum + advertisement.weight }
    advertisements.each do |advertisement|
      advertisement.weight_multiplier = (Float(advertisement.weight)/Float(totalWeights))
    end
    advertisements
end

您可以向 Advertisement class

添加 2 个新方法
def total_weight
  @total_weight ||= Advertisement.sum(:weight)
end

def weight_multiplier
  self.weight.to_f / total_weight
end

然后你可以调用 weight_multiplier 作为实例方法 Advertisement instance