【问题标题】:NoMethodError (undefined method) for embedded object嵌入对象的 NoMethodError(未定义方法)
【发布时间】:2017-04-11 13:57:17
【问题描述】:

我正在尝试保存一个嵌入另一个的 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>

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

【问题讨论】:

    标签: ruby-on-rails ruby mongodb mongoid


    【解决方案1】:
    @block = Block.where(:name => block_params[:name])  
    

    .where 不会给你一条记录——而是给你一个标准(有点像ActiveRecord::Relation),它是一个延迟加载对象,可能包含多个甚至根本没有记录。

    您需要使用.find_by 来选择一条记录:

    @block = Block.find_by(name: block_params[:name])  
    

    如果找不到块,这也会引发Mongoid::Errors::DocumentNotFound - 这是一件好事。如果找不到块,尝试创建嵌套记录将毫无意义。

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

    但您可能首先要寻找的是使回复成为嵌套资源:

    # 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
    

    <%= form_for([@block, @reply || @block.replies.new]) do |f| %>
      <div class="row">
        <%= f.label :title %>
        <%= f.text_field :title %>
      </div>
      <div class="row">
        <%= f.label :payload %>
        <%= f.text_field :payload %>
      </div>
      <%= f.submit %>
    <% end %>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 2013-04-24
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多