首页 > 解决方案 > 覆盖 has_many getter

问题描述

我有以下模型:

class Metric < ApplicationRecord
  has_many key_phrases
end

我想创建一个覆盖 getter 的方法,key_phrases例如:

class Metric < ApplicationRecord
  has_many key_phrases

  def key_phrases
    # if current value is not an empty array, return, otherwise creates, something like:
    current_value = super()
    return current_value unless current_value.nil?

    get_key_phrases.each do |k|
      key_phrases.create(k)
    end
    return key_phrases
  end
end

我知道我想做什么,但是因为我缺乏关于 Ruby 和 Rails 的知识,所以我不知道如何编写代码。

标签: ruby-on-railsruby

解决方案


从技术上讲,您可以添加别名以确保其余代码不会中断。这个想法是将现有has_many方法重命名为其他方法 并将现有方法key_phrases用作普通方法。

这样您就不必更改代码库中的其他任何地方,并且只需进行最少的更改。

在此处阅读有关 alias_attribute 的更多信息

class Metric < ApplicationRecord

  alias_attribute :phrases, :key_phrases #NOTE the alias_attribute should be before `key_phrases`
  has_many key_phrases

  def key_phrases
    # your logic goes into this method
    if phrases.empty?
      # create
    else
      phrases
    end
  end 
end

但是......我个人创建了一个更有意义的完整方法并保留“has_many key_phrases”,原因是,这意味着并获取,如果您尝试以相同的方法创建记录,这有点令人困惑。

所以,我会做这样的事情

class Metric < ApplicationRecord

  has_many key_phrases

  def get_or_create_key_phrases(*params)
    if phrases.empty?
      # create
    else
      phrases
    end
  end 
end

然后更改所有调用的地方,key_phrasesget_or_create_key_phrases个人认为更明确。但不利的一面是,您必须更改代码中的更多位置。


推荐阅读