在没有`attr_accessor`的情况下为rails模型设置非数据库属性

时间:2015-12-22 11:10:58

标签: ruby-on-rails ruby

在PHP中,我可以为模型设置一个属性(不是数据库中的列)。例如(PHP代码),

$user = new User;
$user.flag = true;

但是在rails中,当我设置数据库中不存在的任何属性时,它将抛出错误undefined method flag。有attr_accessor方法,但如果我需要大约十个临时属性会发生什么?

5 个答案:

答案 0 :(得分:10)

  

但如果我需要大约十个临时属性会发生什么?

#app/models/user.rb
class User < ActiveRecord::Base
   attr_accessor :flag, :other_attribute, :other_attribute2, :etc...
end

attr_accessor在Rails中创建"virtual" attributes - 它们不存在于数据库中,但存在于模型中。

与数据库中的属性一样,attr_accessor只会创建一组setter&amp;你班上的getter(实例)方法,你可以称之为&amp;在初始化类时进行交互:

#app/models/user.rb
class User < ActiveRecord::Base
   attr_accessor :flag

   # getter
   def flag
     @flag
   end

   # setter
   def flag=(val)
     @flag = val
   end
end

答案 1 :(得分:4)

这是预期的,因为ActiveRecord的设计工作原理。如果需要设置任意属性,则必须使用不同类型的对象。

例如,Ruby提供了一个名为OpenStruct的库,它允许您创建可以分配任意键/值的对象。您可能希望使用此类库,然后仅在/需要保存到数据库时将对象转换为相应的ActiveRecord实例。

请勿尝试对{{1}}进行建模,使其按照您刚刚描述的方式行事,因为它的设计并不是为了表现出来。这将是您当前PHP知识的cargo culting错误。

答案 2 :(得分:2)

正如小伙子们解释的那样,attr_accessor只是一个快速settergetter

我们可以将记录初始化时的模型attr_accessor设置为Ruby#Hash,例如使用ActiveRecord#After_initilize method,这样我们就可以更灵活地临时存储值(idea credit to this answer)。

类似的东西:

class User < ActiveRecord::Base

  attr_accessor :vars

  after_initialize do |user|
    self.vars = Hash.new
  end

end

现在你可以这样做:

user = User.new

#set
user.vars['flag'] = true

#get
user.vars['flag']
#> true

答案 3 :(得分:1)

attr_accessor所做的就是添加使用实例变量的getter和setter方法,例如

attr_accessor :flag

将添加以下方法:

def flag
  @flag
end

def flag=(val)
  @flag = val
end

如果需要,您可以自己编写这些方法,并让它们做一些更有趣的事情,而不仅仅是将值存储在实例var中,如果需要的话。

答案 4 :(得分:0)

如果需要临时属性,可以将它们添加到单例对象中。

instance = Model.new

class << instance
  attr_accessor :name
end