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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:52:11  来源:igfitidea点击:

Non persistent ActiveRecord model attributes

ruby-on-railsactiverecord

提问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那么它总是nilselect. 这是我最终采用的方法,用于设置新对象并从左连接中检索。

after_initialize do
  self.foo = nil unless @attributes.key?("foo")
end

def foo
  @attributes["foo"]
end

def foo=(value)
  @attributes["foo"] = value
end