如果你只是想设置一个实例变量没有在初始化任何额外的逻辑则维杰的回答是一个很好的一个。但是,您可以拥有更多的灵活性,而不仅限于attr
方法。
与所有的红宝石,你总是可以利用super
如果你保持正确的接口超级方法。 ActiveRecord::Base#initialize
只需要一个可选参数,即属性和值的hash
。如果给出一个块,它也会自动产生一个块。 https://github.com/rails/rails/blob/master/activerecord/lib/active_record/core.rb#L313
所以,如果你想设置在初始化实例变量还没有定义任何公共接入方式,您可以:
class Quote < ApplicationRecord
def initialize(attributes = nil, &block)
@my_var = attributes.delete(:my_var) if attributes
super
end
end
quote = Quote.new(my_var: 'value')
quote.instance_variable_get(:@my_var) # => "value"
您还可以执行更复杂的操作。假设你有User has_many :posts
和Post belongs_to :user
,User
有:name
和Post
有:title
。
class User < ApplicationRecord
def initialize(attributes = nil, &block)
title = attributes.delete(:first_post_title) if attributes
super
posts.build(title: "#{name}'s first post: #{title}") if title
end
end
user = User.new(first_post_title: 'Hello, world!', name: 'Matz')
user.posts.first # => #<Post:xxxxxxxxxxx title: "Matz's first post: Hello, world!">
希望这演示如何灵活的是,即使ActiveRecord
对象,有时可能回调是有点实施过于复杂和限制性在使用时如果使用得当super
可以工作得很好,甚至更好。
这两个真正有用的答案,谢谢你们。希望我能接受两个答案,但是因为我不能,所以我不得不接受M.西蒙博格斯的解释提供了很长的时间,尽管维杰是一个非常好的答案。再次感谢维杰,下次再见。 – jbk