diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb
index 44cc10936..1fb0c1b26 100644
--- a/app/models/budget/investment.rb
+++ b/app/models/budget/investment.rb
@@ -7,13 +7,14 @@ class Budget
include Reclassification
include Followable
include Documentable
+ documentable max_documents_allowed: 3,
+ max_file_size: 3.megabytes,
+ accepted_content_types: [ "application/pdf" ]
acts_as_votable
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
- MAX_DOCUMENTS_SIZE = 3
-
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :heading
belongs_to :group
diff --git a/app/models/concerns/documentable.rb b/app/models/concerns/documentable.rb
index 82c6c0b6e..4aeaf6eab 100644
--- a/app/models/concerns/documentable.rb
+++ b/app/models/concerns/documentable.rb
@@ -5,4 +5,16 @@ module Documentable
has_many :documents, as: :documentable, dependent: :destroy
end
+ module ClassMethods
+ attr_reader :max_documents_allowed, :max_file_size, :accepted_content_types
+
+ private
+
+ def documentable(options= {})
+ @max_documents_allowed = options[:max_documents_allowed]
+ @max_file_size = options[:max_file_size]
+ @accepted_content_types = options[:accepted_content_types]
+ end
+ end
+
end
diff --git a/app/models/document.rb b/app/models/document.rb
index 688540c09..0c48edbba 100644
--- a/app/models/document.rb
+++ b/app/models/document.rb
@@ -4,12 +4,36 @@ class Document < ActiveRecord::Base
belongs_to :user
belongs_to :documentable, polymorphic: true
- validates_attachment :attachment, presence: true,
- content_type: { content_type: "application/pdf" },
- size: { in: 0..3.megabytes }
+ validates_attachment :attachment, presence: true
+ do_not_validate_attachment_file_type :attachment
+ validate :validate_attachment_content_type
+
+ validate :validate_attachment_size
validates :title, presence: true
validates :user, presence: true
validates :documentable_id, presence: true
validates :documentable_type, presence: true
+ def validate_attachment_size
+ if attachment.file? && documentable.present? && attachment_file_size > documentable.class.max_file_size
+ errors[:attachment] = I18n.t("documents.errors.messages.in_between",
+ min: "0 Bytes",
+ max: "#{bytesToMeg(documentable.class.max_file_size)} MB")
+ end
+ end
+
+ def validate_attachment_content_type
+ if attachment.file? && documentable.present? && !documentable.class.accepted_content_types.include?(attachment_content_type)
+ errors[:attachment] = I18n.t("documents.errors.messages.content_type",
+ content_type: attachment_content_type,
+ accepted_content_types: documentable.class.accepted_content_types.join(", "))
+ end
+ end
+
+ private
+
+ def bytesToMeg bytes
+ bytes / (1024.0 * 1024.0)
+ end
+
end
diff --git a/app/models/proposal.rb b/app/models/proposal.rb
index 9e0e0e96a..e780dd21b 100644
--- a/app/models/proposal.rb
+++ b/app/models/proposal.rb
@@ -10,12 +10,14 @@ class Proposal < ActiveRecord::Base
include Graphqlable
include Followable
include Documentable
+ documentable max_documents_allowed: 3,
+ max_file_size: 3.megabytes,
+ accepted_content_types: [ "application/pdf" ]
acts_as_votable
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
- MAX_DOCUMENTS_SIZE = 3
RETIRE_OPTIONS = %w(duplicated started unfeasible done other)
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb
index 7017e22e0..3f1890ae8 100644
--- a/app/views/budgets/investments/_investment_show.html.erb
+++ b/app/views/budgets/investments/_investment_show.html.erb
@@ -4,7 +4,7 @@
<%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %>
- <% if can?(:create, @document) && investment.documents.size < Budget::Investment::MAX_DOCUMENTS_SIZE %>
+ <% if can?(:create, @document) && investment.documents.size < Budget::Investment.max_documents_allowed %>
<%= link_to t("documents.upload_document"),
new_document_path(documentable_id:investment, documentable_type: investment.class.name, from: request.url),
class: 'button hollow float-right' %>
diff --git a/app/views/budgets/investments/show.html.erb b/app/views/budgets/investments/show.html.erb
index 37565eadd..e55e88510 100644
--- a/app/views/budgets/investments/show.html.erb
+++ b/app/views/budgets/investments/show.html.erb
@@ -23,7 +23,7 @@
<%= render 'documents/documents',
documents: @investment.documents,
- max_documents_size: Budget::Investment::MAX_DOCUMENTS_SIZE %>
+ max_documents_allowed: Budget::Investment.max_documents_allowed %>
diff --git a/app/views/documents/_documents.html.erb b/app/views/documents/_documents.html.erb
index e9bac2505..3f5a47adc 100644
--- a/app/views/documents/_documents.html.erb
+++ b/app/views/documents/_documents.html.erb
@@ -1,10 +1,10 @@
<% if documents.any? %>
- <% if documents.size == max_documents_size %>
+ <% if documents.size == max_documents_allowed %>
- <%= t "documents.max_documents_size_reached" %>
+ <%= t "documents.max_documents_allowed_reached" %>
diff --git a/app/views/proposals/show.html.erb b/app/views/proposals/show.html.erb
index 62c7f4314..e75f80dd6 100644
--- a/app/views/proposals/show.html.erb
+++ b/app/views/proposals/show.html.erb
@@ -16,7 +16,7 @@
<%= back_link_to %>
- <% if can?(:create, @document) && @proposal.documents.size < Proposal::MAX_DOCUMENTS_SIZE %>
+ <% if can?(:create, @document) && @proposal.documents.size < Proposal.max_documents_allowed %>
<%= link_to t("documents.upload_document"),
new_document_path(documentable_id: @proposal, documentable_type: @proposal.class.name, from: request.url),
class: 'button hollow float-right' %>
@@ -166,6 +166,6 @@
<%= render 'documents/documents',
documents: @proposal.documents,
- max_documents_size: Proposal::MAX_DOCUMENTS_SIZE %>
+ max_documents_allowed: Proposal.max_documents_allowed %>
diff --git a/config/locales/en/documents.yml b/config/locales/en/documents.yml
index b4a614516..8a81861ca 100644
--- a/config/locales/en/documents.yml
+++ b/config/locales/en/documents.yml
@@ -3,7 +3,7 @@ en:
tab: Documents
no_documents: Don't have uploaded documents
upload_document: Upload document
- max_documents_size_reached: You have reached the maximum number of documents allowed! You have to delete one before you can upload another.
+ max_documents_allowed_reached: You have reached the maximum number of documents allowed! You have to delete one before you can upload another.
form:
attachment_label: Choose attachment file
submit_button: Upload document
@@ -24,3 +24,7 @@ en:
download_document: Download PDF
destroy_document: Destroy
link_document: Link
+ errors:
+ messages:
+ in_between: must be in between %{min} and %{max}
+ wrong_content_type: content type %{content_type} does not match any of accepted content types %{accepted_content_types}
\ No newline at end of file
diff --git a/config/locales/es/documents.yml b/config/locales/es/documents.yml
index e237dee21..3fe544cee 100644
--- a/config/locales/es/documents.yml
+++ b/config/locales/es/documents.yml
@@ -3,7 +3,7 @@ es:
tab: Documentos
no_documents: No hay documentos subidos
upload_document: Subir documento
- max_documents_size_reached: ¡Has alcanzado el número máximo de documentos permitidos! Tienes que eliminar uno antes de poder subir otro.
+ max_documents_allowed_reached: ¡Has alcanzado el número máximo de documentos permitidos! Tienes que eliminar uno antes de poder subir otro.
form:
attachment_label: Selecciona un archivo
submit_button: Subir documento
@@ -24,3 +24,7 @@ es:
download_document: Descargar PDF
destroy_document: Eliminar
link_document: Enlace
+ errors:
+ messages:
+ in_between: debe estar entre %{min} y %{max}
+ wrong_content_type: El tipo de contenido %{content_type} del archivo no coincide con ninguno de los tipos de contenido aceptados %{accepted_content_types}
\ No newline at end of file
diff --git a/spec/shared/models/document_validations.rb b/spec/shared/models/document_validations.rb
index a5cff53c5..6f85705f4 100644
--- a/spec/shared/models/document_validations.rb
+++ b/spec/shared/models/document_validations.rb
@@ -1,6 +1,8 @@
shared_examples "document validations" do |documentable_factory|
- let(:document) { build(:document, documentable_factory.to_sym) }
+ let(:document) { build(:document, documentable_factory.to_sym) }
+ let(:max_file_size) { document.documentable.class.max_file_size }
+ let(:accepted_content_types) { document.documentable.class.accepted_content_types }
it "should be valid" do
expect(document).to be_valid
@@ -18,17 +20,20 @@ shared_examples "document validations" do |documentable_factory|
expect(document).to_not be_valid
end
- it "should not be valid for attachment images" do
- document.attachment = File.new("spec/fixtures/files/logo_header.png")
+ it "should be valid for all accepted content types" do
+ accepted_content_types.each do |content_type|
+ extension = content_type.split("/").last
+ document.attachment = File.new("spec/fixtures/files/empty.#{extension}")
- expect(document).to_not be_valid
+ expect(document).to be_valid
+ end
end
- it "should not be valid for attachment 3MB" do
- document.stub(:attachment_file_size).and_return(3.1.megabytes)
+ it "should not be valid for attachments larger than documentable max_file_size definition" do
+ document.stub(:attachment_file_size).and_return(max_file_size.bytes + 1.byte)
- document.should_not be_valid
- expect(document.errors[:attachment]).to include "must be in between 0 Bytes and 3 MB"
+ expect(document).to_not be_valid
+ expect(document.errors[:attachment]).to include "must be in between 0 Bytes and #{bytesToMeg(max_file_size)} MB"
end
it "should not be valid without a user_id" do
@@ -50,3 +55,7 @@ shared_examples "document validations" do |documentable_factory|
end
end
+
+def bytesToMeg(bytes)
+ bytes / (1024.0 * 1024.0)
+end
\ No newline at end of file