2014-10-08 63 views
3

我正在使用Rails4和Carrierwave來上傳文件,並且我正在使用它。 我來看看這個作品的尺寸,2. Model Level ValidationRails4:如何驗證carrierwave上傳的圖片大小?

我在models \ article.rb中添加了validate :image_size_validation,但出現了NoMethodError in ArticlesController#create

如何檢查圖像大小?

我是否應該使用file_size_validator.rb(請參閱How to: Validate attachment file size)而不是上述文章中的解決方案?

任何想法?提前致謝。

\型號\ article.rb

class Article < ActiveRecord::Base 
... 
    has_many :photos, dependent: :destroy 
    validate :image_size_validation 
... 
    private 

    def image_size_validation 
     errors[:image] << "should be less than 1MB" if photos.image.size > 1.megabytes 
    end 

end 

\型號\ photo.rb

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

\控制器\ article_controller.rb

... 
    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 
... 

文章表

sqlite> .schema articles 
CREATE TABLE "articles" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "content" varchar(255),"user_id" integer, "created_at" datetime, "updated_at" datetime, "category_id" integer); 

照片表

sqlite> .schema photos 
CREATE TABLE "photos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "article_id" integer,"image" varchar(255), "created_at" datetime, "updated_at" datetime, "bin_image" blob); #prepare bin_image for saving image as binary 

development.log

Started POST "/articles" for 127.0.0.1 at 2014-10-08 19:47:05 +0900 
Processing by ArticlesController#create as HTML 
    Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxx", "article"=>{"category_id"=>"1718", "photos_attributes"=>{"0"=>{"article_id"=>"", "image"=>#<ActionDispatch::Http::UploadedFile:0x4579140 @tempfile=#<File:C:/xxx/AppData/Local/Temp/RackMultipart20141008-5252-vsv6z>, @original_filename="DSCN0721_080.JPG", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"article[photos_attributes][0][image]\"; filename=\"DSCN0721_080.JPG\"\r\nContent-Type: image/jpeg\r\n">}, "1"=>{"article_id"=>""}, "2"=>{"article_id"=>""}}, "content"=>"test"}, "commit"=>"逋サ骭イ縺吶k"} 
    [1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxx' LIMIT 1 
    [1m[36m (0.0ms)[0m [1mbegin transaction[0m 
    [1m[35m (0.0ms)[0m rollback transaction 
Completed 500 Internal Server Error in 888ms 

NoMethodError (undefined method `image' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Photo:0x472f8d8>): 
    app/models/article.rb:27:in `image_size_validation' 
    app/controllers/articles_controller.rb:20:in `create' 

編輯

我photo.rb代替article.rb添加image_size_validation,但是當我上傳出現錯誤消息超過1MB的圖像。

\型號\ photo.rb

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

validate :image_size_validation 

    private 

    def image_size_validation 
     #errors[:image] << "should be less than xMB" if image.size > 1.megabytes 
     #add the following code instead of above line 
     if image.size > 1.megabytes 
     errors.add(:base, "Image should be less than 1MB") 
     end 

    end 

end 

\日誌\ development.log

Started POST "/articles" for 127.0.0.1 at 2014-10-11 05:50:06 +0900 
Processing by ArticlesController#create as HTML 
    Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxxx", "article"=>{"categort_id"=>"1718", "photos_attributes"=>{"0"=>{"article_id"=>"", "image"=>#<ActionDispatch::Http::UploadedFile:0x43af760 @tempfile=#<File:C:/xxxx/AppData/Local/Temp/xxxxk>, @original_filename="DSCN0721.JPG", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"article[photos_attributes][0][image]\"; filename=\"DSCN0721.JPG\"\r\nContent-Type: image/jpeg\r\n">}, "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[35mSQL (3.0ms)[0m INSERT INTO "articles" ("content", "created_at", "category_id", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["content", "test"], ["created_at", Fri, 10 Oct 2014 20:50:08 UTC +00:00], ["category_id", 1718], ["updated_at", Fri, 10 Oct 2014 20:50:08 UTC +00:00], ["user_id", 1]] 
Binary data inserted for `string` type on column `image` 
    [1m[36mSQL (1.0ms)[0m [1mINSERT INTO "photos" ("article_id", "created_at", "image", "updated_at") VALUES (?, ?, ?, ?)[0m [["article_id", 78], ["created_at", Fri, 10 Oct 2014 20:50:08 UTC +00:00], ["image", "xxxx.jpg"], ["updated_at", Fri, 10 Oct 2014 20:50:08 UTC +00:00]] 
    [1m[35m (3.0ms)[0m commit transaction 
Redirected to http://localhost:3000/users/1 
Completed 302 Found in 1306ms (ActiveRecord: 7.0ms) 
+0

應驗證文件的大小在'Photo'模型,向人們展示它的工作,你總是可以做'把「林驗證」'在'image_size_validation'方法,然後看看你的控制檯看到它工作 – Richlewis 2014-10-08 13:38:16

+0

感謝您的評論,@Richlewis。我編輯了我的問題。我在照片模型中添加了「驗證」,但無法驗證。我不明白'提出'我正在驗證''。不勝感激,如果你可以更具體一點。 – SamuraiBlue 2014-10-09 13:05:17

+0

你怎麼輸出你的錯誤信息? – Richlewis 2014-10-09 13:06:59

回答

6

試試這個在您的照片型號

validate :image_size_validation, :if => "image?" 

def image_size_validation 
    if image.size > 1.megabytes 
     errors.add(:base, "Image should be less than 1MB") 
    end 
end 

刪除private聲明

+0

謝謝你的回答。雖然我編輯了代碼,但出現了以下錯誤。 'e:/xxxx/kabuhiro_app/app/models/photo.rb:20:語法錯誤,意外的$結束,期待keyword_end' – SamuraiBlue 2014-10-09 14:27:28

+0

道歉代表我的錯字,但看看錯誤,這是一個'if'語句,他們應該總是有一個結局 – Richlewis 2014-10-09 14:33:58

+0

謝謝你的回答,@ Richlewis。雖然沒有顯示上述錯誤,但我可以正常上傳大小超過1MB的圖片。沒有錯誤信息仍然顯示。 – SamuraiBlue 2014-10-10 12:58:35

4

因爲1.0版本CarrierWave具有內置的文件大小驗證功能。

安裝最新carrierwave寶石

gem 'carrierwave', '~> 1.0' 

Add方法size_range提供最小尺寸和最大尺寸

class ImageUploader < CarrierWave::Uploader::Base 
    def size_range 
    0..2.megabytes 
    end 

在模型添加validates_integrity_of到一個有效的文件大小(和內容類型)圖片。

class Image < ApplicationRecord 
    mount_uploader :image, ImageUploader 

    validates_integrity_of :image 

Rspec的規範是:

it 'is invalid with an image size greater 2mb' do 
    image = build(:image, image: File.open(File.join(Rails.root, 'spec/support/images/image-3mb.jpg'))) 
    image.valid? 
    expect(image.errors[:image]).to include("File size should be less than 2097152") 
end 

爲了使錯誤消息更友好的替代carrierwave的check_size!方法在ImageUploader

private 
def check_size!(new_file) 
    size = new_file.size 
    expected_size_range = size_range 
    if expected_size_range.is_a?(::Range) 
     if size < expected_size_range.min 
     raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ApplicationController.helpers.number_to_human_size(expected_size_range.min)) 
     elsif size > expected_size_range.max 
     raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ApplicationController.helpers.number_to_human_size(expected_size_range.max)) 
     end 
    end 
    end 
+0

謝謝。這是一個很好的答案。我只是想知道如何將錯誤消息*文件大小應該小於2097152 *轉換爲我的用戶可以理解的東西。有沒有辦法在錯誤信息中用* 0.2 MB *代替* 2097152 *? – Tintin81 2017-02-06 09:50:36

+0

非常感謝! 同時添加gem:'gem'carrierwave-i18n'' – 2017-09-03 09:00:45