From 4f852ea3de80534957fb0e508a10f20123421315 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 8 Apr 2019 06:56:06 +0200 Subject: [PATCH 01/14] Setup the project --- lecture_4/homework/.rubocop.yml | 2 ++ lecture_4/homework/Gemfile | 2 ++ lecture_4/homework/Gemfile.lock | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/lecture_4/homework/.rubocop.yml b/lecture_4/homework/.rubocop.yml index b9797cb5..b820ed41 100644 --- a/lecture_4/homework/.rubocop.yml +++ b/lecture_4/homework/.rubocop.yml @@ -1,3 +1,5 @@ +require: rubocop-performance + AllCops: Exclude: - bin/**/* diff --git a/lecture_4/homework/Gemfile b/lecture_4/homework/Gemfile index b742cedc..57f69fc7 100644 --- a/lecture_4/homework/Gemfile +++ b/lecture_4/homework/Gemfile @@ -5,12 +5,14 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.2' +gem 'awesome_print' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.2' # Use pg as the database for Active Record gem 'pg' # Use Puma as the app server gem 'puma', '~> 3.11' +gem 'rubocop-performance' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production diff --git a/lecture_4/homework/Gemfile.lock b/lecture_4/homework/Gemfile.lock index cfb773d4..4e178f2b 100644 --- a/lecture_4/homework/Gemfile.lock +++ b/lecture_4/homework/Gemfile.lock @@ -49,6 +49,7 @@ GEM tzinfo (~> 1.1) arel (9.0.0) ast (2.4.0) + awesome_print (1.8.0) bootsnap (1.4.1) msgpack (~> 1.0) builder (3.2.3) @@ -131,6 +132,8 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 1.6) + rubocop-performance (1.0.0) + rubocop (>= 0.58.0) ruby-progressbar (1.10.0) ruby_dep (1.5.0) spring (2.0.2) @@ -159,6 +162,7 @@ PLATFORMS DEPENDENCIES active_model_serializers + awesome_print bootsnap (>= 1.1.0) byebug listen (>= 3.0.5, < 3.2) @@ -166,6 +170,7 @@ DEPENDENCIES puma (~> 3.11) rails (~> 5.2.2) rubocop + rubocop-performance spring spring-watcher-listen (~> 2.0.0) tzinfo-data From b84eace1e1178a2e6234fc20428dd3ee6f0f189c Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Apr 2019 06:27:13 +0200 Subject: [PATCH 02/14] Setup Sentry and fix rubocop issues except for mercenaries controller file --- lecture_4/homework/Gemfile | 1 + lecture_4/homework/Gemfile.lock | 6 ++++++ .../app/controllers/application_controller.rb | 9 +++++++++ .../controllers/clans/warriors_controller.rb | 2 +- .../app/controllers/errors_controller.rb | 7 +++++++ lecture_4/homework/config/application.rb | 1 + .../homework/config/initializers/sentry.rb | 4 ++++ .../homework/lib/exceptions/exceptions.rb | 20 +++++++++++++++++++ .../controllers/errors_controller_test.rb | 9 +++++++++ 9 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 lecture_4/homework/app/controllers/errors_controller.rb create mode 100644 lecture_4/homework/config/initializers/sentry.rb create mode 100644 lecture_4/homework/lib/exceptions/exceptions.rb create mode 100644 lecture_4/homework/test/controllers/errors_controller_test.rb diff --git a/lecture_4/homework/Gemfile b/lecture_4/homework/Gemfile index 57f69fc7..029954bc 100644 --- a/lecture_4/homework/Gemfile +++ b/lecture_4/homework/Gemfile @@ -13,6 +13,7 @@ gem 'pg' # Use Puma as the app server gem 'puma', '~> 3.11' gem 'rubocop-performance' +gem 'sentry-raven' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production diff --git a/lecture_4/homework/Gemfile.lock b/lecture_4/homework/Gemfile.lock index 4e178f2b..6cbf013e 100644 --- a/lecture_4/homework/Gemfile.lock +++ b/lecture_4/homework/Gemfile.lock @@ -59,6 +59,8 @@ GEM concurrent-ruby (1.1.5) crass (1.0.4) erubi (1.8.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) ffi (1.10.0) globalid (0.4.2) activesupport (>= 4.2.0) @@ -83,6 +85,7 @@ GEM mini_portile2 (2.4.0) minitest (5.11.3) msgpack (1.2.9) + multipart-post (2.0.0) nio4r (2.3.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) @@ -136,6 +139,8 @@ GEM rubocop (>= 0.58.0) ruby-progressbar (1.10.0) ruby_dep (1.5.0) + sentry-raven (2.9.0) + faraday (>= 0.7.6, < 1.0) spring (2.0.2) activesupport (>= 4.2) spring-watcher-listen (2.0.1) @@ -171,6 +176,7 @@ DEPENDENCIES rails (~> 5.2.2) rubocop rubocop-performance + sentry-raven spring spring-watcher-listen (~> 2.0.0) tzinfo-data diff --git a/lecture_4/homework/app/controllers/application_controller.rb b/lecture_4/homework/app/controllers/application_controller.rb index 5f846d87..5cb1656c 100644 --- a/lecture_4/homework/app/controllers/application_controller.rb +++ b/lecture_4/homework/app/controllers/application_controller.rb @@ -2,4 +2,13 @@ class ApplicationController < ActionController::API include ErrorsHandler + + before_action :set_raven_context + + private + + def set_raven_context + Raven.user_context(id: session[:current_user_id]) # or anything else in session + Raven.extra_context(params: params.to_unsafe_h, url: request.url) + end end diff --git a/lecture_4/homework/app/controllers/clans/warriors_controller.rb b/lecture_4/homework/app/controllers/clans/warriors_controller.rb index 6ccf3ff9..acab2d6a 100644 --- a/lecture_4/homework/app/controllers/clans/warriors_controller.rb +++ b/lecture_4/homework/app/controllers/clans/warriors_controller.rb @@ -10,7 +10,7 @@ def index warriors = clan.warriors if params.key?(:alive) - if params[:alive].to_i == 0 + if params[:alive].to_i.zero? render json: warriors.dead else render json: warriors.alive diff --git a/lecture_4/homework/app/controllers/errors_controller.rb b/lecture_4/homework/app/controllers/errors_controller.rb new file mode 100644 index 00000000..30458903 --- /dev/null +++ b/lecture_4/homework/app/controllers/errors_controller.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ErrorsController < ApplicationController + def index + raise Exceptions::SpecificError.new(extra: { date: DateTime.now, another_important_key: 4 }) + end +end diff --git a/lecture_4/homework/config/application.rb b/lecture_4/homework/config/application.rb index 02acf880..77549df4 100644 --- a/lecture_4/homework/config/application.rb +++ b/lecture_4/homework/config/application.rb @@ -33,5 +33,6 @@ class Application < Rails::Application # Middleware like session, flash, cookies can be added back manually. # Skip views, helpers and assets when generating a new resource. config.api_only = true + config.autoload_paths << Rails.root.join('lib/exceptions') end end diff --git a/lecture_4/homework/config/initializers/sentry.rb b/lecture_4/homework/config/initializers/sentry.rb new file mode 100644 index 00000000..d67d78fe --- /dev/null +++ b/lecture_4/homework/config/initializers/sentry.rb @@ -0,0 +1,4 @@ +Raven.configure do |config| + config.dsn = 'https://774c7dbdb0304995af09d6b633d6c371:2fecc80d42a9418aa3268723022f5503@sentry.io/1433184' + config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) +end diff --git a/lecture_4/homework/lib/exceptions/exceptions.rb b/lecture_4/homework/lib/exceptions/exceptions.rb new file mode 100644 index 00000000..38aa7e0b --- /dev/null +++ b/lecture_4/homework/lib/exceptions/exceptions.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Exceptions + class MyAppError < StandardError + def initialize(message, context = {}) + super(message) + @context = context + end + + def raven_context + @context + end + end + + class SpecificError < MyAppError + def initialize(context = {}) + super('Message for SpecificError', context) + end + end +end diff --git a/lecture_4/homework/test/controllers/errors_controller_test.rb b/lecture_4/homework/test/controllers/errors_controller_test.rb new file mode 100644 index 00000000..f08e83fb --- /dev/null +++ b/lecture_4/homework/test/controllers/errors_controller_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ErrorsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end From d9079e5129d7ba210b6784fdd9364dc51d1b5a92 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Apr 2019 22:34:52 +0200 Subject: [PATCH 03/14] Add NullObject pattern to handle cases when no weapon or mercenary --- lecture_4/homework/app/models/warrior.rb | 4 ++++ lecture_4/homework/app/models/warriors/hussar.rb | 6 ++++++ lecture_4/homework/app/models/warriors/samurai.rb | 6 ++++++ lecture_4/homework/app/nulls/no_mercenary.rb | 7 +++++++ lecture_4/homework/app/nulls/no_weapon.rb | 7 +++++++ 5 files changed, 30 insertions(+) create mode 100644 lecture_4/homework/app/nulls/no_mercenary.rb create mode 100644 lecture_4/homework/app/nulls/no_weapon.rb diff --git a/lecture_4/homework/app/models/warrior.rb b/lecture_4/homework/app/models/warrior.rb index eacdc13f..7d698bfb 100644 --- a/lecture_4/homework/app/models/warrior.rb +++ b/lecture_4/homework/app/models/warrior.rb @@ -14,4 +14,8 @@ class Warrior < ApplicationRecord scope :alive, -> { where('death_date IS NULL') } scope :dead, -> { where('death_date IS NOT NULL') } + + def mercenary + super || NoMercenary.new.mercenary + end end diff --git a/lecture_4/homework/app/models/warriors/hussar.rb b/lecture_4/homework/app/models/warriors/hussar.rb index c277ff70..b8677d9b 100644 --- a/lecture_4/homework/app/models/warriors/hussar.rb +++ b/lecture_4/homework/app/models/warriors/hussar.rb @@ -5,6 +5,12 @@ class Hussar < Warrior attribute :preferred_weapon_kind, :string, default: :ranged def attack + weapon && attack_with_gun || NoWeapon.new.attack + end + + private + + def attack_with_gun "Hussar #{name} charged while yielding #{weapon.type.demodulize}" end end diff --git a/lecture_4/homework/app/models/warriors/samurai.rb b/lecture_4/homework/app/models/warriors/samurai.rb index 2b477760..6dabecba 100644 --- a/lecture_4/homework/app/models/warriors/samurai.rb +++ b/lecture_4/homework/app/models/warriors/samurai.rb @@ -5,6 +5,12 @@ class Samurai < Warrior attribute :preferred_weapon_kind, :string, default: :melee def attack + weapon && attack_with_gun || NoWeapon.new.attack + end + + private + + def attack_with_gun "Samurai #{name} attacked with #{weapon.type.demodulize}" end end diff --git a/lecture_4/homework/app/nulls/no_mercenary.rb b/lecture_4/homework/app/nulls/no_mercenary.rb new file mode 100644 index 00000000..c5d9d376 --- /dev/null +++ b/lecture_4/homework/app/nulls/no_mercenary.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class NoMercenary + def mercenary + 'This warrior has no mercenary' + end +end diff --git a/lecture_4/homework/app/nulls/no_weapon.rb b/lecture_4/homework/app/nulls/no_weapon.rb new file mode 100644 index 00000000..f407fdb5 --- /dev/null +++ b/lecture_4/homework/app/nulls/no_weapon.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class NoWeapon + def attack + 'This warrior has no weapon' + end +end From a2e496d87274e473add17eeccd8db253741db332 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Apr 2019 23:49:07 +0200 Subject: [PATCH 04/14] Create mercenaries method and available scope --- .../app/controllers/mercenaries_controller.rb | 17 +++++++++++++---- lecture_4/homework/app/models/mercenary.rb | 1 + .../app/nulls/no_available_mercenary.rb | 7 +++++++ lecture_4/homework/app/nulls/no_mercenary.rb | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 lecture_4/homework/app/nulls/no_available_mercenary.rb diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index 4382cfcf..58586eec 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -3,7 +3,7 @@ # This controller is written badly on purpose. Please refactor this class MercenariesController < ApplicationController def index - render json: Mercenary.where('available_from < ?', Time.now).all + render json: mercenaries end def show @@ -11,27 +11,36 @@ def show end def employ_best - mercenary = Mercenary.where('available_from < ?', Time.now).order(price: :asc).first # TODO: what about experience? + best_mercenary = mercenaries.available.order(experience: :desc).first + return unless best_mercenary + clan = find_clan building = find_building warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class - warrior = warrior_class.create!(name: mercenary.name, clan: clan, building: building, preferred_weapon_kind: mercenary.preferred_weapon_kind, mercenary: mercenary) - create_good_weapon(mercenary) + warrior = warrior_class.create!(name: best_mercenary.name, clan: clan, building: building, preferred_weapon_kind: best_mercenary.preferred_weapon_kind, mercenary: best_mercenary) + create_good_weapon(best_mercenary) + render json: warrior, include: [:mercenary], status: 201 end def employ return unless mercenary.available_from < Time.now + clan = find_clan building = find_building warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class warrior = warrior_class.create!(name: mercenary.name, clan: clan, building: building, preferred_weapon_kind: mercenary.preferred_weapon_kind, mercenary: mercenary) create_good_weapon(mercenary) + render json: warrior, include: [:mercenary], status: 201 end private + def mercenaries + @mercenaries ||= Mercenary.all + end + def mercenary @mercenary ||= Mercenary.find(params[:id]) end diff --git a/lecture_4/homework/app/models/mercenary.rb b/lecture_4/homework/app/models/mercenary.rb index 82aa4bdd..e9e61936 100644 --- a/lecture_4/homework/app/models/mercenary.rb +++ b/lecture_4/homework/app/models/mercenary.rb @@ -13,4 +13,5 @@ class Mercenary < ApplicationRecord scope :alive, -> { where('death_date IS NULL') } scope :dead, -> { where('death_date IS NOT NULL') } + scope :available, -> { where('available_from < ? AND warrior_id IS NULL', Time.now) } end diff --git a/lecture_4/homework/app/nulls/no_available_mercenary.rb b/lecture_4/homework/app/nulls/no_available_mercenary.rb new file mode 100644 index 00000000..af8ff4f9 --- /dev/null +++ b/lecture_4/homework/app/nulls/no_available_mercenary.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class NoAvailableMercenary + def employ_best + 'There is no available mercenary' + end +end diff --git a/lecture_4/homework/app/nulls/no_mercenary.rb b/lecture_4/homework/app/nulls/no_mercenary.rb index c5d9d376..b1f32f6f 100644 --- a/lecture_4/homework/app/nulls/no_mercenary.rb +++ b/lecture_4/homework/app/nulls/no_mercenary.rb @@ -2,6 +2,6 @@ class NoMercenary def mercenary - 'This warrior has no mercenary' + "This warrrior doesn't have a mercenary" end end From b6ff5af86ed16496fc621b039ed81953fe9c1b01 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 15 Apr 2019 11:36:27 +0200 Subject: [PATCH 05/14] Add Mercenary serializer --- .../homework/app/controllers/clans/warriors_controller.rb | 4 ++-- .../homework/app/serializers/mercenary_serializer.rb | 8 ++++++++ lecture_4/homework/app/serializers/warrior_serializer.rb | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 lecture_4/homework/app/serializers/mercenary_serializer.rb diff --git a/lecture_4/homework/app/controllers/clans/warriors_controller.rb b/lecture_4/homework/app/controllers/clans/warriors_controller.rb index acab2d6a..fc38b066 100644 --- a/lecture_4/homework/app/controllers/clans/warriors_controller.rb +++ b/lecture_4/homework/app/controllers/clans/warriors_controller.rb @@ -3,7 +3,7 @@ module Clans class WarriorsController < ApplicationController def show - render json: warrior, include: %i[weapon building] + render json: warrior, include: %i[weapon building mercenary] end def index @@ -16,7 +16,7 @@ def index render json: warriors.alive end else - render json: warriors + render json: warriors, include: [:mercenary] end end diff --git a/lecture_4/homework/app/serializers/mercenary_serializer.rb b/lecture_4/homework/app/serializers/mercenary_serializer.rb new file mode 100644 index 00000000..9cb4dad1 --- /dev/null +++ b/lecture_4/homework/app/serializers/mercenary_serializer.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class MercenarySerializer < ActiveModel::Serializer + attributes :name, :experience, :preferred_weapon_kind, :available_from, + :warrior_id + + belongs_to :warrior +end diff --git a/lecture_4/homework/app/serializers/warrior_serializer.rb b/lecture_4/homework/app/serializers/warrior_serializer.rb index 2499bf85..00d73711 100644 --- a/lecture_4/homework/app/serializers/warrior_serializer.rb +++ b/lecture_4/homework/app/serializers/warrior_serializer.rb @@ -7,4 +7,5 @@ class WarriorSerializer < ActiveModel::Serializer belongs_to :clan belongs_to :building has_one :weapon + has_one :mercenary end From 372efcd759534dd56f628dceea5c73014a5a7395 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 15 Apr 2019 12:21:14 +0200 Subject: [PATCH 06/14] Add MercenariesQueries --- .../app/controllers/mercenaries_controller.rb | 8 +++---- .../homework/app/queries/mercenaries_query.rb | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 lecture_4/homework/app/queries/mercenaries_query.rb diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index 58586eec..e4e55df7 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -11,7 +11,7 @@ def show end def employ_best - best_mercenary = mercenaries.available.order(experience: :desc).first + best_mercenary = MercenariesQuery.find_best return unless best_mercenary clan = find_clan @@ -24,7 +24,7 @@ def employ_best end def employ - return unless mercenary.available_from < Time.now + return unless MercenariesQuery.can_be_hired(mercenary_id: mercenary.id) clan = find_clan building = find_building @@ -38,11 +38,11 @@ def employ private def mercenaries - @mercenaries ||= Mercenary.all + @mercenaries ||= MercenariesQuery.all_mercenaries end def mercenary - @mercenary ||= Mercenary.find(params[:id]) + @mercenary ||= MercenariesQuery.mercenary(mercenary_id: params[:id]) end def find_building diff --git a/lecture_4/homework/app/queries/mercenaries_query.rb b/lecture_4/homework/app/queries/mercenaries_query.rb new file mode 100644 index 00000000..df3ec9dd --- /dev/null +++ b/lecture_4/homework/app/queries/mercenaries_query.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class MercenariesQuery + def self.can_be_hired(mercenary_id:, relation: Mercenary) + relation.find(mercenary_id).available_from < Time.now + end + + def self.find_best(relation: Mercenary) + relation.all + .where('available_from < ? AND warrior_id IS NULL', Time.now) + .order(experience: :desc) + .first + end + + def self.all_mercenaries(relation: Mercenary) + relation.all + end + + def self.mercenary(mercenary_id:, relation: Mercenary) + relation.find(mercenary_id) + end +end From 2597a15d7341ad1056e2c8690da3749419ecb7e4 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 16 Apr 2019 07:31:59 +0200 Subject: [PATCH 07/14] Add more Mercenaries in db seeds --- lecture_4/homework/db/seeds.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lecture_4/homework/db/seeds.rb b/lecture_4/homework/db/seeds.rb index e3666e1a..5f6f7126 100644 --- a/lecture_4/homework/db/seeds.rb +++ b/lecture_4/homework/db/seeds.rb @@ -16,6 +16,9 @@ unavailable_mercenary = Mercenary.create!(name: 'Cosimo Smallburrow', experience: 10, preferred_weapon_kind: 'melee', price: 100, available_from: 10.day.from_now) available_mercenary = Mercenary.create!(name: 'Priamus Brandagamba', experience: 5, preferred_weapon_kind: 'ranged', price: 20, available_from: 5.day.ago) expensive_mercenary = Mercenary.create!(name: 'Tanta Mugwort', experience: 50, preferred_weapon_kind: 'ranged', price: 200, available_from: 5.day.ago) +expensive_mercenary_2 = Mercenary.create!(name: 'Moby Dick', experience: 60, preferred_weapon_kind: 'melee', price: 220, available_from: 6.day.ago) +expensive_mercenary_3 = Mercenary.create!(name: 'Woody Allen', experience: 70, preferred_weapon_kind: 'ranged', price: 240, available_from: 7.day.ago) +expensive_mercenary_4 = Mercenary.create!(name: 'Tony Hawk', experience: 80, preferred_weapon_kind: 'melee', price: 260, available_from: 8.day.ago) Weapons::Katana.create!(warrior: samurai_2, range: 3, damage: 30) Weapons::Katana.create!(warrior: samurai_3, range: 2, damage: 35) From f063033a63c937ad0c6be811e0b0d30d6ca2ab8a Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 16 Apr 2019 08:13:58 +0200 Subject: [PATCH 08/14] Add Mercenaries, Clans and Buildings queries --- .../controllers/clans/warriors_controller.rb | 12 +++--- .../app/controllers/clans_controller.rb | 6 +-- .../app/controllers/mercenaries_controller.rb | 18 +++----- .../homework/app/queries/buildings_queries.rb | 7 ++++ .../homework/app/queries/clans_queries.rb | 19 +++++++++ .../homework/app/queries/warriors_queries.rb | 42 +++++++++++++++++++ 6 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 lecture_4/homework/app/queries/buildings_queries.rb create mode 100644 lecture_4/homework/app/queries/clans_queries.rb create mode 100644 lecture_4/homework/app/queries/warriors_queries.rb diff --git a/lecture_4/homework/app/controllers/clans/warriors_controller.rb b/lecture_4/homework/app/controllers/clans/warriors_controller.rb index fc38b066..453ceda2 100644 --- a/lecture_4/homework/app/controllers/clans/warriors_controller.rb +++ b/lecture_4/homework/app/controllers/clans/warriors_controller.rb @@ -7,7 +7,7 @@ def show end def index - warriors = clan.warriors + warriors = WarriorsQueries.all_clans_warriors(clan: clan) if params.key?(:alive) if params[:alive].to_i.zero? @@ -21,29 +21,29 @@ def index end def create - warrior = clan.warriors.create!(warrior_params) + warrior = WarriorsQueries.create_warrior(warrior_params: warrior_params, clan: clan) render json: warrior.to_json, include: %i[weapon building], status: 201 end def update - warrior.update!(warrior_params) + WarriorsQueries.update_warrior(warrior: warrior, warrior_params: warrior_params) render json: warrior, include: %i[weapon building] end def destroy - warrior.destroy! + WarriorsQueries.destroy_warrior(warrior: warrior) end private def clan - @clan ||= Clan.find(params[:clan_id]) + @clan ||= ClansQueries.find(clan_id: params[:clan_id]) end def warrior - @warrior ||= clan.warriors.find(params[:id]) + @warrior ||= WarriorsQueries.find_warrior(clan: clan, warrior_id: params[:id]) end def warrior_params diff --git a/lecture_4/homework/app/controllers/clans_controller.rb b/lecture_4/homework/app/controllers/clans_controller.rb index 720823e0..3583645b 100644 --- a/lecture_4/homework/app/controllers/clans_controller.rb +++ b/lecture_4/homework/app/controllers/clans_controller.rb @@ -2,7 +2,7 @@ class ClansController < ApplicationController def index - render json: Clan.all + render json: ClansQueries.all_clans end def show @@ -10,7 +10,7 @@ def show end def create - clan = Clan.create!(clan_params) + clan = ClansQueries.create_clan(clan_params: clan_params) render json: clan, include: [:warriors], status: 201 end @@ -18,7 +18,7 @@ def create private def clan - @clan ||= Clan.find(params[:id]) + @clan ||= ClansQueries.find(clan_id: params[:id]) end def clan_params diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index e4e55df7..211555e4 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -16,8 +16,8 @@ def employ_best clan = find_clan building = find_building - warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class - warrior = warrior_class.create!(name: best_mercenary.name, clan: clan, building: building, preferred_weapon_kind: best_mercenary.preferred_weapon_kind, mercenary: best_mercenary) + warrior_class = WarriorsQueries.choose_class(clan: clan) + warrior = WarriorsQueries.create_mercenary_warrior(warrior_class: warrior_class, mercenary: best_mercenary, clan: clan, building: building) create_good_weapon(best_mercenary) render json: warrior, include: [:mercenary], status: 201 @@ -28,8 +28,8 @@ def employ clan = find_clan building = find_building - warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class - warrior = warrior_class.create!(name: mercenary.name, clan: clan, building: building, preferred_weapon_kind: mercenary.preferred_weapon_kind, mercenary: mercenary) + warrior_class = WarriorsQueries.choose_class(clan: clan) + warrior = WarriorsQueries.create_mercenary_warrior(warrior_class: warrior_class, mercenary: mercenary, clan: clan, building: building) create_good_weapon(mercenary) render json: warrior, include: [:mercenary], status: 201 @@ -46,17 +46,11 @@ def mercenary end def find_building - if params[:building_id] - Building.find(params[:building_id]) - end + BuildingsQueries.find_building(id: params[:building_id]) end def find_clan - if params[:clan_id] - Clan.find(params[:clan_id]) - else - Clan.order(warriors_count: :desc).first - end + ClansQueries.find(clan_id: params[:clan_id]) end def create_good_weapon(mercenary) diff --git a/lecture_4/homework/app/queries/buildings_queries.rb b/lecture_4/homework/app/queries/buildings_queries.rb new file mode 100644 index 00000000..d9952dc6 --- /dev/null +++ b/lecture_4/homework/app/queries/buildings_queries.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class BuildingsQueries + def self.find_building(id:, relation: Building) + relation.find(id) if id + end +end diff --git a/lecture_4/homework/app/queries/clans_queries.rb b/lecture_4/homework/app/queries/clans_queries.rb new file mode 100644 index 00000000..f085031d --- /dev/null +++ b/lecture_4/homework/app/queries/clans_queries.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ClansQueries + def self.find(clan_id:, relation: Clan) + if clan_id + relation.find(clan_id) + else + relation.order(warriors_count: :desc).first + end + end + + def self.all_clans(relation: Clan) + relation.all + end + + def self.create_clan(clan_params:, relation: Clan) + relation.create!(clan_params) + end +end diff --git a/lecture_4/homework/app/queries/warriors_queries.rb b/lecture_4/homework/app/queries/warriors_queries.rb new file mode 100644 index 00000000..4e97dac4 --- /dev/null +++ b/lecture_4/homework/app/queries/warriors_queries.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class WarriorsQueries + def self.destroy_warrior(warrior:) + warrior.destroy! + end + + def self.all_clans_warriors(clan:) + clan.warriors.all + end + + def self.find_warrior(clan:, warrior_id:) + clan.warriors.find(warrior_id) + end + + def self.create_warrior(clan:, warrior_params:) + clan.warriors.create!(warrior_params) + end + + def self.update_warrior(warrior:, warrior_params:) + warrior.update!(warrior_params) + end + + def self.choose_class(clan:) + clan.warriors + .select('type, count(type) as warriors_count') + .group(:type) + .order('warriors_count ASC') + .first + .class + end + + def self.create_mercenary_warrior(warrior_class:, mercenary:, clan:, building:) + warrior_class.create!( + name: mercenary.name, + clan: clan, + building: building, + preferred_weapon_kind: mercenary.preferred_weapon_kind, + mercenary: mercenary + ) + end +end From 8e33a3781bf6866aca5bd9a3d05f44ef049ed0f7 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 12:16:17 +0200 Subject: [PATCH 09/14] Handle else case in create_good_weapon method --- .../app/controllers/mercenaries_controller.rb | 2 +- lecture_4/homework/app/models/weapons/magic_wand.rb | 11 +++++++++++ lecture_4/homework/db/seeds.rb | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 lecture_4/homework/app/models/weapons/magic_wand.rb diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index 211555e4..caa34f4e 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -60,7 +60,7 @@ def create_good_weapon(mercenary) when :ranged Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) else - # TODO: some default? + Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) end end end diff --git a/lecture_4/homework/app/models/weapons/magic_wand.rb b/lecture_4/homework/app/models/weapons/magic_wand.rb new file mode 100644 index 00000000..18d5b99c --- /dev/null +++ b/lecture_4/homework/app/models/weapons/magic_wand.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Weapons + class MagicWand < Weapon + attribute :kind, :string, default: :magical + + def calculate_damage(distance) + distance < range ? damage * 3 : damage * 0.05 + end + end +end diff --git a/lecture_4/homework/db/seeds.rb b/lecture_4/homework/db/seeds.rb index 5f6f7126..c918e860 100644 --- a/lecture_4/homework/db/seeds.rb +++ b/lecture_4/homework/db/seeds.rb @@ -19,6 +19,9 @@ expensive_mercenary_2 = Mercenary.create!(name: 'Moby Dick', experience: 60, preferred_weapon_kind: 'melee', price: 220, available_from: 6.day.ago) expensive_mercenary_3 = Mercenary.create!(name: 'Woody Allen', experience: 70, preferred_weapon_kind: 'ranged', price: 240, available_from: 7.day.ago) expensive_mercenary_4 = Mercenary.create!(name: 'Tony Hawk', experience: 80, preferred_weapon_kind: 'melee', price: 260, available_from: 8.day.ago) +expensive_mercenary_5 = Mercenary.create!(name: 'Magic Man', experience: 100, preferred_weapon_kind: 'magical', price: 280, available_from: 8.day.ago) +expensive_mercenary_6 = Mercenary.create!(name: 'Harry Potter', experience: 120, preferred_weapon_kind: 'magical', price: 300, available_from: 8.day.ago) +expensive_mercenary_7 = Mercenary.create!(name: 'Bruce Magic Lee', experience: 140, preferred_weapon_kind: 'magical', price: 320, available_from: 8.day.ago) Weapons::Katana.create!(warrior: samurai_2, range: 3, damage: 30) Weapons::Katana.create!(warrior: samurai_3, range: 2, damage: 35) From 08e1ee06ebe2b37babd44ded40ab3df75cf6459c Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 12:18:13 +0200 Subject: [PATCH 10/14] Add object services, except create_good_weapon method --- .../app/controllers/mercenaries_controller.rb | 39 ++++------- lecture_4/homework/app/nulls/no_mercenary.rb | 4 ++ .../app/services/mercenary_recruiter.rb | 66 +++++++++++++++++++ 3 files changed, 84 insertions(+), 25 deletions(-) create mode 100644 lecture_4/homework/app/services/mercenary_recruiter.rb diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index caa34f4e..f8e4a619 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -11,28 +11,25 @@ def show end def employ_best - best_mercenary = MercenariesQuery.find_best - return unless best_mercenary + mercenary = MercenariesQuery.find_best - clan = find_clan - building = find_building - warrior_class = WarriorsQueries.choose_class(clan: clan) - warrior = WarriorsQueries.create_mercenary_warrior(warrior_class: warrior_class, mercenary: best_mercenary, clan: clan, building: building) - create_good_weapon(best_mercenary) + render json: { error: NoMercenary.new.employ } and return unless mercenary - render json: warrior, include: [:mercenary], status: 201 + MercenaryRecruiter.call(mercenary: mercenary, params: params) + create_good_weapon(mercenary: mercenary) + + render json: mercenary, include: %i[warrior], status: 201 end def employ - return unless MercenariesQuery.can_be_hired(mercenary_id: mercenary.id) + unless MercenariesQuery.can_be_hired(mercenary_id: mercenary.id) + render json: { error: NoMercenary.new.employ } and return + end - clan = find_clan - building = find_building - warrior_class = WarriorsQueries.choose_class(clan: clan) - warrior = WarriorsQueries.create_mercenary_warrior(warrior_class: warrior_class, mercenary: mercenary, clan: clan, building: building) - create_good_weapon(mercenary) + MercenaryRecruiter.call(mercenary: mercenary, params: params) + create_good_weapon(mercenary: mercenary) - render json: warrior, include: [:mercenary], status: 201 + render json: mercenary, include: %i[warrior], status: 201 end private @@ -45,16 +42,8 @@ def mercenary @mercenary ||= MercenariesQuery.mercenary(mercenary_id: params[:id]) end - def find_building - BuildingsQueries.find_building(id: params[:building_id]) - end - - def find_clan - ClansQueries.find(clan_id: params[:clan_id]) - end - - def create_good_weapon(mercenary) - case mercenary.preferred_weapon_kind + def create_good_weapon(mercenary:) + case mercenary.preferred_weapon_kind.to_sym when :melee Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) when :ranged diff --git a/lecture_4/homework/app/nulls/no_mercenary.rb b/lecture_4/homework/app/nulls/no_mercenary.rb index b1f32f6f..cf3ede2f 100644 --- a/lecture_4/homework/app/nulls/no_mercenary.rb +++ b/lecture_4/homework/app/nulls/no_mercenary.rb @@ -4,4 +4,8 @@ class NoMercenary def mercenary "This warrrior doesn't have a mercenary" end + + def employ + 'There is no available mercenary' + end end diff --git a/lecture_4/homework/app/services/mercenary_recruiter.rb b/lecture_4/homework/app/services/mercenary_recruiter.rb new file mode 100644 index 00000000..bea0c631 --- /dev/null +++ b/lecture_4/homework/app/services/mercenary_recruiter.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +class MercenaryRecruiter + def self.call(mercenary:, params:) + new(mercenary, params) + end + + private + + attr_reader :params, :mercenary + + def initialize(mercenary, params) + @mercenary = mercenary + @params = params + employ + end + + def employ + clan = ClanFinder.new(params: params[:clan_id]).call + building = BuildingFinder.new(params: params[:building_id]).call + warrior_class = WarriorsQueries.choose_class(clan: clan) + + WarriorsQueries.create_mercenary_warrior( + warrior_class: warrior_class, + mercenary: mercenary, + clan: clan, + building: building + ) + end +end + +class ClanFinder + def initialize(params:) + @params = params + end + + def call + find_clan + end + + private + + attr_reader :params + + def find_clan + ClansQueries.find(clan_id: params) + end +end + +class BuildingFinder + def initialize(params:) + @params = params + end + + def call + find_building + end + + private + + attr_reader :params + + def find_building + BuildingsQueries.find_building(id: params) + end +end From c9fee1144f03da1805ecb23aa7456a09f4267b8c Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 13:49:55 +0200 Subject: [PATCH 11/14] Extract create_good_weapon method into separate service class --- .../app/controllers/mercenaries_controller.rb | 16 ------------ .../app/services/mercenary_recruiter.rb | 26 +++++++++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index f8e4a619..c30ae752 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -12,12 +12,9 @@ def show def employ_best mercenary = MercenariesQuery.find_best - render json: { error: NoMercenary.new.employ } and return unless mercenary MercenaryRecruiter.call(mercenary: mercenary, params: params) - create_good_weapon(mercenary: mercenary) - render json: mercenary, include: %i[warrior], status: 201 end @@ -27,8 +24,6 @@ def employ end MercenaryRecruiter.call(mercenary: mercenary, params: params) - create_good_weapon(mercenary: mercenary) - render json: mercenary, include: %i[warrior], status: 201 end @@ -41,15 +36,4 @@ def mercenaries def mercenary @mercenary ||= MercenariesQuery.mercenary(mercenary_id: params[:id]) end - - def create_good_weapon(mercenary:) - case mercenary.preferred_weapon_kind.to_sym - when :melee - Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) - when :ranged - Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) - else - Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) - end - end end diff --git a/lecture_4/homework/app/services/mercenary_recruiter.rb b/lecture_4/homework/app/services/mercenary_recruiter.rb index bea0c631..c055b163 100644 --- a/lecture_4/homework/app/services/mercenary_recruiter.rb +++ b/lecture_4/homework/app/services/mercenary_recruiter.rb @@ -26,6 +26,7 @@ def employ clan: clan, building: building ) + WeaponCreator.new(mercenary: mercenary).call end end @@ -64,3 +65,28 @@ def find_building BuildingsQueries.find_building(id: params) end end + +class WeaponCreator + def initialize(mercenary:) + @mercenary = mercenary + end + + def call + create_good_weapon + end + + private + + attr_reader :mercenary + + def create_good_weapon + case mercenary.preferred_weapon_kind.to_sym + when :melee + Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) + when :ranged + Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) + else + Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) + end + end +end From fde8550ce1866da911042e492c852c233ad7e8c8 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 13:55:31 +0200 Subject: [PATCH 12/14] Extract services into separate files --- .../app/controllers/mercenaries_controller.rb | 1 - .../homework/app/services/building_finder.rb | 19 ++++++ .../homework/app/services/clan_finder.rb | 19 ++++++ .../app/services/mercenary_recruiter.rb | 61 ------------------- .../homework/app/services/weapon_creator.rb | 26 ++++++++ 5 files changed, 64 insertions(+), 62 deletions(-) create mode 100644 lecture_4/homework/app/services/building_finder.rb create mode 100644 lecture_4/homework/app/services/clan_finder.rb create mode 100644 lecture_4/homework/app/services/weapon_creator.rb diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index c30ae752..23078088 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -# This controller is written badly on purpose. Please refactor this class MercenariesController < ApplicationController def index render json: mercenaries diff --git a/lecture_4/homework/app/services/building_finder.rb b/lecture_4/homework/app/services/building_finder.rb new file mode 100644 index 00000000..edde9b07 --- /dev/null +++ b/lecture_4/homework/app/services/building_finder.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class BuildingFinder + def initialize(params:) + @params = params + end + + def call + find_building + end + + private + + attr_reader :params + + def find_building + BuildingsQueries.find_building(id: params) + end +end diff --git a/lecture_4/homework/app/services/clan_finder.rb b/lecture_4/homework/app/services/clan_finder.rb new file mode 100644 index 00000000..72c630c6 --- /dev/null +++ b/lecture_4/homework/app/services/clan_finder.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ClanFinder + def initialize(params:) + @params = params + end + + def call + find_clan + end + + private + + attr_reader :params + + def find_clan + ClansQueries.find(clan_id: params) + end +end diff --git a/lecture_4/homework/app/services/mercenary_recruiter.rb b/lecture_4/homework/app/services/mercenary_recruiter.rb index c055b163..3f26251a 100644 --- a/lecture_4/homework/app/services/mercenary_recruiter.rb +++ b/lecture_4/homework/app/services/mercenary_recruiter.rb @@ -29,64 +29,3 @@ def employ WeaponCreator.new(mercenary: mercenary).call end end - -class ClanFinder - def initialize(params:) - @params = params - end - - def call - find_clan - end - - private - - attr_reader :params - - def find_clan - ClansQueries.find(clan_id: params) - end -end - -class BuildingFinder - def initialize(params:) - @params = params - end - - def call - find_building - end - - private - - attr_reader :params - - def find_building - BuildingsQueries.find_building(id: params) - end -end - -class WeaponCreator - def initialize(mercenary:) - @mercenary = mercenary - end - - def call - create_good_weapon - end - - private - - attr_reader :mercenary - - def create_good_weapon - case mercenary.preferred_weapon_kind.to_sym - when :melee - Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) - when :ranged - Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) - else - Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) - end - end -end diff --git a/lecture_4/homework/app/services/weapon_creator.rb b/lecture_4/homework/app/services/weapon_creator.rb new file mode 100644 index 00000000..d8fa50e4 --- /dev/null +++ b/lecture_4/homework/app/services/weapon_creator.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class WeaponCreator + def initialize(mercenary:) + @mercenary = mercenary + end + + def call + create_good_weapon + end + + private + + attr_reader :mercenary + + def create_good_weapon + case mercenary.preferred_weapon_kind.to_sym + when :melee + Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) + when :ranged + Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) + else + Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) + end + end +end From 6f3caa05064cf8da57fb84caa2c0bee569919157 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 14:06:24 +0200 Subject: [PATCH 13/14] Create WeaponsQueries --- lecture_4/homework/app/queries/weapons_queries.rb | 15 +++++++++++++++ lecture_4/homework/app/services/weapon_creator.rb | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 lecture_4/homework/app/queries/weapons_queries.rb diff --git a/lecture_4/homework/app/queries/weapons_queries.rb b/lecture_4/homework/app/queries/weapons_queries.rb new file mode 100644 index 00000000..fadd79ca --- /dev/null +++ b/lecture_4/homework/app/queries/weapons_queries.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class WeaponsQueries + def self.create_katana(warrior:, relation:) + relation.create!(warrior: warrior, range: 2, damage: 25) + end + + def self.create_musket(warrior:, relation:) + relation.create!(warrior: warrior, range: 40, damage: 10) + end + + def self.create_magic_wand(warrior:, relation:) + relation.create!(warrior: warrior, range: 20, damage: 45) + end +end diff --git a/lecture_4/homework/app/services/weapon_creator.rb b/lecture_4/homework/app/services/weapon_creator.rb index d8fa50e4..f1265107 100644 --- a/lecture_4/homework/app/services/weapon_creator.rb +++ b/lecture_4/homework/app/services/weapon_creator.rb @@ -16,11 +16,11 @@ def call def create_good_weapon case mercenary.preferred_weapon_kind.to_sym when :melee - Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) + WeaponsQueries.create_katana(warrior: mercenary.warrior, relation: Weapons::Katana) when :ranged - Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) + WeaponsQueries.create_musket(warrior: mercenary.warrior, relation: Weapons::Musket) else - Weapons::MagicWand.create!(warrior: mercenary.warrior, range: 20, damage: 45) + WeaponsQueries.create_magic_wand(warrior: mercenary.warrior, relation: Weapons::MagicWand) end end end From 8bb38f6252d97bf4adbff1e744a0574b07ba65e1 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 17 Apr 2019 15:45:30 +0200 Subject: [PATCH 14/14] Refactor code - dry out code into separate methods --- .../app/controllers/mercenaries_controller.rb | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index 23078088..6af36286 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -11,19 +11,15 @@ def show def employ_best mercenary = MercenariesQuery.find_best - render json: { error: NoMercenary.new.employ } and return unless mercenary + render_no_available_mercenary and return unless mercenary - MercenaryRecruiter.call(mercenary: mercenary, params: params) - render json: mercenary, include: %i[warrior], status: 201 + recruit_mercenary(mercenary: mercenary) end def employ - unless MercenariesQuery.can_be_hired(mercenary_id: mercenary.id) - render json: { error: NoMercenary.new.employ } and return - end + render_no_available_mercenary and return unless can_be_hired? - MercenaryRecruiter.call(mercenary: mercenary, params: params) - render json: mercenary, include: %i[warrior], status: 201 + recruit_mercenary(mercenary: mercenary) end private @@ -35,4 +31,17 @@ def mercenaries def mercenary @mercenary ||= MercenariesQuery.mercenary(mercenary_id: params[:id]) end + + def recruit_mercenary(mercenary:) + MercenaryRecruiter.call(mercenary: mercenary, params: params) + render json: mercenary, include: %i[warrior], status: 201 + end + + def render_no_available_mercenary + render json: { error: NoMercenary.new.employ } + end + + def can_be_hired? + MercenariesQuery.can_be_hired(mercenary_id: mercenary.id) + end end