Ruby-on-rails 如何向 ActiveRecord 添加新属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18429274/
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-02 22:35:43  来源:igfitidea点击:

How to add new attribute to ActiveRecord

ruby-on-rails

提问by Ladiko

After getting all values from model, I want to add another custom attribute to the ActiveRecord class (this attribute is not a column in db) so that I could use it in view, but rails does not allow me to add one. What should I add in its model class?

从模型中获取所有值后,我想向 ActiveRecord 类添加另一个自定义属性(此属性不是 db 中的列),以便我可以在视图中使用它,但 Rails 不允许我添加一个。我应该在它的模型类中添加什么?

@test.all

@test.each do |elm|
    elm[:newatt] = 'added string'
end

error:

错误:

can't write unknown attribute `newatt'

回答by CuriousMind

try this

尝试这个

class Test < ActiveRecord::Base
  attr_accessor :newattr
end

you can access it like

你可以像这样访问它

@test = Test.new
@test.newattr = "value"

As you may notice this a property, not a hash. so it uses .syntax. however, if you need it to behave like an hash you can do this without defining a new attribute

您可能会注意到这是一个属性,而不是哈希。所以它使用.语法。但是,如果您需要它表现得像一个散列,您可以在不定义新属性的情况下执行此操作

@test.all
@test.each do |elm|
    new_elm = {}
    new_elm[:newatt] = 'added string'
end

Lastly, I am not exactly sure what you are trying to do. if this doesn't make sense to you, kindly rephrase your question so we can understand the problem better.

最后,我不确定您要做什么。如果这对您没有意义,请重新表述您的问题,以便我们更好地理解问题。

回答by sajith

If you want this only for your views and do not have any other purpose then you need not to add attr_accessor

如果您只希望这仅用于您的视图并且没有任何其他目的,那么您无需添加 attr_accessor

@test.all.select('tests.*, "added string" as newattr')

here you are adding newattr attribute for query output of ActiveRecord with a value 'added string'

在这里,您正在为 ActiveRecord 的查询输出添加 newattr 属性,其值为“已添加字符串”

回答by boulder

Define virtual attributes as instance variables:

将虚拟属性定义为实例变量:

attr_accessor :newattr

回答by Andrew Schwartz

I think you mean to assign @test to the ActiveRecord query, correct? Try:

我认为您的意思是将 @test 分配给 ActiveRecord 查询,对吗?尝试:

@test = MyARClass.select("*, NULL as newatt")
@test.each {|t| t[:newatt] = some_value}

Another related solution is to make it a singleton class method, though you'd have to jump though more hoops to make it writeable and I intuitively feel like this probably incurs more overhead

另一个相关的解决方案是使它成为一个单例类方法,尽管你必须跳过更多的箍以使其可写,我直觉地觉得这可能会导致更多的开销

@test = MyARClass.all
@test.each do t
  def t.newatt
    some_value
  end
end

Using the second method, of course you'd access it via @test.first.newatt, rather than @test.first[:newatt]. You could try redefining t.[] and t.[]=, but this is starting to get really messy.

使用第二种方法,当然你会通过@test.first.newatt 访问它,而不是@test.first[:newatt]。您可以尝试重新定义 t.[] 和 t.[]=,但这开始变得非常混乱。

回答by Chris Kerlin

If it's really just temporary it doesn't have to be in the object:

如果它真的只是暂时的,它不必在对象中:

@test.all
@test_temp = []

@test.each do |elm|
    @test_temp << {:elm => elm, :newatt => 'added string'}
end   

Otherwise, there are also good answers here.

否则,这里也有很好的答案

回答by Hugo

@test.all

@test.each do |elm|
    write_attribute(:newatt, "added string")
end

回答by Gundam Meister

If it temporary, you can try this:

如果是暂时的,你可以试试这个:

@test.all.map{ |t| t.attributes.merge({ newatt: "added string" }) }

@test.all.map{ |t| t.attributes.merge({ newatt: "added string" }) }

回答by roadtang

I met the same issue. and successfully bypass using instance_eval

我遇到了同样的问题。并使用 instance_eval 成功绕过

@test.all

@test.each do |elm|
  elm.instance_eval { @newatt = 'added string' }
end

normally it doesn't run into issue, when use attr_accessor. it appears when other DSL override "newattr=" which cause the issue. In my case, it's money-rails "monetize :newatt"

通常它不会遇到问题,当使用 attr_accessor 时。当其他 DSL 覆盖导致问题的“newattr=”时,它就会出现。就我而言,它是货币轨“货币化:newatt”

Explicitly use write_attribute doesn't work as it is the reason to raise exception in rails 4.x

显式使用 write_attribute 不起作用,因为它是在 rails 4.x 中引发异常的原因