嵌入式对象的 NoMethodError(未定义方法)
NoMethodError (undefined method) for embedded object
我正在尝试保存嵌入另一个的 Mongo::Document。我的 classes:
class Block
include Mongoid::Document
field :name, type: String
field :text, type: String
embeds_many :replies
end
其他class:
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>
我想了解为什么以及如何解决这个问题。谢谢
@block = Block.where(:name => block_params[:name])
.where
不会给你一条记录——而是给你一个标准(有点像 ActiveRecord::Relation
),这是一个延迟加载对象,可能包含多个甚至根本没有记录.
相反,您需要使用 .find_by
来 select 一条记录:
@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 %>
我正在尝试保存嵌入另一个的 Mongo::Document。我的 classes:
class Block
include Mongoid::Document
field :name, type: String
field :text, type: String
embeds_many :replies
end
其他class:
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>
我想了解为什么以及如何解决这个问题。谢谢
@block = Block.where(:name => block_params[:name])
.where
不会给你一条记录——而是给你一个标准(有点像 ActiveRecord::Relation
),这是一个延迟加载对象,可能包含多个甚至根本没有记录.
相反,您需要使用 .find_by
来 select 一条记录:
@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 %>