【问题标题】:rails calling a class method based on the value of instance attribute?rails 根据实例属性的值调用类方法?
【发布时间】:2016-08-17 18:43:28
【问题描述】:

所以我基本上需要调用一个定义了一些方法和关系的类方法,但是需要根据这个类的实例的一个属性传递不同的参数,所以不同的实例得到不同的方法。

我需要这样做,因为我们使用的是旧数据库。

我得到了什么:

after_find do |instance|
  group_id = case instance.finance_object_type
    when 'E' then 281
    when 'A' then 282
    when 'K' then 283
    else ''
  end
  self.class.keyword_attribute :leistung_code, group_id: group_id
end

这行得通,keyword_attribute 方法会生成正确的方法和关系。

唯一的问题是,如果您加载 instance_1,然后立即使用不同的 finance_object_type 加载 instance_2,则为 instance_1 生成的方法也会被覆盖。

还有其他方法吗?

关键字属性:

def keyword_attribute(name, **options)
  foreign_key = options[:foreign_key] || name
  group_id    = options[:group_id]

  unless name.is_a?(Symbol)
    fail 'A name is required for the keyword_attribute'
  end

  unless group_id.is_a?(Integer)
    fail 'A group_id is required for the keyword_attribute'
  end

  self.belongs_to name,
    -> () { group_id ? where(keyword_group_id: group_id) : where },
    foreign_key: foreign_key,
    primary_key: 'stichwort',
    class_name:  'Keyword'

  define_method("#{name}=") do |keyword|
    if keyword.is_a?(String)
      keyword =
        if group_id
          Keyword.where(keyword_group_id: group_id)
        else
          Keyword
        end.find_by!(code: keyword)
    end

    super(keyword)
  end

  define_method("#{name}_id") do
    if read_attribute(foreign_key).present?
      "#{group_id}:#{read_attribute(foreign_key)}"
    end
  end

  define_method("#{name}_id=") do |primary_key|
    if primary_key.present?
      if primary_key&.match(":")
        _, keyword = primary_key.split(':')
      else
        keyword = Keyword.find(primary_key)&.code
      end
    else
      keyword = nil
    end
    send("#{name}=", keyword)
  end
end

更新:我正在尝试使用 singleton_class,这适用于生成的方法。但不是belongs_to,可能是因为this

这是最新情况:

after_find do
  group_id = case finance_object_type
    when 'E' then 281
    when 'A' then 282
    when 'K' then 283
  end
  singleton_class.keyword_attribute :leistung_code, group_id: group_id
end

【问题讨论】:

  • 你能把keyword_attribute的代码也发一下吗?
  • 添加了keyword_attribute方法

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

你在运行时修补你的类。这不限于单个对象。这将更改您班级的所有新对象。您可以尝试仅扩展新对象,例如:

instance.define_singleton_method("#{name}_id") do
  if read_attribute(foreign_key).present?
     "#{group_id}:#{read_attribute(foreign_key)}"
   end
end

或与

instance.extend(ModuleWithNeededMethods)

如何将其与belongs_to 的定义结合起来,我目前还不能说。

但我认为您应该尝试另一种方法并查看单表继承。 finance_object_type 看起来像是 STI 的类型列。

【讨论】:

  • 像你建议的那样实现了singleton_class,除了belongs_to(就像你说的那样)之外,这都有效。如果 STI 想法适合我的情况,我会尝试
  • STI 对我有用,还有一些 STI 标志我没有在这里显示,感谢您的输入!
猜你喜欢
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
相关资源
最近更新 更多