From ebca521e2fc7e7cbd40579ea711e211e9ea4d16d Mon Sep 17 00:00:00 2001 From: Lars Henrik Mai Date: Sun, 27 Sep 2015 13:51:13 +0200 Subject: [PATCH] Refactor and expand Paper validations --- app/models/paper.rb | 15 +++++++++-- config/locales/de.yml | 5 +++- config/locales/en.yml | 5 ++++ lib/parseable_date_validator.rb | 12 +++++++++ test/factories/papers.rb | 14 ++++++++++ test/models/paper_test.rb | 48 ++++++++++++++++++++++++++++----- 6 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 config/locales/en.yml create mode 100644 lib/parseable_date_validator.rb create mode 100644 test/factories/papers.rb diff --git a/app/models/paper.rb b/app/models/paper.rb index 2d94c38..7c73ea1 100644 --- a/app/models/paper.rb +++ b/app/models/paper.rb @@ -1,12 +1,23 @@ require 'elasticsearch/model' require 'json' +require 'parseable_date_validator' class Paper < ActiveRecord::Base include Elasticsearch::Model include Elasticsearch::Model::Callbacks - validates_presence_of :body, :content, :name , :originator, :paper_type, :reference, :url, :published_at - validates :url, uniqueness: true + validates :name, presence: true, length: { maximum: 1000 } + validates :url, presence: true, + length: { maximum: 1000 }, + uniqueness: true, # TODO use unique index instead + url: true + validates :reference, presence: true, length: { maximum: 100 } + validates :body, presence: true, length: { maximum: 100 } + validates :content, presence: true, length: { maximum: 100_000 } + validates :originator, presence: true, length: { maximum: 300 } + validates :paper_type, presence: true, length: { maximum: 50 } + validates :published_at, presence: true, parseable_date: true + validates :resolution, length: { maximum: 30_000 } settings index: { number_of_shards: 1 } do mappings dynamic: false do diff --git a/config/locales/de.yml b/config/locales/de.yml index f538bba..d127a46 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1,2 +1,5 @@ de: - hello: 'Hallo' + errors: + messages: + unparseable_date: "ist kein gültiges Datum" + url: "ist keine gültige URL" diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..afdc4ab --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,5 @@ +en: + errors: + messages: + unparseable_date: "is not a parseable date" + url: "is not a valid URL" diff --git a/lib/parseable_date_validator.rb b/lib/parseable_date_validator.rb new file mode 100644 index 0000000..e64ecca --- /dev/null +++ b/lib/parseable_date_validator.rb @@ -0,0 +1,12 @@ +class ParseableDateValidator < ActiveModel::EachValidator + + def validate_each(record, attribute, value) + raw_value = record.read_attribute_before_type_cast(attribute) + return nil if raw_value.nil? + Date.parse(raw_value) + nil + rescue ArgumentError => e + record.errors[attribute] << (options[:message] || I18n.t("errors.messages.unparseable_date")) + end + +end diff --git a/test/factories/papers.rb b/test/factories/papers.rb new file mode 100644 index 0000000..b113481 --- /dev/null +++ b/test/factories/papers.rb @@ -0,0 +1,14 @@ +FactoryGirl.define do + factory :paper do + name Faker::Lorem.sentence + url Faker::Internet.url("example-ris.de") + reference "MyString" + body "leipzig" + published_at "2015-07-20 21:16:53" + scraped_at "2015-07-20 21:16:53" + paper_type "Verwaltungsstandpunkt" + originator Faker::Name.name + resolution Faker::Lorem.paragraph(3) + content "-------------------------------\n\n " # oh well... + end +end diff --git a/test/models/paper_test.rb b/test/models/paper_test.rb index 8354fbe..58e5002 100644 --- a/test/models/paper_test.rb +++ b/test/models/paper_test.rb @@ -3,14 +3,50 @@ require 'test_helper' class PaperTest < ActiveSupport::TestCase context "Validations" do - should validate_presence_of(:body) - should validate_presence_of(:content) should validate_presence_of(:name) - should validate_presence_of(:originator) - should validate_presence_of(:paper_type) - should validate_presence_of(:reference) + should validate_length_of(:name).is_at_most(1000) + should validate_presence_of(:url) - should validate_presence_of(:published_at) + should validate_length_of(:url).is_at_most(1000) + context "URL uniqueness" do + subject { FactoryGirl.build(:paper) } + should validate_uniqueness_of(:url) + end + should "validate url format sane" do + expected_error = "ist keine gültige URL" + paper = FactoryGirl.build(:paper, url: "wtf") + assert_not paper.valid?, "Expected paper to not be valid with invalid URL" + assert_not paper.errors[:url].empty? + assert paper.errors[:url].include?(expected_error), "Expected #{paper.errors[:url]} to include \"#{expected_error}\"" + end + + should validate_presence_of(:reference) + should validate_length_of(:reference).is_at_most(100) + + should validate_presence_of(:body) + should validate_length_of(:body).is_at_most(100) + + should validate_presence_of(:content) + should validate_length_of(:content).is_at_most(100_000) + + should validate_presence_of(:originator) + should validate_length_of(:originator).is_at_most(300) + + should validate_presence_of(:paper_type) + should validate_length_of(:paper_type).is_at_most(50) + + context "published_at" do + should validate_presence_of(:published_at) + should "validate date is parseable" do + expected_error = "ist kein gültiges Datum" + paper = FactoryGirl.build(:paper, published_at: "fubar") + assert_not paper.valid? + assert_not paper.errors[:published_at].empty? + assert paper.errors[:published_at].include?(expected_error), "Expected #{paper.errors[:published_at]} to include \"#{expected_error}\"" + end + end + + should validate_length_of(:resolution).is_at_most(30_000) end end