ruby-on-rails Ruby Mixin / Rails Concern在所有包含类之间共享变量

3zwtqj6y  于 2023-05-19  发布在  Ruby
关注(0)|答案(1)|浏览(145)

我正在尝试创建一个关注点,它保存从包含类Map的字段。然后我需要根据所有Map的数据执行操作。这是我目前拥有的一个简化:

require 'active_support/concern'

module MyConcern
  extend ActiveSupport::Concern

  included do
  end

  def self.mapped_fields
    # _ = [Test, Test2]
    @@all_fields
  end

  class_methods do
    def add_field(name)
      @@all_fields ||= []
      @@all_fields << name 
    end
  end

end

class Test
  include MyConcern
  
  add_field :test
end

class Test2
  include MyConcern
  
  add_field :test_2
end

puts MyConcern.mapped_fields
# => [:test, :test_2]

但是,如果我不急于加载包含类_ = [Test, Test2]@@all_fields变量永远不会被触及。这使得在开发中使用它变得不切实际(我认为它在生产环境中会工作得很好,因为默认情况下所有类都是即时加载的)。
是什么让我怀疑这是否是正确的方法?感觉怪怪的。Rubocop说我应该用类示例变量(规则Style/ClassVars)替换所有的类变量,但我不知道如何使用它来达到同样的效果。
有没有更好的办法?我在第一次尝试时就已经将Map存储到数据库中了。但这似乎是不必要的,因为所有Map都是以声明的方式定义的,这也使得有必要将Map镜像到数据库中,从而增加了复杂性。所以我想利用ruby的特性。

在原始问题上编辑更多的上下文

这里讨论的关注点是为了跟踪大量设置了空值的数据库列,以便建议用户填写它们。Concern为包含它的模型添加了update/create/destroy触发器,这些触发器检查使用上面提到的add_field方法定义的字段,但非简化版本看起来像这样

add_fields fields: {
    FIELD_ONE: { filled: ->(parent) { parent&.field_one.present? } }
}

在设置Map之后,我可以为用户运行所有的filled Procs,并将空白字段显示给前端。这个解决方案不能很好地解决的具体问题是,应该运行Proc的列表(以便获得我应该向用户建议的缺失字段)。

jmp7cifd

jmp7cifd1#

我不会像这样使用类来保存变量信息。我的目标是一个单体或类似的东西。以下是一些涂鸦:

class SharedFields
  attr_reader :shared_array

  def self.instance
    Thread.current[:SharedFields] ||= new
  end

  def initialize
    @shared_array = []
  end
end

...

class Test
  def in
    SharedFields.instance.shared_array << :foo
  end

  def out
    SharedFields.instance.shared_array
  end
end

test = Test.new
test.in
test.out # [:foo]
test.in
test.out # [:foo, #foo]

你懂的没有类变量。看起来它可能是线程安全的。您在测试中有一个明显的地方可以存根/模拟。如果你需要做一些棘手的事情的关系的某一部分,你可以。

相关问题