如何解决保存!蒙古语中引用属性的方法
| 我将Rails 3.0.6与mongoID 2.0.2一起使用。最近,我遇到了保存问题!覆盖setter的方法(我正在尝试创建自己的嵌套属性)。 所以这是模型:class FeedItem
include Mongoid::Document
has_many :audio_refs
def audio_refs=(attributes_array,binding)
attributes_array.each do |attributes|
if attributes[:audio_track][:id]
self.audio_refs.build(:audio_track => AudioTrack.find(attributes[:audio_track][:id]))
elsif attributes[:audio_track][:file]
self.audio_refs.build(:audio_track => AudioTrack.new(:user_id => attributes[:audio_track][:user_id],:file => attributes[:audio_track][:file]))
end
end
if !binding
self.save!
end
end
AudioRef模型(只是在audio_tracks和feed_items之间的缓冲区)是:
class AudioRef
include Mongoid::Document
belongs_to :feed_item
belongs_to :audio_track
end
和AudioTrack:
class AudioTrack
include Mongoid::Document
has_many :audio_refs
mount_uploader :file,AudioUploader
end
因此,这是FeedItem模型无效的规范:
it \"Should create audio_track and add audio_ref\" do
@audio_track = Fabricate(:audio_track,:user_id => @author.id,:file => File.open(\"#{Rails.root}/spec/stuff/test.mp3\"))
@feed_item= FeedItem.new(
:user => @author,:message => {:body => Faker::Lorem.sentence(4)},:audio_refs => [
{:audio_track => {:id => @audio_track.id}},{:audio_track => {:user_id => @author.id,:file => File.open(\"#{Rails.root}/spec/stuff/test.mp3\")}}
]
)
@feed_item.save!
@feed_item.reload
@feed_item.audio_refs.length.should be(2)
end
如您所见,我重写audio_refs =方法的原因是,可以从现有的AudioTracks(有params [:audio_track] [:id])或上传的文件(params [:audio_track] [:file])创建FeedItem )。
问题是我运行此规范时@ feed_item.audio_refs.length == 0,即未保存audio_refs。你能帮我吗?
一些调查:
1)绑定参数默认为\“ true \”(这意味着我们处于构建模式)
解决方法
我找到了解决我问题的方法,但是我不明白为什么save方法不起作用,也没有使我的代码起作用。因此,首先让我描述一下我对该问题的调查。调用audio_refs =后,将创建一个audio_refs数组,但任何audio_ref中的feed都不是feed_item_id。可能是因为此刻feed_item尚未保存。
因此,解决方案非常简单-虚拟属性。要了解他们,请观看相应的railscasts
所以我的解决方案是通过回调“ after_save \”创建audio_refs
我对模型做了些微改动:
在FeedItem.rb中,我添加了
attr_writer :audio_tracks #feed_item operates with audio_tracks array
after_save :assign_audio #method to be called on callback
def assign_audio
if @audio_tracks
@audio_tracks.each do |attributes|
if attributes[:id]
self.audio_refs << AudioRef.new(:audio_track => AudioTrack.find(attributes[:id]))
elsif attributes[:file]
self.audio_refs << AudioRef.new(:audio_track => AudioTrack.new(:user_id => attributes[:user_id],:file => attributes[:file]))
end
end
end
end
现在的规格是:
it \"Should create audio_track and add audio_ref\" do
@audio_track = Fabricate(:audio_track,:user_id => @author.id,:file => File.open(\"#{Rails.root}/spec/stuff/test.mp3\"))
@feed_item= FeedItem.new(
:user => @author,:message => {:body => Faker::Lorem.sentence(4)},:audio_tracks => [
{:id => @audio_track.id},{:user_id => @author.id,:file => File.open(\"#{Rails.root}/spec/stuff/test.mp3\")}
]
)
@feed_item.save!
@feed_item.reload
@feed_item.audio_refs.length.should be(2)
end
而且效果很好!!!祝您编码顺利!
, 通过添加某种调试输出,检查是否真正调用了“ 6”。我的感觉是您的FeedItem.new()
呼叫未使用audio_refs=()
设置器。
这是ActiveRecord::Base#initialize
方法的源代码,取自APIdock:
# File activerecord/lib/active_record/base.rb,line 1396
def initialize(attributes = nil)
@attributes = attributes_from_column_definition
@attributes_cache = {}
@new_record = true
@readonly = false
@destroyed = false
@marked_for_destruction = false
@previously_changed = {}
@changed_attributes = {}
ensure_proper_type
populate_with_current_scope_attributes
self.attributes = attributes unless attributes.nil?
result = yield self if block_given?
_run_initialize_callbacks
result
end
我目前没有测试此环境,但是看起来它无需通过每个属性的设置器即可直接设置without11ѭ哈希。如果是这种情况,则需要手动调用设置器。
实际上,我认为您没有收到数量众多的例外(未设置12个字符)证明了您的setter没有被调用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。