4

我在尝试建立从其他人继承的模型的关联时遇到问题。问题是在调用 save 方法之前关联的模型被保存到数据库中。

我在此页面http://techspry.com/ruby_and_rails/active-records-or-push-or-concat-method/中找到了更多信息

真的很奇怪,为什么 AR 会自动保存附加到关联的模型(使用 << 方法)?人们显然会期望必须调用 save 方法,即使父级已经存在。我们可以阻止这个调用

@user.reviews.build(good_params)

但这在关联具有层次结构的情况下会出现问题,例如:如果 Hunter has_many :animals,并且 Dog 和 Cat 继承自 Animal,我们不能这样做

@hunter.dogs.build
@hunter.cats.build 

相反,我们被困在

@hunter.animals << Cat.new
@hunter.animals << Dog.new 

如果 Cat/Dog 类没有验证,对象将自动保存到数据库中。我怎样才能防止这种行为?

4

2 回答 2

9

我发现 Rails 3 并不完全支持与 STI 的关联,通常需要 hack。阅读这篇文章http://simple10.com/rails-3-sti/的更多信息。正如其中一条评论中提到的,这个问题在 rails 4 https://github.com/rails/rails/commit/89b5b31cc4f8407f648a2447665ef23f9024e8a5 Rails sux 所以不好处理继承=((希望 Rails 4 解决了这个问题。

同时我正在使用这个丑陋的解决方法:

animal = @hunter.animals.build type: 'Dog' 

然后替换构建的对象,这一步可能是反射锻炼所必需的(检查露西的答案和评论)

hunter.animals[@hunter.animals.index(animal)] = animal.becomes(Dog)

这将在这种情况下正确运行,因为

hunter.animals[@hunter.animals.index(animal)].is_a? Dog

将返回 true,并且不会对分配进行任何数据库调用

于 2013-03-07T10:45:19.367 回答
5

根据 Gus 的回答,我实施了一个类似的解决方案:

# instantiate a dog object
dog = Dog.new(name: 'fido')

# get the attributes from the dog, add the class (per Gus's answer)
dog_attributes = dog.attributes.merge(type: 'Dog')

# build a new dog using the correct attributes, including the type
hunter.animals.build(dog_attributes)

请注意,原来的狗对象只是被扔掉了。根据您需要设置的属性数量,可能更容易做到:

hunter.animals.build(type: 'Dog', name: 'Fido')
于 2014-04-08T06:59:50.840 回答