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