Ruby-on-rails 非持久性 ActiveRecord 模型属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11986792/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Non persistent ActiveRecord model attributes
提问by Radu Stoenescu
I want to add to an existing model some attributes that need not be persisted, or even mapped to a database column. Is there a solution to specify such thing ?
我想向现有模型添加一些不需要持久化甚至映射到数据库列的属性。有没有解决方案来指定这样的事情?
回答by apneadiving
Of course use good old ruby's attr_accessor. In your model:
当然使用好的旧 ruby 的attr_accessor. 在您的模型中:
attr_accessor :foo, :bar
You'll be able to do:
你将能够做到:
object.foo = 'baz'
object.foo #=> 'baz'
回答by RustyToms
I was having the same problem but I needed to bootstrap the model, so the attribute had to persist after to_json was called. You need to do one extra thing for this.
我遇到了同样的问题,但我需要引导模型,因此在调用 to_json 后该属性必须保持不变。你需要为此做一件额外的事情。
As stated by apneadiving, the easiest way to start is to go to your model and add:
正如 apneadiving 所述,最简单的开始方法是转到您的模型并添加:
attr_accessor :foo
Then you can assign the attributes you want. But to make the attribute stick you need to change the attributes method. In your model file add this method:
然后你可以分配你想要的属性。但是要使属性保持不变,您需要更改属性方法。在您的模型文件中添加此方法:
def attributes
super.merge('foo' => self.foo)
end
回答by D. Visser
In case anyone is wondering how to render this to the view, use the method arguments for the render method, like so:
如果有人想知道如何将其渲染到视图,请使用渲染方法的方法参数,如下所示:
render json: {results: results}, methods: [:my_attribute]
Please know that this only works if you set the attr_accessor on your model and set the attribute in the controller action, as the selected answer explained.
请注意,这仅在您在模型上设置 attr_accessor 并在控制器操作中设置属性时才有效,如所选答案所述。
回答by estani
From Rails 5.0 onwards you could use attribute:
从 Rails 5.0 开始,您可以使用attribute:
class StoreListing < ActiveRecord::Base
attribute :non_persisted
attribute :non_persisted_complex, :integer, default: -1
end
With attributethe attribute will be created just like the ones being persisted, i.e. you can define the type and other options, use it with the createmethod, etc.
随着attribute该属性将被创建,就像被持久化的,即你可以定义类型和其他选项,与使用create方法等。
If your DB table contains a matching column it will be persistedbecause attributeis also used to affect conversion to/from SQL for existing columns.
如果您的数据库表包含匹配的列,它将被持久化,因为attribute它还用于影响现有列与 SQL 之间的转换。
see: https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
请参阅:https: //api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
回答by Michael
In my case I wanted to use a left join to populate custom attribute. It works if I don't add anything but I also want to be able to set the attribute on a new object and of course it doesn't exist. If I add attr_accessorthen it always returns nilafter a select. Here's the approach I've ended up with that works for setting on new object and retrieving from left join.
就我而言,我想使用左连接来填充自定义属性。如果我不添加任何内容,它就可以工作,但我也希望能够在新对象上设置属性,当然它不存在。如果我添加,attr_accessor那么它总是nil在select. 这是我最终采用的方法,用于设置新对象并从左连接中检索。
after_initialize do
self.foo = nil unless @attributes.key?("foo")
end
def foo
@attributes["foo"]
end
def foo=(value)
@attributes["foo"] = value
end

