防止ActiveRecord关系转换为数组

时间:2019-07-26 04:41:12

标签: ruby-on-rails ruby activerecord ruby-on-rails-5.2

更新:

如何将虚拟属性添加到模型并保留活动记录关系。

我尝试了以下操作,但是.each返回一个数组,而不是活动记录。我还能使用什么其他方法?


我的set_listable_for方法正在将activerecord关系转换为数组。我想保留ActiveRecord关系。

在运行时,我向活动记录模型添加了attr_access。

def add_listable_attribute_to(*relation)
  relation.each do |rel|
    rel[1].first.class.class_eval do
      attr_accessor :listable
    end
  end
end

然后我使用此方法将所有记录的属性值设置为相同的值。...

   def set_listable_for(relation, object)
      relation.each do |record|
        record.listable = object
      end
    end

但是,我的ActiveRecord关系被转换为数组后缀。

如何保留Active Record关系,因为我不需要数组。由于我在这里继续使用它,并继续对其进行范围和查询...

def union_scope(*relation)
  add_listable_attribute_to(*relation)

  listable = relation.first[0]
  combined = set_listable_for(relation.first[1], listable)
  relation.drop(1).each do |relation_set|
    listable = relation[0]
    set_listable_for(relation_set[1], listable)
    combined = combined.or(relation_set[1])
  end
  combined
end

谢谢

2 个答案:

答案 0 :(得分:1)

.each调用执行查询并遍历结果。如果这在范围和分页之后在控制器中发生,这不是问题,但是如果在范围和分页之前被调用,则将加载整个模型数据集,这是不好的。

为避免这种情况,您需要在从数据库中检索数据后尽可能晚地设置listable。我可以看到三种解决方法:

  1. 在将关系加载到控制器或视图中之后,请使用装饰器包装该关系的实例。这很容易理解,但是却使功能脱离了模型层。

  2. listable回调中设置after_initialize。这将功能保留在模型层中,但增加了很多复杂性。

  3. 确保作用域确定后仅在控制器中调用set_listable_for。 #1的变体。

答案 1 :(得分:0)

通过在Select中添加“ AS”语句,我能够返回ActiveRecord模型。唯一的问题是,当我调用.count时,我需要使用.count(:all)或.count(:id)来防止错误。

Project.php