将一个对象数组转换为ActiveRecord :: Relation

我有一个对象的数组,我们称之为Indicator 。 我想在这个数组上运行Indicator类的方法(那些def self.subjects变种,作用域等等)。 我知道在一组对象上运行类方法的唯一方法是让它们成为ActiveRecord :: Relation。 所以我最终诉诸添加to_indicators方法到Array

 def to_indicators # TODO: Make this less terrible. Indicator.where id: self.pluck(:id) end 

有时我链接了相当多的这些范围来筛选结果,在类方法中。 所以,即使我调用一个ActiveRecord :: Relation方法,我不知道如何访问该对象。 我只能通过all的内容来了解​​它的内容。 但是all都是一个数组。 那么我必须将该数组转换为ActiveRecord :: Relation。 例如,这是其中一种方法的一部分:

 all.to_indicators.applicable_for_bank(id).each do |indicator| total += indicator.residual_risk_for(id) indicator_count += 1 if indicator.completed_by?(id) end 

我想这可以归结为两个问题。

  1. 如何将一个对象数组转换为一个ActiveRecord :: Relation? 最好不要每次都做一次。
  2. 在ActiveRecord :: Relation上运行def self.subjectstypes方法时,如何访问ActiveRecord :: Relation对象本身?

谢谢。 如果我需要澄清任何事情,请告诉我。

如何将一个对象数组转换为一个ActiveRecord :: Relation? 最好不要每次都做一次。

你不能将一个数组转换成一个ActiveRecord :: Relation,因为一个Relation只是一个SQL查询的构build器,而且它的方法不能对实际数据进行操作。

但是,如果你想要的是一个关系,那么:

  • 对于ActiveRecord 3.x,不要调用all ,而是调用scoped ,这将返回一个关系,它代表了all将在一个数组中给你的相同的logging。

  • 为ActiveRecord 4.x,只需调用all ,这将返回一个关系。

在ActiveRecord :: Relation上运行def self.subjectstypes方法时,如何访问ActiveRecord :: Relation对象本身?

在Relation对象上调用该方法时, self就是关系(与其定义的模型类相反)。

你可以把一个对象数组arr转换成这样的ActiveRecord :: Relation(假设你知道哪个类是对象,你可能会这样做)

 MyModel.where(id: arr.map(&:id)) 

你必须使用where但它是一个有用的工具,你不应该不愿意使用。 现在你有一个单线程转换数组到一个关系。

map(&:id)将把你的对象数组转换为只包含它们的id的数组。 将一个数组传递给where子句将会生成一个IN语句的SQL语句,如下所示:

 SELECT .... WHERE `my_models`.id IN (2, 3, 4, 6, .... 

请记住,数组的sorting会丢失 – 但是因为你的目标只是在这些对象的集合上运行一个类方法,所以我认为这不会是一个问题。

那么,就我而言,我需要将一个对象数组转换为ActiveRecord :: Relation ,并将其sorting为一个特定的列(例如id)。 由于我正在使用MySQL, 字段function可能会有所帮助。

 MyModel.where('id in (?)',ids).order("field(id,#{ids.join(",")})") 

SQL看起来像:

 SELECT ... FROM ... WHERE (id in (11,5,6,7,8,9,10)) ORDER BY field(id,11,5,6,7,8,9,10) 

MySQL字段function

为什么不把你的对象存储在一个空的ActiveRecord :: Relation中,这样你就可以访问它们。 像这样

 collection = MyModel.where(attribute: nil) #=> #<ActiveRecord::Relation []> 

注意:只要确保你只返回一个空的活动logging关系。 您可以将对象存储在集合中,并将其视为活动logging对象的常规集合,而不必执行涉及将对象数组转换为活动logging关系的杂技。 你可以在你的rails控制台中testing这个。 它为我工作。 我知道这是一个黑客,但我目前还没有意识到一个ruby的方式分配一个空的活动logging关系的variables。