Add missing image model spec. Add shared specs to check image validations at any imageable model
This commit is contained in:
40
app/controllers/direct_uploads_controller.rb
Normal file
40
app/controllers/direct_uploads_controller.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
class DirectUploadsController < ApplicationController
|
||||
|
||||
def destroy_upload
|
||||
@document = Document.new(cached_attachment: params[:path])
|
||||
@document.set_attachment_from_cached_attachment
|
||||
@document.cached_attachment = nil
|
||||
@document.documentable = @documentable
|
||||
|
||||
if @document.attachment.destroy
|
||||
flash.now[:notice] = t "documents.actions.destroy.notice"
|
||||
else
|
||||
flash.now[:alert] = t "documents.actions.destroy.alert"
|
||||
end
|
||||
render :destroy
|
||||
end
|
||||
|
||||
def upload
|
||||
@document = Document.new(document_params.merge(user: current_user))
|
||||
@document.documentable = @documentable
|
||||
@document.valid?
|
||||
|
||||
if @document.valid?
|
||||
@document.attachment.save
|
||||
@document.set_cached_attachment_from_attachment(URI(request.url))
|
||||
else
|
||||
@document.attachment.destroy
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_attachment_container_resource
|
||||
@container_resource = params[:resource_type]
|
||||
end
|
||||
|
||||
def find_attachment_container_resource
|
||||
@uplo = params[:documentable_type].constantize.find_or_initialize_by(id: params[:documentable_id])
|
||||
end
|
||||
|
||||
end
|
||||
@@ -12,8 +12,8 @@ module DocumentablesHelper
|
||||
bytes_to_mega(documentable.class.max_file_size)
|
||||
end
|
||||
|
||||
def accepted_content_types(documentable)
|
||||
documentable.class.accepted_content_types
|
||||
def accepted_content_types(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
end
|
||||
|
||||
def accepted_content_types_extensions(documentable_class)
|
||||
@@ -22,15 +22,15 @@ module DocumentablesHelper
|
||||
.join(",")
|
||||
end
|
||||
|
||||
def documentable_humanized_accepted_content_types(documentable)
|
||||
documentable.class.accepted_content_types
|
||||
def documentable_humanized_accepted_content_types(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
.collect{ |content_type| content_type.split("/").last }
|
||||
.join(", ")
|
||||
end
|
||||
|
||||
def documentables_note(documentable)
|
||||
t "documents.form.note", max_documents_allowed: max_documents_allowed(documentable),
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(documentable),
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(documentable.class),
|
||||
max_file_size: max_file_size(documentable)
|
||||
end
|
||||
|
||||
|
||||
28
app/models/direct_upload.rb
Normal file
28
app/models/direct_upload.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class DirectUpload
|
||||
include ActiveModel::Validations
|
||||
|
||||
attr_accessor :resource, :resource_type, :resource_id, :resource_relation,
|
||||
:attachment, :cached_attachment
|
||||
|
||||
validates_presence_of :attachment, :resource_type, :resource_relation
|
||||
validate :parent_resource_attachment_validations,
|
||||
if: -> { attachment.present? && resource_type.present? && resource_relation.present? }
|
||||
|
||||
def parent_resource_attachment_validations
|
||||
# Proposal or Budget::Investment
|
||||
resource = resource_type.constantize.find_or_initialize_by(id: resource_id)
|
||||
|
||||
# Document or Image
|
||||
relation = if resource.class.reflections[resource_relation].macro == :has_one
|
||||
resource.send("build_#{resource_relation}", attachment: attachment)
|
||||
else
|
||||
resource.send(resource_relation).build(attachment: attachment)
|
||||
end
|
||||
relation.valid?
|
||||
|
||||
if relation.errors.has_key? :attachment
|
||||
errors[:attachment] = relation.errors[:attachment]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -50,9 +50,13 @@ class Document < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def documentable_class
|
||||
documentable_type.constantize if documentable_type.present?
|
||||
end
|
||||
|
||||
def validate_attachment_size
|
||||
if documentable.present? &&
|
||||
attachment_file_size > documentable.class.max_file_size
|
||||
if documentable_class.present? &&
|
||||
attachment_file_size > documentable_class.max_file_size
|
||||
errors[:attachment] = I18n.t("documents.errors.messages.in_between",
|
||||
min: "0 Bytes",
|
||||
max: "#{max_file_size(documentable)} MB")
|
||||
@@ -60,11 +64,11 @@ class Document < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def validate_attachment_content_type
|
||||
if documentable.present? &&
|
||||
!accepted_content_types(documentable).include?(attachment_content_type)
|
||||
if documentable_class &&
|
||||
!accepted_content_types(documentable_class).include?(attachment_content_type)
|
||||
errors[:attachment] = I18n.t("documents.errors.messages.wrong_content_type",
|
||||
content_type: attachment_content_type,
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(documentable))
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(documentable_class))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ class Image < ActiveRecord::Base
|
||||
attachment.reprocess!
|
||||
end
|
||||
|
||||
def imageable_class
|
||||
imageable_type.constantize if imageable_type.present?
|
||||
end
|
||||
|
||||
def validate_image_dimensions
|
||||
if attachment_of_valid_content_type?
|
||||
dimensions = Paperclip::Geometry.from_file(attachment.queued_for_write[:original].path)
|
||||
@@ -75,7 +79,7 @@ class Image < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def validate_attachment_size
|
||||
if imageable.present? &&
|
||||
if imageable_class &&
|
||||
attachment_file_size > 1.megabytes
|
||||
errors[:attachment] = I18n.t("images.errors.messages.in_between",
|
||||
min: "0 Bytes",
|
||||
@@ -84,7 +88,7 @@ class Image < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def validate_attachment_content_type
|
||||
if imageable.present? && !attachment_of_valid_content_type?
|
||||
if imageable_class && !attachment_of_valid_content_type?
|
||||
errors[:attachment] = I18n.t("images.errors.messages.wrong_content_type",
|
||||
content_type: attachment_content_type,
|
||||
accepted_content_types: imageable_humanized_accepted_content_types)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="document-form <%= documentable_class(@document.documentable) %> row">
|
||||
<div class="document-form <%= documentable_class(@document.documentable.class) %> row">
|
||||
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= back_link_to params[:from] %>
|
||||
@@ -16,7 +16,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<%= t "documents.recommendation_two_html",
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(@document.documentable) %>
|
||||
accepted_content_types: documentable_humanized_accepted_content_types(@document.documentable.class) %>
|
||||
</li>
|
||||
<li>
|
||||
<%= t "documents.recommendation_three_html",
|
||||
|
||||
@@ -819,4 +819,23 @@ LOREM_IPSUM
|
||||
association :author, factory: :user
|
||||
end
|
||||
|
||||
factory :direct_upload do
|
||||
|
||||
trait :proposal do
|
||||
resource_type "Proposal"
|
||||
end
|
||||
trait :budget_investment do
|
||||
resource_type "Budget::Investment"
|
||||
end
|
||||
|
||||
trait :documents do
|
||||
resource_relation "documents"
|
||||
attachment { File.new("spec/fixtures/files/empty.pdf") }
|
||||
end
|
||||
trait :image do
|
||||
resource_relation "image"
|
||||
attachment { File.new("spec/fixtures/files/clippy.jpg") }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
BIN
spec/fixtures/files/clippy.jpeg
vendored
Normal file
BIN
spec/fixtures/files/clippy.jpeg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
19
spec/models/direct_upload_spec.rb
Normal file
19
spec/models/direct_upload_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe DirectUpload do
|
||||
|
||||
it "should be valid for different kind of combinations when attachment is valid" do
|
||||
expect(build(:direct_upload, :proposal, :documents)).to be_valid
|
||||
expect(build(:direct_upload, :proposal, :image)).to be_valid
|
||||
expect(build(:direct_upload, :budget_investment, :documents)).to be_valid
|
||||
expect(build(:direct_upload, :budget_investment, :image)).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid for different kind of combinations when invalid atttachment content types" do
|
||||
expect(build(:direct_upload, :proposal, :documents, attachment: File.new("spec/fixtures/files/clippy.png"))).not_to be_valid
|
||||
expect(build(:direct_upload, :proposal, :image, attachment: File.new("spec/fixtures/files/empty.pdf"))).not_to be_valid
|
||||
expect(build(:direct_upload, :budget_investment, :documents, attachment: File.new("spec/fixtures/files/clippy.png"))).not_to be_valid
|
||||
expect(build(:direct_upload, :budget_investment, :image, attachment: File.new("spec/fixtures/files/empty.pdf"))).not_to be_valid
|
||||
end
|
||||
|
||||
end
|
||||
8
spec/models/image_spec.rb
Normal file
8
spec/models/image_spec.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Image do
|
||||
|
||||
it_behaves_like "image validations", "budget_investment_image"
|
||||
it_behaves_like "image validations", "proposal_image"
|
||||
|
||||
end
|
||||
@@ -296,7 +296,7 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path,
|
||||
from: send(documentable_path, arguments))
|
||||
|
||||
expect(page).to have_content "You can upload up to a maximum of #{max_file_size(documentable)} documents."
|
||||
expect(page).to have_content "You can upload #{documentable_humanized_accepted_content_types(documentable)} files."
|
||||
expect(page).to have_content "You can upload #{documentable_humanized_accepted_content_types(documentable.class)} files."
|
||||
expect(page).to have_content "You can upload files up to #{max_file_size(documentable)} MB."
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ shared_examples "document validations" do |documentable_factory|
|
||||
let!(:document) { build(:document, documentable_factory.to_sym) }
|
||||
let!(:documentable) { document.documentable }
|
||||
let!(:maxfilesize) { max_file_size(document.documentable) }
|
||||
let!(:acceptedcontenttypes) { accepted_content_types(document.documentable) }
|
||||
let!(:acceptedcontenttypes) { accepted_content_types(document.documentable.class) }
|
||||
|
||||
it "should be valid" do
|
||||
expect(document).to be_valid
|
||||
|
||||
70
spec/shared/models/image_validations.rb
Normal file
70
spec/shared/models/image_validations.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
shared_examples "image validations" do |imageable_factory|
|
||||
include ImagesHelper
|
||||
include ImageablesHelper
|
||||
|
||||
let!(:image) { build(:image, imageable_factory.to_sym) }
|
||||
let!(:imageable) { image.imageable }
|
||||
let!(:acceptedcontenttypes) { imageable_accepted_content_types }
|
||||
|
||||
it "should be valid" do
|
||||
expect(image).to be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a title" do
|
||||
image.title = nil
|
||||
|
||||
expect(image).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without an attachment" do
|
||||
image.attachment = nil
|
||||
|
||||
expect(image).to_not be_valid
|
||||
end
|
||||
|
||||
it "should be valid for all accepted content types" do
|
||||
acceptedcontenttypes.each do |content_type|
|
||||
extension = content_type.split("/").last
|
||||
image.attachment = File.new("spec/fixtures/files/clippy.#{extension}")
|
||||
|
||||
expect(image).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it "should not be valid for png and gif image content types" do
|
||||
["gif", "png"].each do |content_type|
|
||||
extension = content_type.split("/").last
|
||||
image.attachment = File.new("spec/fixtures/files/clippy.#{extension}")
|
||||
|
||||
expect(image).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it "should not be valid for attachments larger than imageable max_file_size definition" do
|
||||
image.stub(:attachment_file_size).and_return(Image::MAX_IMAGE_SIZE + 1.byte)
|
||||
|
||||
expect(image).to_not be_valid
|
||||
expect(image.errors[:attachment]).to include "must be in between 0 Bytes and 1 MB"
|
||||
end
|
||||
|
||||
it "should not be valid without a user_id" do
|
||||
image.user_id = nil
|
||||
|
||||
expect(image).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a imageable_id" do
|
||||
image.save
|
||||
image.imageable_id = nil
|
||||
|
||||
expect(image).to_not be_valid
|
||||
end
|
||||
|
||||
it "should not be valid without a imageable_type" do
|
||||
image.save
|
||||
image.imageable_type = nil
|
||||
|
||||
expect(image).to_not be_valid
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user