当我删除使用carrierwave上传的图像时,会同时插入新记录 如何避免插入新记录?
article
有很多photo
。
sqlite> .schema photos
CREATE TABLE "photos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "articl_id" integer, "image" varchar(255), "created_at" datetime, "updated_at" datetim);
在删除照片之前存在id 93和94。
sqlite> select * from photos;
93|27|DSCN0722_070.JPG|2014-09-07 01:59:03.320092|2014-09-07 01:59:03.320092
94|27|DSCN0725_070.JPG|2014-09-07 01:59:03.332093|2014-09-07 01:59:03.332093
当我选中复选框以删除id = 93并提交时,我删除了id = 93但是没有插入新记录id = 95,我不确定。
sqlite> select * from photos;
94|27|DSCN0725_070.JPG|2014-09-07 01:59:03.332093|2014-09-07
95|27||2014-09-07 02:01:58.634119|2014-09-07 02:01:58.634119
如果有3条记录,则有效(未插入新记录) 但是有2个记录如上,它发生了。
提前致谢。
log / development.log
.
.
Started PATCH "/articles/27" for 127.0.0.1 at 2014-09-07 11:01:58 +0900
Processing by ArticlesController#update as HTML
Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"27", "_destroy"=>"1", "id"=>"93"}, "1"=>{"article_id"=>"27", "_destroy"=>"0", "id"=>"94"}, "2"=>{"article_id"=>"27"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"27"}
[1m[35mUser Load (1.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxx' LIMIT 1
[1m[36mArticle Load (0.0ms)[0m [1mSELECT "articles".* FROM "articles" WHERE "articles"."user_id" = ? AND "articles"."id" = 27 ORDER BY created_at DESC LIMIT 1[0m [["user_id", 1]]
[1m[35mArticle Load (0.0ms)[0m SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? ORDER BY created_at DESC LIMIT 1 [["id", "27"]]
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
[1m[35mPhoto Load (1.0ms)[0m SELECT "photos".* FROM "photos" WHERE "photos"."article_id" = ? AND "photos"."id" IN (93, 94) [["article_id", 27]]
[1m[36m (0.0ms)[0m [1mSELECT COUNT(*) FROM "photos" WHERE "photos"."article_id" = ?[0m [["article_id", 27]]
#Delete id=93
[1m[35mSQL (0.0ms)[0m DELETE FROM "photos" WHERE "photos"."id" = ? [["id", 93]]
#Why new record is inserted?
[1m[36mSQL (0.0ms)[0m [1mINSERT INTO "photos" ("article_id", "created_at", "updated_at") VALUES (?, ?, ?)[0m [["article_id", 27], ["created_at", Sun, 07 Sep 2014 02:01:58 UTC +00:00], ["updated_at", Sun, 07 Sep 2014 02:01:58 UTC +00:00]]
[1m[35m (5.0ms)[0m commit transaction
Redirected to http://localhost:3000/users/1
Completed 302 Found in 48ms (ActiveRecord: 7.0ms)
\模型\ article.rb
# encoding: utf-8
class Article < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, reject_if: :all_blank, allow_destroy: true
default_scope -> { order('created_at DESC') }
validates :content, presence: true, length: { maximum: 140 }
validates :user_id, presence: true
validates :category_id, presence: true
validate :check_for_at_least_image
def build_images
(3 - self.photos.size).times {self.photos.build}
end
def check_for_at_least_image
errors.add(:image, "select...") if self.photos.size <= 0
end
end
\模型\ photo.rb
class Photo < ActiveRecord::Base
belongs_to :article
mount_uploader :image, ImageUploader
end
\视图\物品\ edit.html.erb
<div class="row">
<div class="span8">
<%= render 'shared/article_form' %>
</div>
</div>
\ view \ shared \ _article_form.html.erb
<%= form_for(@article) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.hidden_field :category_id %>
<%= f.fields_for :photos do |p| %>
<%= p.hidden_field :article_id %>
<div class="photo">
<% if p.object.image and p.object.image.file %>
<%= image_tag p.object.image.thumb.url %>
<p>article:<%= @article.id %></p>
<p>photo:<%= p.object.id %></p>
<%= p.hidden_field :image_cache if p.object.image_cache %>
<label><%= p.check_box :_destroy %>delete</label>
<% end %>
<%= p.file_field :image %>
</div>
<% end %>
<%= f.text_area :content, placeholder: "Enter content..." %>
</div>
<%= f.submit class: "btn btn-large btn-primary" %>
<% end %>
\控制器\ articles_controller.rb
class ArticlesController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: [:update, :destroy]
.
.
def new
@article = Article.new
@category = Category.find(params[:category])
@article.category_id = @category.id
3.times { @article.photos.build }
end
def create
@article = current_user.articles.build(article_params)
if @article.save
flash[:success] = "article created!"
redirect_to current_user #root_url
else
@article.build_images
render 'new'
end
end
.
.
def edit
@article = Article.find(params[:id])
@article.build_images
end
def update
@article = Article.find(params[:id])
if @article.update(article_params)
redirect_to current_user
else
render 'edit'
end
end
def destroy
@article.destroy
redirect_to root_url
end
private
def article_params
params.require(:article).permit(:content, :category_id, photos_attributes: [:id, :article_id, :image, :image_cache, :_destroy])
end
.
.
end
答案 0 :(得分:1)
如果您查看日志,则在删除图片时,其他图片的属性仍会传递给更新操作
"article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"27", "_destroy"=>"1", "id"=>"93"}, "1"=>{"article_id"=>"27", "_destroy"=>"0", "id"=>"94"}, "2"=>{"article_id"=>"27"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"27"}
<强> FIX 强>
您有两种选择:
一个。 不要在编辑操作中构建新图片: 。
您 在您的修改操作中构建新图片,然后在您提交表单时将其传递给您的更新方法 ,以便您可以在编辑操作中删除此行并解决您的问题
@article.build_images
湾 使用Proc而不是blank_all:
如果你查看你的代码
accepts_nested_attributes_for :photos, reject_if: :all_blank, allow_destroy: true
你正在使用reject_if :: all_blank而不是Proc,如果你看docs
,它说
传递:all_blank而不是Proc将创建一个proc,它将拒绝所有属性为空的记录,不包括_destroy的任何值。
,在您的情况下,仍然会为其他图片传递属性,因此它会为您创建新图像。您可以使用Proc来消除此问题:
accepts_nested_attributes_for :photos, reject_if: proc { |attributes| attributes['image'].blank? }, allow_destroy: true
答案 1 :(得分:0)
您始终在文章模型中构建图像三次。当您尝试从两个图像中删除图像时,还有一个由构建创建的照片的空白对象,当您在更新操作中提交时,此部分@article.update(article_params)
添加空白对象并删除照片表的对象。这就是你遇到这个问题的原因。在更新照片记录之前检查您的参数将解决您的问题。