我有HABTM模型Client
和Book
。 Client
模型有一个bookshelf_color属性,用于指示客户是否拥有完整的图书集,部分图书或其中没有图书。一旦书架上的书籍发生变化,回调set_bookshelf_color
就会反映出这一变化。
问题是为什么我必须在下面的私人回调中使用"self."
为bookshelf_color分配添加前缀以使其正常工作(否则不会)?
class Client < ActiveRecord::Base
has_and_belongs_to_many :books, autosave: true, uniq: true,
after_add: :set_bookshelf_color, after_remove: :set_bookshelf_color
attr_accessible :id, :book_ids, :bookshelf_color
private
def set_bookshelf_color(book)
if Book.pluck(:abbr).map{|b| books.map(&:abbr).map(&:to_s).include?(b.to_s)}.all?
self.bookshelf_color = "green"
elsif Book.pluck(:abbr).map{|b| books.map(&:abbr).map(&:to_s).include?(b.to_s)}.any?
self.bookshelf_color = "yellow"
else
self.bookshelf_color = "red"
end
end
# /private
end
答案 0 :(得分:1)
请记住,您的模型属性只是幕后的实例变量 - 我们与它们交互时所做的就是调用attr_accessor
设置的getter和setter方法。当我们写instance.bookshelf_color = "red"
时,我们将带有参数bookshelf_color=
的方法"red"
发送给接收方instance
。
冷却。当我们只写bookshelf_color = "red"
时会发生什么?
在Ruby中,裸字赋值用于定义局部变量。将name = "value"
放在方法定义中将在本地范围内定义name
,而不是在name=
上调用self
方法,即使该方法存在。
class Foo
attr_accessor :bar
def set_bar(val)
bar = val
end
end
f = Foo.new
f.set_bar "baz"
f.bar # still nil
如果我指定了一个明确的接收者self.bar = val
,Ruby会知道我想发送self
方法bar=
,这会产生预期的结果。
对于self
的乐趣有一些很好的进一步阅读,以及为什么要在Joe Yates' Blog上使用它。