Rails4:在删除图像时,检查是否没有通过载波上传的图像不起作用 [英] Rails4: To check for no image uploaded with carrierwave is not working when delete the image

查看:56
本文介绍了Rails4:在删除图像时,检查是否没有通过载波上传的图像不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要为用户选择至少一张图像(最多3张图像),然后在视图中输入 f.text_area:content 共享的_article_form.html.erb。

我在\models\article.rb中添加了自定义验证 check_for_at_least_image

仅在 create 操作中有效(显示错误消息),但在 update 操作中无效。

如何在 update 操作中不检查图像并显示错误消息。

What I want to do is for users to select at least one image (up to 3 images) and to enter f.text_area :content in \views\shared\ _article_form.html.erb.
I added a custom validation check_for_at_least_image in \models\article.rb.
It works (error message is displayed) only in create action, but it doesn't work in update action.
How can I check no image and display error message in update action.

文章有很多照片

日志与

\log / development.log

\log/development.log

新建时无图像(错误消息已按预期显示)

no image when new create (error message was displayed as I expect)

Started POST "/articles" for 127.0.0.1 at 2014-09-13 10:40:49 +0900
Processing by ArticlesController#create as HTML
  Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>""}, "1"=>{"article_id"=>""}, "2"=>{"article_id"=>""}}, "content"=>"test"}, "commit"=>"逋サ骭イ縺吶k"}
  [1m[35mUser Load (0.0ms)[0m  SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxx' LIMIT 1
  [1m[36m (0.0ms)[0m  [1mbegin transaction[0m
  [1m[35m (0.0ms)[0m  rollback transaction
  [1m[36mCategory Load (1.0ms)[0m  [1mSELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT 1[0m  [["id", 1379]]
  Rendered shared/_error_messages.html.erb (1.0ms)
  Rendered shared/_article_form.html.erb (8.0ms)
  Rendered articles/new.html.erb within layouts/application (10.0ms)
  Rendered layouts/_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 63ms (Views: 51.0ms | ActiveRecord: 1.0ms)

删除全部(三张)图像(未显示错误消息)

Started PATCH "/articles/40" for 127.0.0.1 at 2014-09-13 11:10:00 +0900
Processing by ArticlesController#update as HTML
  Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"132"}, "1"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"133"}, "2"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"134"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"40"}
  [1m[35mUser Load (0.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" = 40 ORDER BY created_at DESC LIMIT 1[0m  [["user_id", 1]]
  [1m[35mArticle Load (1.0ms)[0m  SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? ORDER BY created_at DESC LIMIT 1  [["id", "40"]]
  [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 (132, 133, 134)  [["article_id", 40]]
  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "photos" WHERE "photos"."article_id" = ?[0m  [["article_id", 40]]
  [1m[35mSQL (1.0ms)[0m  DELETE FROM "photos" WHERE "photos"."id" = ?  [["id", 132]]
  [1m[36mSQL (0.0ms)[0m  [1mDELETE FROM "photos" WHERE "photos"."id" = ?[0m  [["id", 133]]
  [1m[35mSQL (0.0ms)[0m  DELETE FROM "photos" WHERE "photos"."id" = ?  [["id", 134]]
  [1m[36m (4.0ms)[0m  [1mcommit transaction[0m
Redirected to http://localhost:3000/users/1
Completed 302 Found in 26ms (ActiveRecord: 7.0ms)

照片表

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);

\models\article.rb

\models\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

\models\photo.rb

\models\photo.rb

class Photo < ActiveRecord::Base
    belongs_to :article
   mount_uploader :image, ImageUploader
end

\view\articles\edit.html.erb

\view\articles\edit.html.erb

<div class="row">
  <div class="span8">
        <%= render 'shared/article_form' %>
  </div>
</div>

\view\shared\ _article_form.html.erb

\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 %>

\controllers\articles_controller.rb

\controllers\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


推荐答案

只看了你的问题, 认为可能是您的验证正在对子对象进行销毁调用之前运行 ,并进行了一些搜索,发现 此帖子 ,看来我对运行验证是正确的毁灭之前只是要发布与您的问题相关的指针

Just looked at your question and was thinking that may be your validations are running before the destory call on child objects and searched around a bit and found this post, looks like i was right about validations being run before destory. Just going to post pointer related to your question


这里的问题是,在父对象验证之后,accepts_nested_attributes_for调用销毁了子对象。因此,用户可以删除图像。当然,稍后,当用户尝试编辑文章时,他/她会得到一个错误-选择至少一张图像。。

The problem here is that accepts_nested_attributes_for call destroy for child objects AFTER validation of the parent object. So the user is able to delete an image. Of course, later, when the user will try to edit an article, he/she will get an error – "Select at least one image.".

修复:

accepts_nested_attributes_for :photos, reject_if: proc { |attributes| attributes['image'].blank? } , allow_destroy: true  #as discussed in your other question you have to use proc to solve your update problem

validate :check_for_at_least_image

def check_for_at_least_image
  errors.add(:image, "select...") if photos.reject(&:marked_for_destruction?).size <= 0
end

这篇关于Rails4:在删除图像时,检查是否没有通过载波上传的图像不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆