Rails4:为什么在删除使用carrierwave上传的图像时插入新记录?

时间:2014-09-07 02:33:09

标签: ruby-on-rails ruby-on-rails-4 carrierwave

当我删除使用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

2 个答案:

答案 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)添加空白对象并删除照片表的对象。这就是你遇到这个问题的原因。在更新照片记录之前检查您的参数将解决您的问题。