减少实例方法的数量

时间:2018-10-13 18:26:42

标签: ruby

我将报告建模为一个类,并将每个列值建模为一个访问器。报告中的每个值都需要从数据库中访问。但这使类看起来很胖,RubyMine警告我类中的方法太多。

class Report

attr_accessor :name, :col1, :col2, :col3 .... :col15

def col1
 db.find({x: 1})['some_var']
end

def col2
 db.find({y: 4})['some_other_var']
end

and so forth for each attribute...

end

由于每个getter本质上是对数据库进行调用的单行,是否有更简单的方法来声明这些var,而无需使用方法?

我不想在initialize方法中进行设置,因为这些报表将被子类化,子报表将不具有所有/某些这些属性。

2 个答案:

答案 0 :(得分:1)

您可以使用元编程来动态创建attr_accessor之类的方法。

例如:

class Report
  def initialize(attributes)
    attributes.each do |attribute|
      define_singleton_method :"#{attribute}" do |hash_param, string_param|
        db.find(hash_param)[string_param]
      end
    end
  end
end

然后,您可以创建新的报表对象并按如下所示传递属性名称:

r = Report.new(["n","m"])

现在您可以在n对象上调用mr方法

r.m({val1: "val1"}, "val2")
r.n({val2: "val1"}, "val2")

答案 1 :(得分:0)

@Rahul基于对我的问题的回答,那么我在这里只能给出的建议是使用最佳的OOP设计原则。尽可能进行子类化和模块化,以及使用ruby元编程。如果需要这些方法,则必须将它们编写在某处。但是,如果只需要吸气剂,则考虑使用attr_reader,除非也需要吸气剂。

如果可以获取列名,则可以使用动态方法定义以及类似的方法,假设db是在您不清楚的地方神奇定义的,我们将假定它是与数据库的连接。

class Report

  db.column_names.each do |col|
    define_method(col.to_sym) { db.find(options={}) }
  end

end

如果您只是想让RubyMine停止对您的困扰,我假设它正在使用rubocop,并且您可以看到this post来了解如何覆盖规则。

https://www.jetbrains.com/help/ruby/2017.1/rubocop.html

https://github.com/rubocop-hq/rubocop