在PHP中,我可以为模型设置一个属性(不是数据库中的列)。例如(PHP代码),
$user = new User;
$user.flag = true;
但是在rails中,当我设置数据库中不存在的任何属性时,它将抛出错误undefined method flag
。有attr_accessor
方法,但如果我需要大约十个临时属性会发生什么?
答案 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
只是一个快速setter
和getter
。
我们可以将记录初始化时的模型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