是否可以在 Rails 模型中自动 return 虚拟属性?

Is is possible to return virtual attributes automatically in Rails models?

鉴于:

class Foo
  has_one :bar

  def bar_name
    bar.name
  end
end

class Bar
  belongs_to :foo
end

在控制台或视图中,我可以 @foo.bar_name 获取 'baz'

我知道我可以 @foo.as_json(methods: :bar_name) 获得 {"id"=>"abc123", "bar_name"=>"baz"}

我也可以对属性进行反规范化并使其成为非虚拟的,但在这种情况下我宁愿不这样做。

是否可以自动return包含虚拟属性的模型?

#<Foo id: "abc123", bar_name: "baz">

我想这样做是因为我正在构建一个带有嵌套模型集合的大型对象,并且 as_json 调用是从我这里抽象出来的。

您可以使用 attr_accessor - 根据 Rails docs:

Defines a named attribute for this module, where the name is symbol.id2name, creating an instance variable (@name) and a corresponding access method to read it. Also creates a method called name= to set the attribute.

不是 100% 确定我理解你的担忧是否与 as_json 有关,但如果是这样,这将有效

class Foo
  has_one :bar

  def bar_name
    bar.name
  end
  def as_json(options={})
    super(options.merge!(methods: :bar_name))
  end
end

现在,对 @foo.as_json 的调用将默认包含 bar_name,就像您的明确示例所做的那样。

Ugly 不推荐,但您可以更改 foo 的检查,例如#<Foo id: "abc123", bar_name: "baz">如下

class Foo
  def inspect
    base_string = "#<#{self.class.name}:#{self.object_id} "
    fields = self.attributes.map {|k,v| "#{k}: #{v.inspect}"}
    fields << "bar_name: #{self.bar_name.inspect}"
    base_string << fields.join(", ") << ">"
  end
end

然后 "inspection notation" 会显示该信息,尽管我仍然不清楚这是否是您的意图,如果是这样,您为什么想要这个。