提问人:User12234327832 提问时间:10/26/2023 最后编辑:User12234327832 更新时间:10/28/2023 访问量:105
无缘无故创建的 Rails 活动记录对象
Rails Active Record Object being created for no reason
问:
我正在使用 Rails 7。我有模型 Post、Venue 和 VenuePost 模型。它们如下所示:
class Post < ApplicationRecord
has_many :venue_posts, dependent: :destroy
accepts_nested_attributes_for :venue_posts
end
class Venue < ApplicationRecord
has_many :venue_posts, dependent: :destroy
end
class VenuePost < ApplicationRecord
belongs_to :post
belongs_to :venue
end
现在,我的 Posts#new 操作如下所示:
def new
@post = Post.new
Venue.all.each do |v|
vp = @post.venue_posts.build(venue: v)
v.venue_posts << vp
end
end
问题是,即使我不调用创建操作,帖子仍会保存到数据库中,并显示在索引页面上。为什么会这样,我怎样才能防止它,同时仍然保持我现在的相同行为,即在创建新帖子时为每个场地实例化一个 VenuePost,并能够在表单中编辑它并保存它。
感谢您的阅读
编辑以供参考:
强参数:
def post_params
params.require(:post).permit(:title, :content, venue_posts_attributes: [:id, :title, :content])
end
嵌套形式:
<%= form.fields_for :venue_posts do |vpf| %>
<div>
<strong>Venue:</strong>
<%# vpf.object.venue.name %>
<%= vpf.label :title, style: "display: block" %>
<%= vpf.text_field :title %>
<%= vpf.label :content, style: "display: block" %>
<%= vpf.text_area :content %>
</div>
<% end %>
Post的创建方法:
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to post_url(@post), notice: "Post was successfully created." }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
目前新的发布方法:
def new
@post = Post.new
Venue.all.each do |v|
@post.venue_posts.new(venue: v)
end
end
答:
1赞
engineersmnky
10/26/2023
#1
我相信导致记录保存,这至少在文档中有所暗示。<<
相反,要为每个实例化一个,您应该能够进行以下调整Post
Venue
class Post < ApplicationRecord
has_many :venue_posts, dependent: :destroy
has_many :venues, through: :venue_posts
end
class Venue < ApplicationRecord
has_many :venue_posts, dependent: :destroy
has_many :posts, through: :venue_posts
end
在控制器操作中
def new
Venue.all.each {|v| v.posts.build}
end
评论
0赞
User12234327832
10/27/2023
好的,谢谢,但这仍然适用于accepts_nested_attributes_for吗(这意味着我在创建帖子时是否能够显示所有 VenuePosts 的表单)?
1赞
Alex
10/26/2023
#2
<<
方法确实保存了新记录,解释有点微妙:
通过将一条或多条记录的外键设置为关联的主键,将这些记录添加到集合中。由于扁平化其参数列表并插入每条记录,因此 push 和 concat 的行为相同。返回 self,因此可以将多个追加链接在一起。
<<
也许这让它更清楚一点:
post = Post.new #=> #<Post:0x00007fdbc7279610 id: nil>
venue_post = post.venue_posts.build(venue: Venue.first)
venue_post.post #=> #<Post:0x00007fdbc7279610 id: nil>
# when you save venue_post the new post is also saved
venue_post.save
#=>
# TRANSACTION (0.1ms) begin transaction
# Post Create (0.4ms) INSERT INTO "posts" DEFAULT VALUES RETURNING "id"
# VenuePost Create (0.1ms) INSERT INTO "venue_posts" ("venue_id", "post_id") VALUES (?, ?) RETURNING "id" [["venue_id", 1], ["post_id", 5]]
# TRANSACTION (0.1ms) commit transaction
这就是您使用时发生的情况,但对于所有venue_posts。<<
据我所知,你根本不需要部分,因为你只是在为你的表单建立新的记录,你真的想在这里使用关联:
https://guides.rubyonrails.org/association_basics.html#the-has-many-through-associationv.venue_posts << vp
has_many through:
评论
0赞
User12234327832
10/27/2023
好的,谢谢,但这仍然适用于accepts_nested_attributes_for吗(这意味着我在创建帖子时是否能够显示所有 VenuePosts 的表单)?
0赞
Alex
10/27/2023
添加关联是可选的,它只是添加快捷方式方法并为您执行连接,例如或。如果需要,您仍然可以使用与嵌套属性的关联。如果您的表单中有额外的字段用于venue_posts,您确实需要,如 .你没有在问题中包含你的表单,所以我只关注“无缘无故创建的对象”部分。through:
Venue.first.posts
Post.first.venues
has_many :venue_posts
accepts_nested_attributes_for :venue_posts
f.fields_for :venue_posts do |ff|
0赞
User12234327832
10/27/2023
好的,部分字段是我现在已经使用的,所以这很棒!稍后会尝试,谢谢!
评论
has_many :venues, through: :venue_posts
@post.venues << v
Post.new(post_params)
post_params
through