From 0ec9124b413117b1d9ffcf971d213b7bfd40b4a0 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Fri, 25 Dec 2020 03:12:24 +0200 Subject: [PATCH 01/19] Add models, add validations --- .ruby-version | 1 + autoload.rb | 5 ++++ main.rb | 17 +++++++++++++ models/author.rb | 15 +++++++++++ models/book.rb | 16 ++++++++++++ models/order.rb | 0 models/reader.rb | 22 ++++++++++++++++ modules/validation.rb | 59 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 135 insertions(+) create mode 100644 .ruby-version create mode 100644 autoload.rb create mode 100644 main.rb create mode 100644 models/author.rb create mode 100644 models/book.rb create mode 100644 models/order.rb create mode 100644 models/reader.rb create mode 100644 modules/validation.rb diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..aedc15b --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.5.3 diff --git a/autoload.rb b/autoload.rb new file mode 100644 index 0000000..7da8b80 --- /dev/null +++ b/autoload.rb @@ -0,0 +1,5 @@ +require_relative 'modules/validation' +require_relative 'models/author' +require_relative 'models/reader' +require_relative 'models/book' +require_relative 'models/order' \ No newline at end of file diff --git a/main.rb b/main.rb new file mode 100644 index 0000000..5dc78e6 --- /dev/null +++ b/main.rb @@ -0,0 +1,17 @@ +require_relative 'autoload' + + + reader1 = Reader.new(name: "vasya", email: "@sabaka", street: "", house: -10) + reader1.errors + + author1 = Author.new(name: "Boris Akunin") + author2 = Author.new(name: "") + + book1 = Book.new(title: "BEloe solnce", author: author1) + book2 = Book.new(title: "Rikitikitavi", author: "Djek Vorobey") + + author2.errors + p author1.name + p book1.title + p book1.author + book2.errors \ No newline at end of file diff --git a/models/author.rb b/models/author.rb new file mode 100644 index 0000000..4858f15 --- /dev/null +++ b/models/author.rb @@ -0,0 +1,15 @@ +class Author + include Validator + attr_reader :name, :biography + + def initialize(name: nil, biography: {}) + @name = name + @biography = biography + @errors = {} + + validate_presence :name + validate_type String,:name + validate_emptiness :name + end + +end \ No newline at end of file diff --git a/models/book.rb b/models/book.rb new file mode 100644 index 0000000..95c2323 --- /dev/null +++ b/models/book.rb @@ -0,0 +1,16 @@ +class Book + include Validator + attr_reader :title, :author + + def initialize(title: nil, author: nil) + @title = title + @author = author + @errors = {} + + validate_presence :title, :author + validate_type String, :title + validate_type Author, :author + validate_emptiness :title + end + +end diff --git a/models/order.rb b/models/order.rb new file mode 100644 index 0000000..e69de29 diff --git a/models/reader.rb b/models/reader.rb new file mode 100644 index 0000000..910013f --- /dev/null +++ b/models/reader.rb @@ -0,0 +1,22 @@ +class Reader + include Validator + attr_reader :name, :email, :city, :street, :house + + def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) + @name = name + @email = email + @city = city + @street = street + @house = house + @errors = {} + validate_presence :name, :email, :city, :street, :house + validate_type String, :name, :email, :city, :street + validate_type Integer, :house + validate_emptiness :name, :email, :city, :street, :house + validate_positive :house + + end + +end + + diff --git a/modules/validation.rb b/modules/validation.rb new file mode 100644 index 0000000..1c7d6db --- /dev/null +++ b/modules/validation.rb @@ -0,0 +1,59 @@ +module Validator + + def validate_type(class_name, *attributes) + @errors[:type] = [] + attributes.each do |attr| + if self.send(attr).nil? + next + elsif self.send(attr).class == class_name + true + else + @errors[:type] << "Type of #{attr} must be a #{class_name}" + end + end + end + + def validate_presence(*attributes) + @errors[:presence] = [] + attributes.each do |attr| + unless self.send(attr).nil? + true + else + @errors[:presence] << "#{attr} must be present" + end + end + end + + def validate_emptiness(*attributes) + @errors[:emptiness] = [] + attributes.each do |attr| + if self.send(attr).nil? + next + elsif self.send(attr).to_s == "" + @errors[:emptiness] << "#{attr} can't be blank" + else + true + end + end + end + + def validate_positive(*attributes) + @errors[:positive] = [] + attributes.each do |attr| + if self.send(attr).nil? + next + elsif self.send(attr).is_a?(Integer) && self.send(attr) <= 0 + @errors[:positive] << "#{attr} must be positive" + else + true + end + end + end + + def errors + @errors.each do |_key, value| + p "Errors in #{self}: #{value}" if value.any? + end + end + +end \ No newline at end of file From cb51f8c08da51b6efa7b08e3b34a9aa7b47d59a4 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Sat, 26 Dec 2020 20:50:58 +0200 Subject: [PATCH 02/19] Refactor models, change validations logic --- main.rb | 21 ++++++++++++++----- models/author.rb | 21 +++++++++++++++---- models/book.rb | 22 ++++++++++++++++---- models/reader.rb | 24 ++++++++++++++++++---- modules/validation.rb | 48 +++++++++++++++---------------------------- 5 files changed, 88 insertions(+), 48 deletions(-) diff --git a/main.rb b/main.rb index 5dc78e6..3b74463 100644 --- a/main.rb +++ b/main.rb @@ -1,17 +1,28 @@ require_relative 'autoload' +require 'pry-byebug' - reader1 = Reader.new(name: "vasya", email: "@sabaka", street: "", house: -10) - reader1.errors - + reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) + author1 = Author.new(name: "Boris Akunin") author2 = Author.new(name: "") book1 = Book.new(title: "BEloe solnce", author: author1) - book2 = Book.new(title: "Rikitikitavi", author: "Djek Vorobey") + book2 = Book.new(title: "", author: "Djek Vorobey") + + p reader1.valid? + p author2.valid? + p author1.valid? + p book1.valid? + p book2.valid? + reader1.errors author2.errors + book2.errors + p author1.name p book1.title p book1.author - book2.errors \ No newline at end of file + + binding.pry + p \ No newline at end of file diff --git a/models/author.rb b/models/author.rb index 4858f15..a7dacba 100644 --- a/models/author.rb +++ b/models/author.rb @@ -5,11 +5,24 @@ class Author def initialize(name: nil, biography: {}) @name = name @biography = biography - @errors = {} - + @errors = [] + end + + def valid? + [presence?, type?, emptiness?].all? + end + + private + + def presence? validate_presence :name - validate_type String,:name - validate_emptiness :name end + def type? + validate_type String, :name + end + + def emptiness? + validate_emptiness :name + end end \ No newline at end of file diff --git a/models/book.rb b/models/book.rb index 95c2323..1004dad 100644 --- a/models/book.rb +++ b/models/book.rb @@ -5,12 +5,26 @@ class Book def initialize(title: nil, author: nil) @title = title @author = author - @errors = {} - - validate_presence :title, :author + @errors = [] + end + + def valid? + [presence?, type?, emptiness?].all? + end + + private + + def presence? + validate_presence :title, :author + end + + def type? validate_type String, :title validate_type Author, :author - validate_emptiness :title end + def emptiness? + validate_emptiness :title + end end + diff --git a/models/reader.rb b/models/reader.rb index 910013f..43895fe 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -8,15 +8,31 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @city = city @street = street @house = house - @errors = {} - validate_presence :name, :email, :city, :street, :house + @errors = [] + end + + def valid? + [presence?, type?, emptiness?, positive?].all? + end + + private + + def presence? + validate_presence :name, :email, :city, :street, :house + end + + def type? validate_type String, :name, :email, :city, :street validate_type Integer, :house + end + + def emptiness? validate_emptiness :name, :email, :city, :street, :house - validate_positive :house - end + def positive? + validate_positive :house + end end diff --git a/modules/validation.rb b/modules/validation.rb index 1c7d6db..df5e280 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -1,58 +1,44 @@ module Validator - def validate_type(class_name, *attributes) - @errors[:type] = [] + def validate_type(class_name, *attributes) attributes.each do |attr| - if self.send(attr).nil? - next - elsif self.send(attr).class == class_name - true - else - @errors[:type] << "Type of #{attr} must be a #{class_name}" + if self.send(attr).class != class_name + @errors << "Type of #{attr} must be a #{class_name}" end end + + @errors.any? ? false : true end def validate_presence(*attributes) - @errors[:presence] = [] attributes.each do |attr| - unless self.send(attr).nil? - true - else - @errors[:presence] << "#{attr} must be present" - end + @errors << "#{attr} must be present" if self.send(attr).nil? end + + @errors.any? ? false : true end def validate_emptiness(*attributes) - @errors[:emptiness] = [] attributes.each do |attr| - if self.send(attr).nil? - next - elsif self.send(attr).to_s == "" - @errors[:emptiness] << "#{attr} can't be blank" - else - true - end + @errors << "#{attr} can't be blank" if self.send(attr) == "" end + + @errors.any? ? false : true end def validate_positive(*attributes) - @errors[:positive] = [] attributes.each do |attr| - if self.send(attr).nil? - next - elsif self.send(attr).is_a?(Integer) && self.send(attr) <= 0 - @errors[:positive] << "#{attr} must be positive" - else - true + if self.send(attr).is_a?(Integer) && self.send(attr) <= 0 + @errors << "#{attr} must be positive" end end + + @errors.any? ? false : true end def errors - @errors.each do |_key, value| - p "Errors in #{self}: #{value}" if value.any? + unless @errors.empty? + @errors.each { |value| p "Errors in #{self}: #{value}" } end end From d68895cdcdfde6fc92287b0dfc4297a0f639948e Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Sun, 27 Dec 2020 23:21:35 +0200 Subject: [PATCH 03/19] add gemfile, add rubocop, fix a lot of rubocop warnings --- .fasterer.yml | 21 ++++++++++++++++ .rubocop.yml | 9 +++++++ Gemfile | 9 +++++++ Gemfile.lock | 58 +++++++++++++++++++++++++++++++++++++++++++ autoload.rb | 7 +++++- main.rb | 51 +++++++++++++++++++------------------ models/author.rb | 19 ++++++++------ models/book.rb | 20 ++++++++------- models/order.rb | 31 +++++++++++++++++++++++ models/reader.rb | 25 ++++++++++--------- modules/validation.rb | 45 ++++++++++++++++----------------- 11 files changed, 218 insertions(+), 77 deletions(-) create mode 100644 .fasterer.yml create mode 100644 .rubocop.yml create mode 100644 Gemfile create mode 100644 Gemfile.lock diff --git a/.fasterer.yml b/.fasterer.yml new file mode 100644 index 0000000..5ba63b2 --- /dev/null +++ b/.fasterer.yml @@ -0,0 +1,21 @@ +speedups: + rescue_vs_respond_to: true + module_eval: true + shuffle_first_vs_sample: true + for_loop_vs_each: true + each_with_index_vs_while: false + map_flatten_vs_flat_map: true + reverse_each_vs_reverse_each: true + select_first_vs_detect: true + sort_vs_sort_by: true + fetch_with_argument_vs_block: true + keys_each_vs_each_key: true + hash_merge_bang_vs_hash_brackets: true + block_vs_symbol_to_proc: true + proc_call_vs_yield: true + gsub_vs_tr: true + select_last_vs_reverse_detect: true + getter_vs_attr_reader: true + setter_vs_attr_writer: true + +exclude_paths: diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..7a6d3e3 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,9 @@ +Style/RedundantArgument: # (new in 1.4) + Enabled: true +Style/SwapValues: # (new in 1.1) + Enabled: true +Metrics/MethodLength: + IgnoredMethods: ["initialize"] + Max: 13 +Metrics/AbcSize: + IgnoredMethods: ["initialize"] diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7563561 --- /dev/null +++ b/Gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +gem 'awesome_print' +gem 'faker' +gem 'fasterer' +gem 'pry-byebug' +gem 'rubocop', require: false diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..3ac4b0f --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,58 @@ +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.1) + awesome_print (1.8.0) + byebug (11.1.3) + coderay (1.1.3) + colorize (0.8.1) + concurrent-ruby (1.1.7) + faker (2.15.1) + i18n (>= 1.6, < 2) + fasterer (0.8.3) + colorize (~> 0.7) + ruby_parser (>= 3.14.1) + i18n (1.8.5) + concurrent-ruby (~> 1.0) + method_source (1.0.0) + parallel (1.20.1) + parser (3.0.0.0) + ast (~> 2.4.1) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.9.0) + byebug (~> 11.0) + pry (~> 0.13.0) + rainbow (3.0.0) + regexp_parser (2.0.2) + rexml (3.2.4) + rubocop (1.7.0) + parallel (~> 1.10) + parser (>= 2.7.1.5) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.2.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (1.3.0) + parser (>= 2.7.1.5) + ruby-progressbar (1.10.1) + ruby_parser (3.15.0) + sexp_processor (~> 4.9) + sexp_processor (4.15.1) + unicode-display_width (1.7.0) + +PLATFORMS + ruby + +DEPENDENCIES + awesome_print + faker + fasterer + pry-byebug + rubocop + +BUNDLED WITH + 2.0.1 diff --git a/autoload.rb b/autoload.rb index 7da8b80..b1bcd60 100644 --- a/autoload.rb +++ b/autoload.rb @@ -1,5 +1,10 @@ +# frozen_string_literal: true + +require 'date' +require 'yaml' +require 'faker' require_relative 'modules/validation' require_relative 'models/author' require_relative 'models/reader' require_relative 'models/book' -require_relative 'models/order' \ No newline at end of file +require_relative 'models/order' diff --git a/main.rb b/main.rb index 3b74463..ca25060 100644 --- a/main.rb +++ b/main.rb @@ -1,28 +1,31 @@ +# frozen_string_literal: true + require_relative 'autoload' require 'pry-byebug' +require 'awesome_print' + +reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) + +author1 = Author.new(name: "Boris Akunin") +author2 = Author.new(name: "", biography: "some bio") + +book1 = Book.new(title: "BEloe solnce", author: author1) +book2 = Book.new(title: "", author: "Djek Vorobey") + +order1 = Order.new(book: book2) + +p reader1.valid? +p author2.valid? +p author1.valid? +p book1.valid? +p book2.valid? +p order1.valid? +reader1.errors +author1.errors +author2.errors +book2.errors +order1.errors - reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) - - author1 = Author.new(name: "Boris Akunin") - author2 = Author.new(name: "") - - book1 = Book.new(title: "BEloe solnce", author: author1) - book2 = Book.new(title: "", author: "Djek Vorobey") - - p reader1.valid? - p author2.valid? - p author1.valid? - p book1.valid? - p book2.valid? - - reader1.errors - author2.errors - book2.errors - - p author1.name - p book1.title - p book1.author - - binding.pry - p \ No newline at end of file +binding.pry +p diff --git a/models/author.rb b/models/author.rb index a7dacba..f9a1ffd 100644 --- a/models/author.rb +++ b/models/author.rb @@ -1,28 +1,31 @@ +# frozen_string_literal: true + +# class Author describes an Author model class Author include Validator attr_reader :name, :biography - - def initialize(name: nil, biography: {}) + + def initialize(name: nil, biography: nil) @name = name @biography = biography @errors = [] end - + def valid? [presence?, type?, emptiness?].all? end - + private - + def presence? validate_presence :name end - + def type? validate_type String, :name end - + def emptiness? validate_emptiness :name end -end \ No newline at end of file +end diff --git a/models/book.rb b/models/book.rb index 1004dad..5961a36 100644 --- a/models/book.rb +++ b/models/book.rb @@ -1,30 +1,32 @@ +# frozen_string_literal: true + +# class Book describes a Book model class Book include Validator attr_reader :title, :author - + def initialize(title: nil, author: nil) @title = title @author = author @errors = [] end - + def valid? - [presence?, type?, emptiness?].all? + [presence?, type?, emptiness?].all? end - + private - + def presence? - validate_presence :title, :author + validate_presence :title, :author end - + def type? validate_type String, :title validate_type Author, :author end - + def emptiness? validate_emptiness :title end end - diff --git a/models/order.rb b/models/order.rb index e69de29..83bd040 100644 --- a/models/order.rb +++ b/models/order.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# class Order describes an Order model +class Order + include Validator + attr_reader :book, :reader, :date + +# strftime("%B %d, %Y") + def initialize(book: nil, reader: nil, date: Date.today) + @book = book + @reader = reader + @date = date + @errors = [] + end + + def valid? + [presence?, type?].all? + end + + private + + def presence? + validate_presence :book + end + + def type? + validate_type Book, :book + validate_type Reader, :reader + validate_type Date, :date + end +end diff --git a/models/reader.rb b/models/reader.rb index 43895fe..0168b12 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + +# class Reader describes a Reader model class Reader include Validator attr_reader :name, :email, :city, :street, :house - + def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @name = name @email = email @@ -10,29 +13,27 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @house = house @errors = [] end - + def valid? - [presence?, type?, emptiness?, positive?].all? + [presence?, type?, emptiness?, positive?].all? end - + private - + def presence? - validate_presence :name, :email, :city, :street, :house + validate_presence :name, :email, :city, :street, :house end - + def type? validate_type String, :name, :email, :city, :street validate_type Integer, :house end - + def emptiness? validate_emptiness :name, :email, :city, :street, :house end - + def positive? - validate_positive :house + validate_positive :house end end - - diff --git a/modules/validation.rb b/modules/validation.rb index df5e280..e136bf8 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -1,45 +1,44 @@ +# frozen_string_literal: true + +# Validator module - add validations to models module Validator - + def errors + @errors.empty? || @errors.each { |value| p "Errors in #{self}: #{value}" } + end + + private + def validate_type(class_name, *attributes) attributes.each do |attr| - if self.send(attr).class != class_name + if self.public_send(attr).class != class_name @errors << "Type of #{attr} must be a #{class_name}" end end - + @errors.any? ? false : true end def validate_presence(*attributes) attributes.each do |attr| - @errors << "#{attr} must be present" if self.send(attr).nil? + @errors << "#{attr} must be present" if self.public_send(attr).nil? end - + @errors.any? ? false : true - end - + end + def validate_emptiness(*attributes) attributes.each do |attr| - @errors << "#{attr} can't be blank" if self.send(attr) == "" + @errors << "#{attr} can't be blank" if self.public_send(attr) == '' end - + @errors.any? ? false : true - end - + end + def validate_positive(*attributes) attributes.each do |attr| - if self.send(attr).is_a?(Integer) && self.send(attr) <= 0 - @errors << "#{attr} must be positive" - end + @errors << "#{attr} must be positive" if self.public_send(attr).to_i <= 0 end - + @errors.any? ? false : true end - - def errors - unless @errors.empty? - @errors.each { |value| p "Errors in #{self}: #{value}" } - end - end - -end \ No newline at end of file +end From f8462b50e3383495405c05797e89940f4acb5c4e Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Wed, 13 Jan 2021 20:09:24 +0200 Subject: [PATCH 04/19] add library model and seed module --- .gitignore | 1 + .rubocop.yml | 3 ++ autoload.rb | 2 ++ main.rb | 25 ++++++++++----- models/author.rb | 5 ++- models/book.rb | 5 ++- models/library.rb | 75 +++++++++++++++++++++++++++++++++++++++++++ models/order.rb | 6 ++-- models/reader.rb | 5 ++- modules/seed.rb | 45 ++++++++++++++++++++++++++ modules/validation.rb | 28 ++++++++++------ 11 files changed, 170 insertions(+), 30 deletions(-) create mode 100644 .gitignore create mode 100644 models/library.rb create mode 100644 modules/seed.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6bd197e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ + db.yml diff --git a/.rubocop.yml b/.rubocop.yml index 7a6d3e3..c711df4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,6 @@ +AllCops: + NewCops: enable + Style/RedundantArgument: # (new in 1.4) Enabled: true Style/SwapValues: # (new in 1.1) diff --git a/autoload.rb b/autoload.rb index b1bcd60..b5c589e 100644 --- a/autoload.rb +++ b/autoload.rb @@ -4,7 +4,9 @@ require 'yaml' require 'faker' require_relative 'modules/validation' +require_relative 'modules/seed' require_relative 'models/author' require_relative 'models/reader' require_relative 'models/book' require_relative 'models/order' +require_relative 'models/library' diff --git a/main.rb b/main.rb index ca25060..68c926c 100644 --- a/main.rb +++ b/main.rb @@ -5,14 +5,14 @@ require 'awesome_print' reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) - +reader2 = Reader.new(name: 'Mark', email: "markus@gmail.com", city: 'London', street: 'Bayker', house: 21) author1 = Author.new(name: "Boris Akunin") author2 = Author.new(name: "", biography: "some bio") - book1 = Book.new(title: "BEloe solnce", author: author1) book2 = Book.new(title: "", author: "Djek Vorobey") +order1 = Order.new(book: book2, reader: reader1) +order2 = Order.new(book: book1, reader: reader2) -order1 = Order.new(book: book2) p reader1.valid? p author2.valid? @@ -21,11 +21,20 @@ p book2.valid? p order1.valid? -reader1.errors -author1.errors -author2.errors -book2.errors -order1.errors +lib = Library.new +lib.add(reader1) +lib.add(reader2) +lib.add(author1) +lib.add(author2) +lib.add(book1) +lib.add(book2) +lib.add(order1) +lib.add(order2) +lib.add(author1) + +lib1 = Library.new +lib1.generate_data +lib1.store_to_file binding.pry p diff --git a/models/author.rb b/models/author.rb index f9a1ffd..2aca115 100644 --- a/models/author.rb +++ b/models/author.rb @@ -3,16 +3,15 @@ # class Author describes an Author model class Author include Validator - attr_reader :name, :biography + attr_reader :name, :biography, :errors def initialize(name: nil, biography: nil) @name = name @biography = biography - @errors = [] end def valid? - [presence?, type?, emptiness?].all? + presence? && type? && emptiness? end private diff --git a/models/book.rb b/models/book.rb index 5961a36..52656bd 100644 --- a/models/book.rb +++ b/models/book.rb @@ -3,16 +3,15 @@ # class Book describes a Book model class Book include Validator - attr_reader :title, :author + attr_reader :title, :author, :errors def initialize(title: nil, author: nil) @title = title @author = author - @errors = [] end def valid? - [presence?, type?, emptiness?].all? + presence? && type? && emptiness? && @author.valid? end private diff --git a/models/library.rb b/models/library.rb new file mode 100644 index 0000000..35eae96 --- /dev/null +++ b/models/library.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +# class Reader describes a Reader model +class Library + include Seed + + DATA_FILE = File.expand_path('../db.yml', __dir__) + CLASSES = [Integer, String, Date, Author, Book, Library, Order, Reader].freeze + + attr_reader :authors, :books, :readers, :orders + + def initialize + @authors = [] + @books = [] + @readers = [] + @orders = [] + + load_from_file! + end + + def uniq?(entity) + instance_variables.map do |var| + return false if instance_variable_get(var).include?(entity) + end + true + end + + def author_uniq?(entity) + @authors.none? { |author| author.name == entity.name } + end + + def book_uniq?(entity) + @books.none? { |book| book.title == entity.title } + end + + def reader_uniq?(entity) + @readers.none? { |reader| reader.name == entity.name } + end + + def order_uniq?(entity) + @orders.none? do |order| + order.reader.name == entity.reader.name && + order.book.title == entity.book.title && + order.date == entity.date + end + end + + def can_add?(entity) + entity.valid? && uniq?(entity) + end + + def add(entity) + return unless can_add?(entity) + + if entity.is_a?(Author) && author_uniq?(entity) then @authors << entity + elsif entity.is_a?(Book) && book_uniq?(entity) then @books << entity + elsif entity.is_a?(Reader) && reader_uniq?(entity) then @readers << entity + elsif entity.is_a?(Order) && order_uniq?(entity) then @orders << entity + end + end + + def load_from_file! + data = YAML.safe_load(File.read(DATA_FILE), CLASSES, [], true) if File.exist?(DATA_FILE) + + return unless data + + data.instance_variables.each do |var| + data.instance_variable_get(var).map { |entity| add(entity) } + end + end + + def store_to_file + File.open(DATA_FILE, 'w') { |file| file.write(to_yaml) } + end +end diff --git a/models/order.rb b/models/order.rb index 83bd040..89c0eea 100644 --- a/models/order.rb +++ b/models/order.rb @@ -3,18 +3,16 @@ # class Order describes an Order model class Order include Validator - attr_reader :book, :reader, :date + attr_reader :book, :reader, :date, :errors -# strftime("%B %d, %Y") def initialize(book: nil, reader: nil, date: Date.today) @book = book @reader = reader @date = date - @errors = [] end def valid? - [presence?, type?].all? + presence? && type? && @book.valid? && @reader.valid? end private diff --git a/models/reader.rb b/models/reader.rb index 0168b12..3a9d39e 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -3,7 +3,7 @@ # class Reader describes a Reader model class Reader include Validator - attr_reader :name, :email, :city, :street, :house + attr_reader :name, :email, :city, :street, :house, :errors def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @name = name @@ -11,11 +11,10 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @city = city @street = street @house = house - @errors = [] end def valid? - [presence?, type?, emptiness?, positive?].all? + presence? && type? && emptiness? && positive? end private diff --git a/modules/seed.rb b/modules/seed.rb new file mode 100644 index 0000000..9f49083 --- /dev/null +++ b/modules/seed.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'faker' + +# module Seed generate fake data +module Seed + def generate_data + seed_authors + seed_books + seed_readers + seed_orders + end + + def seed_authors + 10.times do + add(Author.new(name: Faker::Book.unique.author, + biography: Faker::Lorem.sentence(word_count: 10))) + end + end + + def seed_books + 50.times do + add(Book.new(title: Faker::Book.unique.title, + author: authors.sample)) + end + end + + def seed_readers + 20.times do + add(Reader.new(name: Faker::Name.unique.name, + email: Faker::Internet.unique.email, + city: Faker::Address.city, + street: Faker::Address.street_name, + house: Faker::Address.building_number.to_i)) + end + end + + def seed_orders + 100.times do + add(Order.new(book: books.sample, + reader: readers.sample, + date: Date.today - rand(0..30))) + end + end +end diff --git a/modules/validation.rb b/modules/validation.rb index e136bf8..59e9205 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -2,7 +2,7 @@ # Validator module - add validations to models module Validator - def errors + def show_errors @errors.empty? || @errors.each { |value| p "Errors in #{self}: #{value}" } end @@ -10,35 +10,45 @@ def errors def validate_type(class_name, *attributes) attributes.each do |attr| - if self.public_send(attr).class != class_name + if public_send(attr).class != class_name + @errors ||= [] @errors << "Type of #{attr} must be a #{class_name}" end end - @errors.any? ? false : true + @errors&.any? ? false : true end def validate_presence(*attributes) attributes.each do |attr| - @errors << "#{attr} must be present" if self.public_send(attr).nil? + if public_send(attr).nil? + @errors ||= [] + @errors << "#{attr} must be present" + end end - @errors.any? ? false : true + @errors&.any? ? false : true end def validate_emptiness(*attributes) attributes.each do |attr| - @errors << "#{attr} can't be blank" if self.public_send(attr) == '' + if public_send(attr) == '' + @errors ||= [] + @errors << "#{attr} can't be blank" + end end - @errors.any? ? false : true + @errors&.any? ? false : true end def validate_positive(*attributes) attributes.each do |attr| - @errors << "#{attr} must be positive" if self.public_send(attr).to_i <= 0 + if public_send(attr).to_i <= 0 + @errors ||= [] + @errors << "#{attr} must be positive" + end end - @errors.any? ? false : true + @errors&.any? ? false : true end end From f6b1a08c29919c7e73f6f7b62f9adaf368b62afa Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Mon, 18 Jan 2021 01:49:20 +0200 Subject: [PATCH 05/19] Change some models validation logic --- .gitignore | 1 + main.rb | 8 +++++--- models/author.rb | 29 ++++++++++++++++++++++++---- models/book.rb | 33 +++++++++++++++++++++++++------ models/library.rb | 6 +++--- models/order.rb | 33 +++++++++++++++++++++++++------ models/reader.rb | 37 +++++++++++++++++++++++++++-------- modules/validation.rb | 45 ++++++++++++++----------------------------- 8 files changed, 131 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index 6bd197e..59ace56 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ db.yml +*.kate-swp diff --git a/main.rb b/main.rb index 68c926c..7de5878 100644 --- a/main.rb +++ b/main.rb @@ -7,7 +7,7 @@ reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) reader2 = Reader.new(name: 'Mark', email: "markus@gmail.com", city: 'London', street: 'Bayker', house: 21) author1 = Author.new(name: "Boris Akunin") -author2 = Author.new(name: "", biography: "some bio") +author2 = Author.new(name: '', biography: "some bio") book1 = Book.new(title: "BEloe solnce", author: author1) book2 = Book.new(title: "", author: "Djek Vorobey") order1 = Order.new(book: book2, reader: reader1) @@ -15,6 +15,7 @@ p reader1.valid? +p reader2.valid? p author2.valid? p author1.valid? p book1.valid? @@ -30,11 +31,12 @@ lib.add(book2) lib.add(order1) lib.add(order2) -lib.add(author1) +lib.store_to_file + lib1 = Library.new lib1.generate_data -lib1.store_to_file +#lib1.store_to_file binding.pry p diff --git a/models/author.rb b/models/author.rb index 2aca115..3a304f2 100644 --- a/models/author.rb +++ b/models/author.rb @@ -3,6 +3,21 @@ # class Author describes an Author model class Author include Validator + @@class_errors = [] + + class << self + def class_errors + @@class_errors + end + + def show_errors + puts "Author class contain not valid items:" + @@class_errors.each do |item| + puts "Item with id #{item.object_id} has errors: #{item.errors}" + end + end + end + attr_reader :name, :biography, :errors def initialize(name: nil, biography: nil) @@ -11,20 +26,26 @@ def initialize(name: nil, biography: nil) end def valid? - presence? && type? && emptiness? + if presence.empty? && type.empty? && emptiness.empty? + return true + else + @@class_errors << self + @errors = [presence, type, emptiness].flatten.compact + return false + end end private - def presence? + def presence validate_presence :name end - def type? + def type validate_type String, :name end - def emptiness? + def emptiness validate_emptiness :name end end diff --git a/models/book.rb b/models/book.rb index 52656bd..8ea9876 100644 --- a/models/book.rb +++ b/models/book.rb @@ -3,6 +3,21 @@ # class Book describes a Book model class Book include Validator + @@class_errors = [] + + class << self + def class_errors + @@class_errors + end + + def show_errors + puts "Book class contain not valid items:" + @@class_errors.each do |item| + puts "Item with id #{item.object_id} has errors: #{item.errors}" + end + end + end + attr_reader :title, :author, :errors def initialize(title: nil, author: nil) @@ -11,21 +26,27 @@ def initialize(title: nil, author: nil) end def valid? - presence? && type? && emptiness? && @author.valid? + if presence.empty? && type.empty? && emptiness.empty? && @author.valid? + return true + else + @@class_errors << self + @errors = [presence, type, emptiness].flatten.compact + return false + end end private - def presence? + def presence validate_presence :title, :author end - def type? - validate_type String, :title - validate_type Author, :author + def type + [validate_type(String, :title), + validate_type(Author, :author)].flatten end - def emptiness? + def emptiness validate_emptiness :title end end diff --git a/models/library.rb b/models/library.rb index 35eae96..f5052f6 100644 --- a/models/library.rb +++ b/models/library.rb @@ -19,10 +19,10 @@ def initialize end def uniq?(entity) - instance_variables.map do |var| - return false if instance_variable_get(var).include?(entity) + check = instance_variables.detect do |var| + instance_variable_get(var).include?(entity) end - true + check.nil? end def author_uniq?(entity) diff --git a/models/order.rb b/models/order.rb index 89c0eea..a028df8 100644 --- a/models/order.rb +++ b/models/order.rb @@ -3,6 +3,21 @@ # class Order describes an Order model class Order include Validator + @@class_errors = [] + + class << self + def class_errors + @@class_errors + end + + def show_errors + puts "Order class contain not valid items:" + @@class_errors.each do |item| + puts "Item with id #{item.object_id} has errors: #{item.errors}" + end + end + end + attr_reader :book, :reader, :date, :errors def initialize(book: nil, reader: nil, date: Date.today) @@ -12,18 +27,24 @@ def initialize(book: nil, reader: nil, date: Date.today) end def valid? - presence? && type? && @book.valid? && @reader.valid? + if presence.empty? && type.empty? && @book.valid? && @reader.valid? + return true + else + @@class_errors << self + @errors = [presence, type].flatten.compact + return false + end end private - def presence? + def presence validate_presence :book end - def type? - validate_type Book, :book - validate_type Reader, :reader - validate_type Date, :date + def type + [validate_type(Book, :book), + validate_type(Reader, :reader), + validate_type(Date, :date)].flatten end end diff --git a/models/reader.rb b/models/reader.rb index 3a9d39e..88ddbb5 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -3,6 +3,21 @@ # class Reader describes a Reader model class Reader include Validator + @@class_errors = [] + + class << self + def class_errors + @@class_errors + end + + def show_errors + puts "Reader class contain not valid items:" + @@class_errors.each do |item| + puts "Item with id #{item.object_id} has errors: #{item.errors}" + end + end + end + attr_reader :name, :email, :city, :street, :house, :errors def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @@ -14,25 +29,31 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) end def valid? - presence? && type? && emptiness? && positive? + if presence.empty? && type.empty? && emptiness.empty? && positive.empty? + return true + else + @@class_errors << self + @errors = [presence, type].flatten.compact + return false + end end - private + #private - def presence? + def presence validate_presence :name, :email, :city, :street, :house end - def type? - validate_type String, :name, :email, :city, :street - validate_type Integer, :house + def type + [validate_type(String, :name, :email, :city, :street), + validate_type(Integer, :house)].flatten end - def emptiness? + def emptiness validate_emptiness :name, :email, :city, :street, :house end - def positive? + def positive validate_positive :house end end diff --git a/modules/validation.rb b/modules/validation.rb index 59e9205..37667b5 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -2,53 +2,36 @@ # Validator module - add validations to models module Validator - def show_errors - @errors.empty? || @errors.each { |value| p "Errors in #{self}: #{value}" } - end - - private - def validate_type(class_name, *attributes) - attributes.each do |attr| + errors = attributes.map do |attr| if public_send(attr).class != class_name - @errors ||= [] - @errors << "Type of #{attr} must be a #{class_name}" + "Type of #{attr} must be an instance of #{class_name}" end end - - @errors&.any? ? false : true + errors.compact end def validate_presence(*attributes) - attributes.each do |attr| - if public_send(attr).nil? - @errors ||= [] - @errors << "#{attr} must be present" - end + errors = attributes.map do |attr| + "#{attr} must be present" if public_send(attr).nil? end - - @errors&.any? ? false : true + errors.compact end def validate_emptiness(*attributes) - attributes.each do |attr| - if public_send(attr) == '' - @errors ||= [] - @errors << "#{attr} can't be blank" - end + errors = attributes.map do |attr| + "#{attr} can't be blank" if public_send(attr) == '' end - - @errors&.any? ? false : true + errors.compact end def validate_positive(*attributes) - attributes.each do |attr| - if public_send(attr).to_i <= 0 - @errors ||= [] - @errors << "#{attr} must be positive" - end + errors = attributes.map do |attr| + "#{attr} must be positive" if public_send(attr).to_i <= 0 end + errors.compact + end - @errors&.any? ? false : true + class ValidationErrors < StandardError end end From 48039d81f7b2380b137913213fd2cad684d884e5 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Mon, 18 Jan 2021 23:51:06 +0200 Subject: [PATCH 06/19] add Statistics module --- autoload.rb | 2 ++ db.yml | 34 ++++++++++++++++++++++ errorclass.rb | 2 ++ main.rb | 68 ++++++++++++++++++++++++++++++++----------- models/author.rb | 22 +++----------- models/book.rb | 22 +++----------- models/library.rb | 1 + models/order.rb | 22 +++----------- models/reader.rb | 24 ++++----------- modules/statistics.rb | 21 +++++++++++++ modules/validation.rb | 3 -- 11 files changed, 128 insertions(+), 93 deletions(-) create mode 100644 db.yml create mode 100644 errorclass.rb create mode 100644 modules/statistics.rb diff --git a/autoload.rb b/autoload.rb index b5c589e..dc30796 100644 --- a/autoload.rb +++ b/autoload.rb @@ -3,7 +3,9 @@ require 'date' require 'yaml' require 'faker' +require_relative 'errorclass' require_relative 'modules/validation' +require_relative 'modules/statistics' require_relative 'modules/seed' require_relative 'models/author' require_relative 'models/reader' diff --git a/db.yml b/db.yml new file mode 100644 index 0000000..be49f47 --- /dev/null +++ b/db.yml @@ -0,0 +1,34 @@ +--- !ruby/object:Library +authors: +- &1 !ruby/object:Author + name: Boris Akunin + biography: +books: +- &2 !ruby/object:Book + title: BEloe solnce + author: *1 +readers: +- &3 !ruby/object:Reader + name: Mark + email: markus@gmail.com + city: London + street: Bayker + house: 21 +orders: +- !ruby/object:Order + book: *2 + reader: *3 + date: 2021-01-16 +- !ruby/object:Order + book: !ruby/object:Book + title: BEloe solnce + author: !ruby/object:Author + name: Boris Akunin + biography: + reader: !ruby/object:Reader + name: Mark + email: markus@gmail.com + city: London + street: Bayker + house: 21 + date: 2021-01-18 diff --git a/errorclass.rb b/errorclass.rb new file mode 100644 index 0000000..76a6400 --- /dev/null +++ b/errorclass.rb @@ -0,0 +1,2 @@ +class ValidationError < StandardError +end diff --git a/main.rb b/main.rb index 7de5878..7347cce 100644 --- a/main.rb +++ b/main.rb @@ -13,30 +13,64 @@ order1 = Order.new(book: book2, reader: reader1) order2 = Order.new(book: book1, reader: reader2) +lib = Library.new -p reader1.valid? -p reader2.valid? -p author2.valid? -p author1.valid? -p book1.valid? -p book2.valid? -p order1.valid? +begin + lib.add(reader1) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(reader2) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(author1) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(author2) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(book1) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(book2) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(order1) +rescue ValidationError => e + puts e.message +end + +begin + lib.add(order2) +rescue ValidationError => e + puts e.message +end -lib = Library.new -lib.add(reader1) -lib.add(reader2) -lib.add(author1) -lib.add(author2) -lib.add(book1) -lib.add(book2) -lib.add(order1) -lib.add(order2) lib.store_to_file lib1 = Library.new lib1.generate_data -#lib1.store_to_file +puts lib1.top_readers +puts lib1.top_books +puts lib1.number_readers_of_top_books binding.pry p diff --git a/models/author.rb b/models/author.rb index 3a304f2..37a4dc8 100644 --- a/models/author.rb +++ b/models/author.rb @@ -3,20 +3,6 @@ # class Author describes an Author model class Author include Validator - @@class_errors = [] - - class << self - def class_errors - @@class_errors - end - - def show_errors - puts "Author class contain not valid items:" - @@class_errors.each do |item| - puts "Item with id #{item.object_id} has errors: #{item.errors}" - end - end - end attr_reader :name, :biography, :errors @@ -26,12 +12,12 @@ def initialize(name: nil, biography: nil) end def valid? - if presence.empty? && type.empty? && emptiness.empty? + errors = [presence, type, emptiness].flatten + if errors.empty? return true else - @@class_errors << self - @errors = [presence, type, emptiness].flatten.compact - return false + msg = "Object with id #{self.object_id} errors: " + errors.join(', ') + raise ValidationError, msg end end diff --git a/models/book.rb b/models/book.rb index 8ea9876..5764999 100644 --- a/models/book.rb +++ b/models/book.rb @@ -3,20 +3,6 @@ # class Book describes a Book model class Book include Validator - @@class_errors = [] - - class << self - def class_errors - @@class_errors - end - - def show_errors - puts "Book class contain not valid items:" - @@class_errors.each do |item| - puts "Item with id #{item.object_id} has errors: #{item.errors}" - end - end - end attr_reader :title, :author, :errors @@ -26,12 +12,12 @@ def initialize(title: nil, author: nil) end def valid? - if presence.empty? && type.empty? && emptiness.empty? && @author.valid? + errors = [presence, type, emptiness].flatten + if errors.empty? && @author.valid? return true else - @@class_errors << self - @errors = [presence, type, emptiness].flatten.compact - return false + msg = "Object with id #{self.object_id} errors: " + errors.join(', ') + raise ValidationError, msg end end diff --git a/models/library.rb b/models/library.rb index f5052f6..d8708da 100644 --- a/models/library.rb +++ b/models/library.rb @@ -3,6 +3,7 @@ # class Reader describes a Reader model class Library include Seed + include Statistics DATA_FILE = File.expand_path('../db.yml', __dir__) CLASSES = [Integer, String, Date, Author, Book, Library, Order, Reader].freeze diff --git a/models/order.rb b/models/order.rb index a028df8..8c8b57a 100644 --- a/models/order.rb +++ b/models/order.rb @@ -3,20 +3,6 @@ # class Order describes an Order model class Order include Validator - @@class_errors = [] - - class << self - def class_errors - @@class_errors - end - - def show_errors - puts "Order class contain not valid items:" - @@class_errors.each do |item| - puts "Item with id #{item.object_id} has errors: #{item.errors}" - end - end - end attr_reader :book, :reader, :date, :errors @@ -27,12 +13,12 @@ def initialize(book: nil, reader: nil, date: Date.today) end def valid? - if presence.empty? && type.empty? && @book.valid? && @reader.valid? + errors = [presence, type].flatten + if errors.empty? && @book.valid? && @reader.valid? return true else - @@class_errors << self - @errors = [presence, type].flatten.compact - return false + msg = "Object with id #{self.object_id} errors: " + errors.join(', ') + raise ValidationError, msg end end diff --git a/models/reader.rb b/models/reader.rb index 88ddbb5..b068086 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -3,20 +3,6 @@ # class Reader describes a Reader model class Reader include Validator - @@class_errors = [] - - class << self - def class_errors - @@class_errors - end - - def show_errors - puts "Reader class contain not valid items:" - @@class_errors.each do |item| - puts "Item with id #{item.object_id} has errors: #{item.errors}" - end - end - end attr_reader :name, :email, :city, :street, :house, :errors @@ -29,16 +15,16 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) end def valid? - if presence.empty? && type.empty? && emptiness.empty? && positive.empty? + errors = [presence, type, emptiness, positive].flatten + if errors.empty? return true else - @@class_errors << self - @errors = [presence, type].flatten.compact - return false + msg = "Object with id #{self.object_id} errors: " + errors.join(', ') + raise ValidationError, msg end end - #private + private def presence validate_presence :name, :email, :city, :street, :house diff --git a/modules/statistics.rb b/modules/statistics.rb new file mode 100644 index 0000000..ab8590d --- /dev/null +++ b/modules/statistics.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# module Statistics do some work +module Statistics + def top_readers(quantity = 1) + top_objects(:reader, quantity).keys.map { |reader| reader.name} + end + + def top_books(quantity = 1) + top_objects(:book, quantity).keys.map { |book| book.title} + end + + def number_readers_of_top_books(quantity = 1) + top_objects(:book, quantity).values.flatten.map {|order| order.reader}.uniq.size + end + end + + def top_objects(object, quantity) + orders.group_by(&object).max_by(quantity) { |_key,value| value.size }.to_h + end + diff --git a/modules/validation.rb b/modules/validation.rb index 37667b5..737e99b 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -31,7 +31,4 @@ def validate_positive(*attributes) end errors.compact end - - class ValidationErrors < StandardError - end end From bde32ceb6a3fd71633ded9f00bdfd44891387210 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 00:00:25 +0200 Subject: [PATCH 07/19] remove errors attribute from models --- main.rb | 6 +----- models/author.rb | 2 +- models/book.rb | 2 +- models/order.rb | 2 +- models/reader.rb | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/main.rb b/main.rb index 7347cce..d388514 100644 --- a/main.rb +++ b/main.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true require_relative 'autoload' -require 'pry-byebug' -require 'awesome_print' reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) reader2 = Reader.new(name: 'Mark', email: "markus@gmail.com", city: 'London', street: 'Bayker', house: 21) @@ -65,12 +63,10 @@ lib.store_to_file - lib1 = Library.new lib1.generate_data + puts lib1.top_readers puts lib1.top_books puts lib1.number_readers_of_top_books -binding.pry -p diff --git a/models/author.rb b/models/author.rb index 37a4dc8..e67848c 100644 --- a/models/author.rb +++ b/models/author.rb @@ -4,7 +4,7 @@ class Author include Validator - attr_reader :name, :biography, :errors + attr_reader :name, :biography def initialize(name: nil, biography: nil) @name = name diff --git a/models/book.rb b/models/book.rb index 5764999..3d563d9 100644 --- a/models/book.rb +++ b/models/book.rb @@ -4,7 +4,7 @@ class Book include Validator - attr_reader :title, :author, :errors + attr_reader :title, :author def initialize(title: nil, author: nil) @title = title diff --git a/models/order.rb b/models/order.rb index 8c8b57a..d2be4e2 100644 --- a/models/order.rb +++ b/models/order.rb @@ -4,7 +4,7 @@ class Order include Validator - attr_reader :book, :reader, :date, :errors + attr_reader :book, :reader, :date def initialize(book: nil, reader: nil, date: Date.today) @book = book diff --git a/models/reader.rb b/models/reader.rb index b068086..f715548 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -4,7 +4,7 @@ class Reader include Validator - attr_reader :name, :email, :city, :street, :house, :errors + attr_reader :name, :email, :city, :street, :house def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @name = name From d84c6a0b718e2c852ca970278ad0e0f8a0705339 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 00:02:33 +0200 Subject: [PATCH 08/19] fix errors in Statistics module --- db.yml | 13 +++++++++++++ modules/statistics.rb | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/db.yml b/db.yml index be49f47..dbcdd93 100644 --- a/db.yml +++ b/db.yml @@ -32,3 +32,16 @@ orders: street: Bayker house: 21 date: 2021-01-18 +- !ruby/object:Order + book: !ruby/object:Book + title: BEloe solnce + author: !ruby/object:Author + name: Boris Akunin + biography: + reader: !ruby/object:Reader + name: Mark + email: markus@gmail.com + city: London + street: Bayker + house: 21 + date: 2021-01-19 diff --git a/modules/statistics.rb b/modules/statistics.rb index ab8590d..3c53b8b 100644 --- a/modules/statistics.rb +++ b/modules/statistics.rb @@ -12,10 +12,9 @@ def top_books(quantity = 1) def number_readers_of_top_books(quantity = 1) top_objects(:book, quantity).values.flatten.map {|order| order.reader}.uniq.size - end end def top_objects(object, quantity) orders.group_by(&object).max_by(quantity) { |_key,value| value.size }.to_h end - +end From 7742ad0d2db846e1cf25b675ac9f799f98827557 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 00:54:09 +0200 Subject: [PATCH 09/19] fix all rubocop warnings --- .rubocop.yml | 13 +++++++++---- autoload.rb | 2 -- main.rb | 13 ++++++------- models/author.rb | 13 ++++--------- models/book.rb | 15 +++++---------- models/order.rb | 17 ++++++----------- models/reader.rb | 15 +++++---------- modules/seed.rb | 3 --- modules/statistics.rb | 11 ++++------- modules/validation.rb | 3 --- 10 files changed, 39 insertions(+), 66 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index c711df4..1f1855f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,7 +6,12 @@ Style/RedundantArgument: # (new in 1.4) Style/SwapValues: # (new in 1.1) Enabled: true Metrics/MethodLength: - IgnoredMethods: ["initialize"] - Max: 13 -Metrics/AbcSize: - IgnoredMethods: ["initialize"] + Max: 20 +Style/FrozenStringLiteralComment: + Enabled: false +Metrics/PerceivedComplexity: + Max: 14 +Metrics/CyclomaticComplexity: + Max: 14 +Style/Documentation: + Enabled: false diff --git a/autoload.rb b/autoload.rb index dc30796..111cca4 100644 --- a/autoload.rb +++ b/autoload.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require 'date' require 'yaml' require 'faker' diff --git a/main.rb b/main.rb index d388514..9250a29 100644 --- a/main.rb +++ b/main.rb @@ -2,12 +2,12 @@ require_relative 'autoload' -reader1 = Reader.new(name: 22, email: "@sabaka", street: "", house: -10) -reader2 = Reader.new(name: 'Mark', email: "markus@gmail.com", city: 'London', street: 'Bayker', house: 21) -author1 = Author.new(name: "Boris Akunin") -author2 = Author.new(name: '', biography: "some bio") -book1 = Book.new(title: "BEloe solnce", author: author1) -book2 = Book.new(title: "", author: "Djek Vorobey") +reader1 = Reader.new(name: 22, email: '@sabaka', street: '', house: -10) +reader2 = Reader.new(name: 'Mark', email: 'markus@gmail.com', city: 'London', street: 'Bayker', house: 21) +author1 = Author.new(name: 'Boris Akunin') +author2 = Author.new(name: '', biography: 'some bio') +book1 = Book.new(title: 'BEloe solnce', author: author1) +book2 = Book.new(title: '', author: 'Djek Vorobey') order1 = Order.new(book: book2, reader: reader1) order2 = Order.new(book: book1, reader: reader2) @@ -69,4 +69,3 @@ puts lib1.top_readers puts lib1.top_books puts lib1.number_readers_of_top_books - diff --git a/models/author.rb b/models/author.rb index e67848c..b7484d0 100644 --- a/models/author.rb +++ b/models/author.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# class Author describes an Author model class Author include Validator @@ -13,12 +10,10 @@ def initialize(name: nil, biography: nil) def valid? errors = [presence, type, emptiness].flatten - if errors.empty? - return true - else - msg = "Object with id #{self.object_id} errors: " + errors.join(', ') - raise ValidationError, msg - end + return true if errors.empty? + + msg = "Object with id #{object_id} errors: " + errors.join(', ') + raise ValidationError, msg end private diff --git a/models/book.rb b/models/book.rb index 3d563d9..d7c0141 100644 --- a/models/book.rb +++ b/models/book.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# class Book describes a Book model class Book include Validator @@ -13,12 +10,10 @@ def initialize(title: nil, author: nil) def valid? errors = [presence, type, emptiness].flatten - if errors.empty? && @author.valid? - return true - else - msg = "Object with id #{self.object_id} errors: " + errors.join(', ') - raise ValidationError, msg - end + return true if errors.empty? && @author.valid? + + msg = "Object with id #{object_id} errors: " + errors.join(', ') + raise ValidationError, msg end private @@ -29,7 +24,7 @@ def presence def type [validate_type(String, :title), - validate_type(Author, :author)].flatten + validate_type(Author, :author)].flatten end def emptiness diff --git a/models/order.rb b/models/order.rb index d2be4e2..df50853 100644 --- a/models/order.rb +++ b/models/order.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# class Order describes an Order model class Order include Validator @@ -14,12 +11,10 @@ def initialize(book: nil, reader: nil, date: Date.today) def valid? errors = [presence, type].flatten - if errors.empty? && @book.valid? && @reader.valid? - return true - else - msg = "Object with id #{self.object_id} errors: " + errors.join(', ') - raise ValidationError, msg - end + return true if errors.empty? && @book.valid? && @reader.valid? + + msg = "Object with id #{object_id} errors: " + errors.join(', ') + raise ValidationError, msg end private @@ -30,7 +25,7 @@ def presence def type [validate_type(Book, :book), - validate_type(Reader, :reader), - validate_type(Date, :date)].flatten + validate_type(Reader, :reader), + validate_type(Date, :date)].flatten end end diff --git a/models/reader.rb b/models/reader.rb index f715548..570b3cd 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# class Reader describes a Reader model class Reader include Validator @@ -16,12 +13,10 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) def valid? errors = [presence, type, emptiness, positive].flatten - if errors.empty? - return true - else - msg = "Object with id #{self.object_id} errors: " + errors.join(', ') - raise ValidationError, msg - end + return true if errors.empty? + + msg = "Object with id #{object_id} errors: " + errors.join(', ') + raise ValidationError, msg end private @@ -32,7 +27,7 @@ def presence def type [validate_type(String, :name, :email, :city, :street), - validate_type(Integer, :house)].flatten + validate_type(Integer, :house)].flatten end def emptiness diff --git a/modules/seed.rb b/modules/seed.rb index 9f49083..8fa1abf 100644 --- a/modules/seed.rb +++ b/modules/seed.rb @@ -1,8 +1,5 @@ -# frozen_string_literal: true - require 'faker' -# module Seed generate fake data module Seed def generate_data seed_authors diff --git a/modules/statistics.rb b/modules/statistics.rb index 3c53b8b..95b537a 100644 --- a/modules/statistics.rb +++ b/modules/statistics.rb @@ -1,20 +1,17 @@ -# frozen_string_literal: true - -# module Statistics do some work module Statistics def top_readers(quantity = 1) - top_objects(:reader, quantity).keys.map { |reader| reader.name} + top_objects(:reader, quantity).keys.map(&:name) end def top_books(quantity = 1) - top_objects(:book, quantity).keys.map { |book| book.title} + top_objects(:book, quantity).keys.map(&:title) end def number_readers_of_top_books(quantity = 1) - top_objects(:book, quantity).values.flatten.map {|order| order.reader}.uniq.size + top_objects(:book, quantity).values.flatten.map(&:reader).uniq.size end def top_objects(object, quantity) - orders.group_by(&object).max_by(quantity) { |_key,value| value.size }.to_h + orders.group_by(&object).max_by(quantity) { |_key, value| value.size }.to_h end end diff --git a/modules/validation.rb b/modules/validation.rb index 737e99b..8bb114f 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# Validator module - add validations to models module Validator def validate_type(class_name, *attributes) errors = attributes.map do |attr| From f321f0b9e13aaaf3d4d30f274c9202d62cd1cd10 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 01:06:40 +0200 Subject: [PATCH 10/19] delete db.yml from git index --- db.yml | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 db.yml diff --git a/db.yml b/db.yml deleted file mode 100644 index dbcdd93..0000000 --- a/db.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- !ruby/object:Library -authors: -- &1 !ruby/object:Author - name: Boris Akunin - biography: -books: -- &2 !ruby/object:Book - title: BEloe solnce - author: *1 -readers: -- &3 !ruby/object:Reader - name: Mark - email: markus@gmail.com - city: London - street: Bayker - house: 21 -orders: -- !ruby/object:Order - book: *2 - reader: *3 - date: 2021-01-16 -- !ruby/object:Order - book: !ruby/object:Book - title: BEloe solnce - author: !ruby/object:Author - name: Boris Akunin - biography: - reader: !ruby/object:Reader - name: Mark - email: markus@gmail.com - city: London - street: Bayker - house: 21 - date: 2021-01-18 -- !ruby/object:Order - book: !ruby/object:Book - title: BEloe solnce - author: !ruby/object:Author - name: Boris Akunin - biography: - reader: !ruby/object:Reader - name: Mark - email: markus@gmail.com - city: London - street: Bayker - house: 21 - date: 2021-01-19 From 7ce382712a471bd2b715c69f57ab084f9e565538 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 01:22:29 +0200 Subject: [PATCH 11/19] remove frozen string magic comment --- Gemfile | 2 -- main.rb | 2 -- models/library.rb | 3 --- 3 files changed, 7 deletions(-) diff --git a/Gemfile b/Gemfile index 7563561..82aa4d4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,3 @@ -# frozen_string_literal: true - source 'https://rubygems.org' gem 'awesome_print' diff --git a/main.rb b/main.rb index 9250a29..9b26334 100644 --- a/main.rb +++ b/main.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require_relative 'autoload' reader1 = Reader.new(name: 22, email: '@sabaka', street: '', house: -10) diff --git a/models/library.rb b/models/library.rb index d8708da..dd755db 100644 --- a/models/library.rb +++ b/models/library.rb @@ -1,6 +1,3 @@ -# frozen_string_literal: true - -# class Reader describes a Reader model class Library include Seed include Statistics From 424ff65595adaaa6065860b49453cf535b392bbe Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 02:01:00 +0200 Subject: [PATCH 12/19] add raise error when object is not uniq --- main.rb | 6 ++++++ models/library.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/main.rb b/main.rb index 9b26334..b85abea 100644 --- a/main.rb +++ b/main.rb @@ -59,6 +59,12 @@ puts e.message end +begin + lib.add(order2) +rescue ValidationError => e + puts e.message +end + lib.store_to_file lib1 = Library.new diff --git a/models/library.rb b/models/library.rb index dd755db..36e2ae9 100644 --- a/models/library.rb +++ b/models/library.rb @@ -48,7 +48,7 @@ def can_add?(entity) end def add(entity) - return unless can_add?(entity) + raise ValidationError, 'Object is not uniq' unless can_add?(entity) if entity.is_a?(Author) && author_uniq?(entity) then @authors << entity elsif entity.is_a?(Book) && book_uniq?(entity) then @books << entity From a2cf70816fe65bc2c53833e489f6e9540cf87aa1 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Tue, 19 Jan 2021 19:41:43 +0200 Subject: [PATCH 13/19] remove ? from predicate method valid? --- models/author.rb | 2 +- models/book.rb | 4 ++-- models/library.rb | 2 +- models/order.rb | 4 ++-- models/reader.rb | 2 +- modules/seed.rb | 2 -- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/models/author.rb b/models/author.rb index b7484d0..40075b0 100644 --- a/models/author.rb +++ b/models/author.rb @@ -8,7 +8,7 @@ def initialize(name: nil, biography: nil) @biography = biography end - def valid? + def valid errors = [presence, type, emptiness].flatten return true if errors.empty? diff --git a/models/book.rb b/models/book.rb index d7c0141..864f696 100644 --- a/models/book.rb +++ b/models/book.rb @@ -8,9 +8,9 @@ def initialize(title: nil, author: nil) @author = author end - def valid? + def valid errors = [presence, type, emptiness].flatten - return true if errors.empty? && @author.valid? + return true if errors.empty? && @author.valid msg = "Object with id #{object_id} errors: " + errors.join(', ') raise ValidationError, msg diff --git a/models/library.rb b/models/library.rb index 36e2ae9..8010936 100644 --- a/models/library.rb +++ b/models/library.rb @@ -44,7 +44,7 @@ def order_uniq?(entity) end def can_add?(entity) - entity.valid? && uniq?(entity) + entity.valid && uniq?(entity) end def add(entity) diff --git a/models/order.rb b/models/order.rb index df50853..df35a92 100644 --- a/models/order.rb +++ b/models/order.rb @@ -9,9 +9,9 @@ def initialize(book: nil, reader: nil, date: Date.today) @date = date end - def valid? + def valid errors = [presence, type].flatten - return true if errors.empty? && @book.valid? && @reader.valid? + return true if errors.empty? && @book.valid && @reader.valid msg = "Object with id #{object_id} errors: " + errors.join(', ') raise ValidationError, msg diff --git a/models/reader.rb b/models/reader.rb index 570b3cd..cdc9116 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -11,7 +11,7 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @house = house end - def valid? + def valid errors = [presence, type, emptiness, positive].flatten return true if errors.empty? diff --git a/modules/seed.rb b/modules/seed.rb index 8fa1abf..828749f 100644 --- a/modules/seed.rb +++ b/modules/seed.rb @@ -1,5 +1,3 @@ -require 'faker' - module Seed def generate_data seed_authors From 850a78a3727e9f724ecae79dc4ff37625a050030 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Wed, 20 Jan 2021 19:46:57 +0200 Subject: [PATCH 14/19] change validation logic, remove uniq validation, other small fixes --- .rubocop.yml | 6 ----- autoload.rb | 2 +- error_class.rb | 14 +++++++++++ errorclass.rb | 2 -- main.rb | 54 +++++++++++-------------------------------- models/author.rb | 23 +++++++++--------- models/book.rb | 25 ++++++++++---------- models/library.rb | 51 +++++++++------------------------------- models/order.rb | 22 ++++++++---------- models/reader.rb | 30 ++++++++++++------------ modules/validation.rb | 2 +- 11 files changed, 88 insertions(+), 143 deletions(-) create mode 100644 error_class.rb delete mode 100644 errorclass.rb diff --git a/.rubocop.yml b/.rubocop.yml index 1f1855f..41ac85e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,13 +5,7 @@ Style/RedundantArgument: # (new in 1.4) Enabled: true Style/SwapValues: # (new in 1.1) Enabled: true -Metrics/MethodLength: - Max: 20 Style/FrozenStringLiteralComment: Enabled: false -Metrics/PerceivedComplexity: - Max: 14 -Metrics/CyclomaticComplexity: - Max: 14 Style/Documentation: Enabled: false diff --git a/autoload.rb b/autoload.rb index 111cca4..ceaa611 100644 --- a/autoload.rb +++ b/autoload.rb @@ -1,7 +1,7 @@ require 'date' require 'yaml' require 'faker' -require_relative 'errorclass' +require_relative 'error_class' require_relative 'modules/validation' require_relative 'modules/statistics' require_relative 'modules/seed' diff --git a/error_class.rb b/error_class.rb new file mode 100644 index 0000000..2327193 --- /dev/null +++ b/error_class.rb @@ -0,0 +1,14 @@ +class PresenceError < StandardError +end + +class ClassError < StandardError +end + +class EmptinessError < StandardError +end + +class PositiveNumberError < StandardError +end + +class NotAllowedObject < StandardError +end diff --git a/errorclass.rb b/errorclass.rb deleted file mode 100644 index 76a6400..0000000 --- a/errorclass.rb +++ /dev/null @@ -1,2 +0,0 @@ -class ValidationError < StandardError -end diff --git a/main.rb b/main.rb index b85abea..9957127 100644 --- a/main.rb +++ b/main.rb @@ -10,66 +10,38 @@ order2 = Order.new(book: book1, reader: reader2) lib = Library.new - -begin - lib.add(reader1) -rescue ValidationError => e - puts e.message -end - -begin - lib.add(reader2) -rescue ValidationError => e - puts e.message -end - -begin - lib.add(author1) -rescue ValidationError => e - puts e.message -end +lib.add(reader2) +lib.add(author1) +lib.add(book1) +lib.add(order2) begin lib.add(author2) -rescue ValidationError => e +rescue EmptinessError => e puts e.message end begin - lib.add(book1) -rescue ValidationError => e + lib.add(reader1) +rescue PresenceError => e puts e.message end begin lib.add(book2) -rescue ValidationError => e +rescue ClassError => e puts e.message end begin lib.add(order1) -rescue ValidationError => e - puts e.message -end - -begin - lib.add(order2) -rescue ValidationError => e - puts e.message -end - -begin - lib.add(order2) -rescue ValidationError => e +rescue ClassError => e puts e.message end +lib.generate_data lib.store_to_file -lib1 = Library.new -lib1.generate_data - -puts lib1.top_readers -puts lib1.top_books -puts lib1.number_readers_of_top_books +puts lib.top_readers +puts lib.top_books +puts lib.number_readers_of_top_books diff --git a/models/author.rb b/models/author.rb index 40075b0..dd7ce25 100644 --- a/models/author.rb +++ b/models/author.rb @@ -8,25 +8,24 @@ def initialize(name: nil, biography: nil) @biography = biography end - def valid - errors = [presence, type, emptiness].flatten - return true if errors.empty? - - msg = "Object with id #{object_id} errors: " + errors.join(', ') - raise ValidationError, msg + def valid? + [check_presence, check_class, check_emptiness].all? end private - def presence - validate_presence :name + def check_presence + errors = validate_presence :name + errors.empty? ? true : raise(PresenceError, errors) end - def type - validate_type String, :name + def check_class + errors = validate_class String, :name + errors.empty? ? true : raise(ClassError, errors) end - def emptiness - validate_emptiness :name + def check_emptiness + errors = validate_emptiness :name + errors.empty? ? true : raise(EmptinessError, errors) end end diff --git a/models/book.rb b/models/book.rb index 864f696..0126eb6 100644 --- a/models/book.rb +++ b/models/book.rb @@ -8,26 +8,25 @@ def initialize(title: nil, author: nil) @author = author end - def valid - errors = [presence, type, emptiness].flatten - return true if errors.empty? && @author.valid - - msg = "Object with id #{object_id} errors: " + errors.join(', ') - raise ValidationError, msg + def valid? + [check_presence, check_class, check_emptiness].all? && @author.valid? end private - def presence - validate_presence :title, :author + def check_presence + errors = validate_presence :title, :author + errors.empty? ? true : raise(PresenceError, errors) end - def type - [validate_type(String, :title), - validate_type(Author, :author)].flatten + def check_class + errors = [validate_class(String, :title), + validate_class(Author, :author)].flatten + errors.empty? ? true : raise(ClassError, errors) end - def emptiness - validate_emptiness :title + def check_emptiness + errors = validate_emptiness :title + errors.empty? ? true : raise(EmptinessError, errors) end end diff --git a/models/library.rb b/models/library.rb index 8010936..1111c73 100644 --- a/models/library.rb +++ b/models/library.rb @@ -4,6 +4,7 @@ class Library DATA_FILE = File.expand_path('../db.yml', __dir__) CLASSES = [Integer, String, Date, Author, Book, Library, Order, Reader].freeze + ADDING_ERROR = "Object cann't be added to library".freeze attr_reader :authors, :books, :readers, :orders @@ -16,44 +17,13 @@ def initialize load_from_file! end - def uniq?(entity) - check = instance_variables.detect do |var| - instance_variable_get(var).include?(entity) - end - check.nil? - end - - def author_uniq?(entity) - @authors.none? { |author| author.name == entity.name } - end - - def book_uniq?(entity) - @books.none? { |book| book.title == entity.title } - end - - def reader_uniq?(entity) - @readers.none? { |reader| reader.name == entity.name } - end - - def order_uniq?(entity) - @orders.none? do |order| - order.reader.name == entity.reader.name && - order.book.title == entity.book.title && - order.date == entity.date - end - end - - def can_add?(entity) - entity.valid && uniq?(entity) - end - def add(entity) - raise ValidationError, 'Object is not uniq' unless can_add?(entity) - - if entity.is_a?(Author) && author_uniq?(entity) then @authors << entity - elsif entity.is_a?(Book) && book_uniq?(entity) then @books << entity - elsif entity.is_a?(Reader) && reader_uniq?(entity) then @readers << entity - elsif entity.is_a?(Order) && order_uniq?(entity) then @orders << entity + if entity.is_a?(Author) && entity.valid? then @authors << entity + elsif entity.is_a?(Book) && entity.valid? then @books << entity + elsif entity.is_a?(Reader) && entity.valid? then @readers << entity + elsif entity.is_a?(Order) && entity.valid? then @orders << entity + else + raise NotAllowedObject, ADDING_ERROR end end @@ -62,9 +32,10 @@ def load_from_file! return unless data - data.instance_variables.each do |var| - data.instance_variable_get(var).map { |entity| add(entity) } - end + @authors = data.authors + @books = data.books + @readers = data.readers + @orders = data.orders end def store_to_file diff --git a/models/order.rb b/models/order.rb index df35a92..a2cf3d1 100644 --- a/models/order.rb +++ b/models/order.rb @@ -9,23 +9,21 @@ def initialize(book: nil, reader: nil, date: Date.today) @date = date end - def valid - errors = [presence, type].flatten - return true if errors.empty? && @book.valid && @reader.valid - - msg = "Object with id #{object_id} errors: " + errors.join(', ') - raise ValidationError, msg + def valid? + [check_presence, check_class].all? && @book.valid? && @reader.valid? end private - def presence - validate_presence :book + def check_presence + errors = validate_presence :book + errors.empty? ? true : raise(PresenceError, errors) end - def type - [validate_type(Book, :book), - validate_type(Reader, :reader), - validate_type(Date, :date)].flatten + def check_class + errors = [validate_class(Book, :book), + validate_class(Reader, :reader), + validate_class(Date, :date)].flatten + errors.empty? ? true : raise(ClassError, errors) end end diff --git a/models/reader.rb b/models/reader.rb index cdc9116..245ee93 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -11,30 +11,30 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @house = house end - def valid - errors = [presence, type, emptiness, positive].flatten - return true if errors.empty? - - msg = "Object with id #{object_id} errors: " + errors.join(', ') - raise ValidationError, msg + def valid? + [check_presence, check_class, check_emptiness, check_positive].all? end private - def presence - validate_presence :name, :email, :city, :street, :house + def check_presence + errors = validate_presence :name, :email, :city, :street, :house + errors.empty? ? true : raise(PresenceError, errors) end - def type - [validate_type(String, :name, :email, :city, :street), - validate_type(Integer, :house)].flatten + def check_class + errors = [validate_class(String, :name, :email, :city, :street), + validate_class(Integer, :house)].flatten + errors.empty? ? true : raise(ClassError, errors) end - def emptiness - validate_emptiness :name, :email, :city, :street, :house + def check_emptiness + errors = validate_emptiness :name, :email, :city, :street, :house + errors.empty? ? true : raise(EmptinessError, errors) end - def positive - validate_positive :house + def check_positive + errors = validate_positive :house + errors.empty? ? true : raise(PositiveNumberError, errors) end end diff --git a/modules/validation.rb b/modules/validation.rb index 8bb114f..bf49694 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -1,5 +1,5 @@ module Validator - def validate_type(class_name, *attributes) + def validate_class(class_name, *attributes) errors = attributes.map do |attr| if public_send(attr).class != class_name "Type of #{attr} must be an instance of #{class_name}" From 6b1ae7e75296a6c998f9a70bd5dae2f2a4e590eb Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Wed, 20 Jan 2021 20:58:44 +0200 Subject: [PATCH 15/19] change valid? method and add method --- models/author.rb | 6 ++++-- models/book.rb | 7 +++++-- models/library.rb | 10 ++++++---- models/order.rb | 7 +++++-- models/reader.rb | 7 +++++-- modules/validation.rb | 4 +--- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/models/author.rb b/models/author.rb index dd7ce25..a464eb4 100644 --- a/models/author.rb +++ b/models/author.rb @@ -8,8 +8,10 @@ def initialize(name: nil, biography: nil) @biography = biography end - def valid? - [check_presence, check_class, check_emptiness].all? + def validate! + check_presence + check_class + check_emptiness end private diff --git a/models/book.rb b/models/book.rb index 0126eb6..5b9d34b 100644 --- a/models/book.rb +++ b/models/book.rb @@ -8,8 +8,11 @@ def initialize(title: nil, author: nil) @author = author end - def valid? - [check_presence, check_class, check_emptiness].all? && @author.valid? + def validate! + check_presence + check_class + check_emptiness + @author.validate! end private diff --git a/models/library.rb b/models/library.rb index 1111c73..7f85b79 100644 --- a/models/library.rb +++ b/models/library.rb @@ -18,10 +18,12 @@ def initialize end def add(entity) - if entity.is_a?(Author) && entity.valid? then @authors << entity - elsif entity.is_a?(Book) && entity.valid? then @books << entity - elsif entity.is_a?(Reader) && entity.valid? then @readers << entity - elsif entity.is_a?(Order) && entity.valid? then @orders << entity + entity.validate! if entity.respond_to?(:validate!) + case entity + when Author then @authors << entity + when Book then @books << entity + when Reader then @readers << entity + when Order then @orders << entity else raise NotAllowedObject, ADDING_ERROR end diff --git a/models/order.rb b/models/order.rb index a2cf3d1..b3b4293 100644 --- a/models/order.rb +++ b/models/order.rb @@ -9,8 +9,11 @@ def initialize(book: nil, reader: nil, date: Date.today) @date = date end - def valid? - [check_presence, check_class].all? && @book.valid? && @reader.valid? + def validate! + check_presence + check_class + @book.validate! + @reader.validate! end private diff --git a/models/reader.rb b/models/reader.rb index 245ee93..86ad01f 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -11,8 +11,11 @@ def initialize(name: nil, email: nil, city: nil, street: nil, house: nil) @house = house end - def valid? - [check_presence, check_class, check_emptiness, check_positive].all? + def validate! + check_presence + check_class + check_emptiness + check_positive end private diff --git a/modules/validation.rb b/modules/validation.rb index bf49694..af93e28 100644 --- a/modules/validation.rb +++ b/modules/validation.rb @@ -1,9 +1,7 @@ module Validator def validate_class(class_name, *attributes) errors = attributes.map do |attr| - if public_send(attr).class != class_name - "Type of #{attr} must be an instance of #{class_name}" - end + "Type of #{attr} must be an instance of #{class_name}" if public_send(attr).class != class_name end errors.compact end From 89808e40cee6fa33b231ee9a55cd9d12936df5ee Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Thu, 21 Jan 2021 12:44:16 +0200 Subject: [PATCH 16/19] some fix of raise call --- models/author.rb | 6 +++--- models/book.rb | 6 +++--- models/order.rb | 4 ++-- models/reader.rb | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/models/author.rb b/models/author.rb index a464eb4..63124ed 100644 --- a/models/author.rb +++ b/models/author.rb @@ -18,16 +18,16 @@ def validate! def check_presence errors = validate_presence :name - errors.empty? ? true : raise(PresenceError, errors) + raise PresenceError, errors unless errors.empty? end def check_class errors = validate_class String, :name - errors.empty? ? true : raise(ClassError, errors) + raise ClassError, errors unless errors.empty? end def check_emptiness errors = validate_emptiness :name - errors.empty? ? true : raise(EmptinessError, errors) + raise EmptinessError, errors unless errors.empty? end end diff --git a/models/book.rb b/models/book.rb index 5b9d34b..263dbaa 100644 --- a/models/book.rb +++ b/models/book.rb @@ -19,17 +19,17 @@ def validate! def check_presence errors = validate_presence :title, :author - errors.empty? ? true : raise(PresenceError, errors) + raise PresenceError, errors unless errors.empty? end def check_class errors = [validate_class(String, :title), validate_class(Author, :author)].flatten - errors.empty? ? true : raise(ClassError, errors) + raise ClassError, errors unless errors.empty? end def check_emptiness errors = validate_emptiness :title - errors.empty? ? true : raise(EmptinessError, errors) + raise EmptinessError, errors unless errors.empty? end end diff --git a/models/order.rb b/models/order.rb index b3b4293..c6d8076 100644 --- a/models/order.rb +++ b/models/order.rb @@ -20,13 +20,13 @@ def validate! def check_presence errors = validate_presence :book - errors.empty? ? true : raise(PresenceError, errors) + raise PresenceError, errors unless errors.empty? end def check_class errors = [validate_class(Book, :book), validate_class(Reader, :reader), validate_class(Date, :date)].flatten - errors.empty? ? true : raise(ClassError, errors) + raise ClassError, errors unless errors.empty? end end diff --git a/models/reader.rb b/models/reader.rb index 86ad01f..18aeae4 100644 --- a/models/reader.rb +++ b/models/reader.rb @@ -22,22 +22,22 @@ def validate! def check_presence errors = validate_presence :name, :email, :city, :street, :house - errors.empty? ? true : raise(PresenceError, errors) + raise PresenceError, errors unless errors.empty? end def check_class errors = [validate_class(String, :name, :email, :city, :street), validate_class(Integer, :house)].flatten - errors.empty? ? true : raise(ClassError, errors) + raise ClassError, errors unless errors.empty? end def check_emptiness errors = validate_emptiness :name, :email, :city, :street, :house - errors.empty? ? true : raise(EmptinessError, errors) + raise EmptinessError, errors unless errors.empty? end def check_positive errors = validate_positive :house - errors.empty? ? true : raise(PositiveNumberError, errors) + raise PositiveNumberError, errors unless errors.empty? end end From e86ce774f38b24a7f9b39043f152acb1977ccb38 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Thu, 21 Jan 2021 13:11:00 +0200 Subject: [PATCH 17/19] fix pass order to statistics module as parameter --- main.rb | 6 +++--- modules/statistics.rb | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/main.rb b/main.rb index 9957127..7855b6d 100644 --- a/main.rb +++ b/main.rb @@ -42,6 +42,6 @@ lib.generate_data lib.store_to_file -puts lib.top_readers -puts lib.top_books -puts lib.number_readers_of_top_books +puts lib.top_readers(lib.orders) +puts lib.top_books(lib.orders) +puts lib.number_readers_of_top_books(lib.orders) diff --git a/modules/statistics.rb b/modules/statistics.rb index 95b537a..20ab8ea 100644 --- a/modules/statistics.rb +++ b/modules/statistics.rb @@ -1,17 +1,17 @@ module Statistics - def top_readers(quantity = 1) - top_objects(:reader, quantity).keys.map(&:name) + def top_readers(orders, quantity = 1) + top_objects(orders, :reader, quantity).keys.map(&:name) end - def top_books(quantity = 1) - top_objects(:book, quantity).keys.map(&:title) + def top_books(orders, quantity = 1) + top_objects(orders, :book, quantity).keys.map(&:title) end - def number_readers_of_top_books(quantity = 1) - top_objects(:book, quantity).values.flatten.map(&:reader).uniq.size + def number_readers_of_top_books(orders, quantity = 1) + top_objects(orders, :book, quantity).values.flatten.map(&:reader).uniq.size end - def top_objects(object, quantity) + def top_objects(orders, object, quantity) orders.group_by(&object).max_by(quantity) { |_key, value| value.size }.to_h end end From 0f6e1852c12a5fbc5f25dcb8ac51f6a2c9d68f69 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Thu, 21 Jan 2021 13:28:34 +0200 Subject: [PATCH 18/19] change Seed module to be a class --- main.rb | 2 +- models/library.rb | 1 - modules/seed.rb | 20 +++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/main.rb b/main.rb index 7855b6d..a1663df 100644 --- a/main.rb +++ b/main.rb @@ -39,7 +39,7 @@ puts e.message end -lib.generate_data +Seed.new(lib).generate_data lib.store_to_file puts lib.top_readers(lib.orders) diff --git a/models/library.rb b/models/library.rb index 7f85b79..7e39cb8 100644 --- a/models/library.rb +++ b/models/library.rb @@ -1,5 +1,4 @@ class Library - include Seed include Statistics DATA_FILE = File.expand_path('../db.yml', __dir__) diff --git a/modules/seed.rb b/modules/seed.rb index 828749f..f5333e7 100644 --- a/modules/seed.rb +++ b/modules/seed.rb @@ -1,4 +1,10 @@ -module Seed +class Seed + attr_reader :library + + def initialize(library) + @library = library + end + def generate_data seed_authors seed_books @@ -8,21 +14,21 @@ def generate_data def seed_authors 10.times do - add(Author.new(name: Faker::Book.unique.author, + library.add(Author.new(name: Faker::Book.unique.author, biography: Faker::Lorem.sentence(word_count: 10))) end end def seed_books 50.times do - add(Book.new(title: Faker::Book.unique.title, - author: authors.sample)) + library.add(Book.new(title: Faker::Book.unique.title, + author: library.authors.sample)) end end def seed_readers 20.times do - add(Reader.new(name: Faker::Name.unique.name, + library.add(Reader.new(name: Faker::Name.unique.name, email: Faker::Internet.unique.email, city: Faker::Address.city, street: Faker::Address.street_name, @@ -32,8 +38,8 @@ def seed_readers def seed_orders 100.times do - add(Order.new(book: books.sample, - reader: readers.sample, + library.add(Order.new(book: library.books.sample, + reader: library.readers.sample, date: Date.today - rand(0..30))) end end From c376c406d2f9d496c2fdbbd53d7c471a3fd6cae0 Mon Sep 17 00:00:00 2001 From: "Valeriy.Pogrebniak" Date: Thu, 21 Jan 2021 13:35:13 +0200 Subject: [PATCH 19/19] move error_class and seed to helpers --- autoload.rb | 4 ++-- error_class.rb => helpers/error_class.rb | 0 {modules => helpers}/seed.rb | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename error_class.rb => helpers/error_class.rb (100%) rename {modules => helpers}/seed.rb (100%) diff --git a/autoload.rb b/autoload.rb index ceaa611..1027840 100644 --- a/autoload.rb +++ b/autoload.rb @@ -1,10 +1,10 @@ require 'date' require 'yaml' require 'faker' -require_relative 'error_class' +require_relative 'helpers/error_class' +require_relative 'helpers/seed' require_relative 'modules/validation' require_relative 'modules/statistics' -require_relative 'modules/seed' require_relative 'models/author' require_relative 'models/reader' require_relative 'models/book' diff --git a/error_class.rb b/helpers/error_class.rb similarity index 100% rename from error_class.rb rename to helpers/error_class.rb diff --git a/modules/seed.rb b/helpers/seed.rb similarity index 100% rename from modules/seed.rb rename to helpers/seed.rb