是否可以在 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" 会显示该信息,尽管我仍然不清楚这是否是您的意图,如果是这样,您为什么想要这个。
鉴于:
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" 会显示该信息,尽管我仍然不清楚这是否是您的意图,如果是这样,您为什么想要这个。