Gus*_*Gus 4 ruby-on-rails associations sti
我遇到了AR试图建立从其他人继承的模型关联的问题.问题是在调用save方法之前,相关模型正在保存到数据库中.
我在此页面中找到了更多信息http://techspry.com/ruby_and_rails/active-records-or-push-or-concat-method/
这真的很奇怪,为什么AR会自动保存附加到关联的模型(用<<方法)?很明显,即使父元素已经存在,也必须调用save方法.我们可以阻止这种呼唤
@user.reviews.build(good_params)
Run Code Online (Sandbox Code Playgroud)
但是在关联具有层次结构的上下文中这将是一个问题,例如:如果猎人has_many:动物,而狗和猫继承动物,我们不能做
@hunter.dogs.build
@hunter.cats.build
Run Code Online (Sandbox Code Playgroud)
相反,我们坚持
@hunter.animals << Cat.new
@hunter.animals << Dog.new
Run Code Online (Sandbox Code Playgroud)
如果Cat/Dog类没有验证,则对象将自动保存到数据库中.我该如何防止这种行为?
我发现Rails 3并不完全支持与STI的关联,并且通常需要黑客攻击.阅读这篇文章的更多内容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'
Run Code Online (Sandbox Code Playgroud)
然后替换构建的对象,这一步可能是反思锻炼所必需的(查看Lucy的答案和评论)
hunter.animals[@hunter.animals.index(animal)] = animal.becomes(Dog)
Run Code Online (Sandbox Code Playgroud)
这将在这种情况下正确行事,因为
hunter.animals[@hunter.animals.index(animal)].is_a? Dog
Run Code Online (Sandbox Code Playgroud)
将返回true,并且不会使用赋值进行数据库调用
基于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)
Run Code Online (Sandbox Code Playgroud)
请注意,原始的狗对象被丢弃了.根据您需要设置的属性数量,可能更容易:
hunter.animals.build(type: 'Dog', name: 'Fido')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4913 次 |
| 最近记录: |