嵌入对象的NoMethodError(未定义方法)

时间:2017-04-11 13:57:17

标签: ruby-on-rails ruby mongodb mongoid

我试图保存一个嵌入另一个的Mongo :: Document。我的课程:

class Block 
  include Mongoid::Document    
  field :name, type: String
  field :text, type: String
  embeds_many :replies         
end

其他课程:

class Reply
    include Mongoid::Document    
    field :content_type, type: String
    field :title, type: String
    field :payload, type: String
    embedded_in :block
end

在控制器中创建方法:

def create
        @block = Block.where(:name => block_params[:name])        
        @quick_reply = Reply.new(title: params[:block][:quick_replies][:title], payload: params[:block][:quick_replies][:payload] )
        @block.replies.push(@quick_reply)          
        @block.name = params[:block][:name]
        @block.text = params[:block][:text]      
        if (@block.save)
            respond_to do |format|
                format.html {render :template => "block/text/edit"}
            end            
        end        
    end

我收到此错误:

undefined method `replies' for #<Mongoid::Criteria:0x71cf550>

我想了解为什么以及如何解决这个问题。感谢。

1 个答案:

答案 0 :(得分:2)

if(a){
  `%my_operator%` <- `%do%`
}else{
  `%my_operator%` <- `%dopar%`
}

@block = Block.where(:name => block_params[:name]) 没有给你一条记录 - 而是它给你一个标准(有点像.where),它是一个懒惰的加载对象,可能包含几个甚至根本没有记录。

相反,您需要使用ActiveRecord::Relation来选择单个记录:

.find_by

如果无法找到Block,这也会引发@block = Block.find_by(name: block_params[:name]) - 这是一件好事。如果找不到块,试图创建嵌套记录将毫无意义。

使用accepts_nested_attributes_for创建嵌套记录还有一种更好的方法。如果您想在单个操作中编辑文档及其子项,这也很有用。

但您首先要查找的是将回复作为嵌套资源:

Mongoid::Errors::DocumentNotFound
# config/routes.rb
resources :blocks do
  resources :replies, only: [:new, :create]
end
class RepliesController

  before_action :set_block

  # GET /blocks/:id/replies/new
  def new
    @reply = @block.replies.new
  end

  # POST /blocks/:id/replies
  def create
    @reply = @block.replies.new(reply_params)
    if @reply.save
      redirect_to @block, success: 'Thank you for your reply'
    else
      render :new, error: 'Your reply could not be saved'
    end
  end

  private
  def set_block
    @block = Block.find(params[:id])
  end

  def reply_params
    params.require(:reply).permit(:title, :payload)
  end
end