rails基于实例属性的值调用类方法?

时间:2016-08-16 17:15:10

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

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

我需要这样做,因为我们正在使用遗留数据库。

我得到了什么:

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,然后立即加载instance_2使用不同的finance_object_type,则生成的instance_1方法也会被覆盖。

还有其他办法吗?

keyword_attribute:

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,可能是由于How can I move .owl-pagination outside the primary owl wrapper? OwlCarousel2

这里是更新的情况:

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

1 个答案:

答案 0 :(得分:0)

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

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的类型列。