рд▓реЗрдЦ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдореИрдВ рддреБрд░рдВрдд рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдореИрдВ рдирдпрд╛ рд╣реЛрдиреЗ рдХрд╛ рджрд┐рдЦрд╛рд╡рд╛ рдирд╣реАрдВ рдХрд░рддрд╛, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ IoC DI рдЬреИрд╕реЗ рдЕрд╡рд╕рд░ рдХреЛ рд╕рд╛рдЭрд╛ / рдпрд╛рдж рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореЗрд░реЗ рдкрд╛рд╕ рд▓реЗрдЦ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдХреЛрдИ рдЕрдиреБрднрд╡ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдореЗрд░рд╛ рдкрд╣рд▓рд╛ рд╣реИред рдпрджрд┐ рдЖрдкрдиреЗ рдХрдбрд╝рд╛рдИ рд╕реЗ рдиреНрдпрд╛рдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рддреЛ рдореИрдВрдиреЗ рдЕрдкрдиреА рдУрд░ рд╕реЗ рдкреВрд░реА рдХреЛрд╢рд┐рд╢ рдХреАред
рд╣рдо рдХрд┐рд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ
рдЕрдзрд┐рдХрд╛рдВрд╢ рд░реЗрд▓ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдБ рдЬреЛ рдореЗрд░реЗ рдкрд╛рд╕ рдЖрдИ рд╣реИрдВ рдЙрдирдореЗрдВ рдПрдХ рдмрдбрд╝реА рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЙрдирдХреЗ рдкрд╛рд╕ рдпрд╛ рддреЛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд╣реИрдВ, рдпрд╛ рдЙрдирдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреБрдЫ рддреБрдЪреНрдЫ рднрд╛рдЧ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рдЗрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рдЧреБрдгрд╡рддреНрддрд╛ рд╡рд╛рдВрдЫрд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХреБрдЫ рдЫреЛрдбрд╝ рджреЗрддреА рд╣реИред
рдЗрд╕рдХрд╛ рдореБрдЦреНрдп рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдмрд╕ рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдХреЗрд╡рд▓ рдЙрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦреЗ рдЧрдП рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдФрд░ рдЙрд╕ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рди рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реЗрд╡рд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдпрд╛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд╕рд┐рд░ рдореЗрдВ рдПрдХ рддрд╛рд░реНрдХрд┐рдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирддреА рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╡реНрдпрд╡рд╕рд╛рдп рддрд░реНрдХ рдХреЛрдб рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реНрддрд░ рдкрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ, рдореИрдВ рдпрд╣рд╛рдВ рд╕рд┐рд░реНрдл рдХреБрдЫ рд▓рд╛рдЗрдиреЗрдВ рдЬреЛрдбрд╝реВрдВрдЧрд╛ рдФрд░ рд╕рдм рдХреБрдЫ рдЧреНрд░рд╛рд╣рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдЧрд╛ред
рдФрд░ рдпрд╣ рдмрд╣реБрдд рдмреБрд░рд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг рд░реАрдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХреЗ рдкреНрд░рддрд┐рд░реЛрдз рдХреЛ рдЦреЛ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдРрд╕реЗ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдПрдиреНрдЯреНрд░реЙрдкреА рдзреАрд░реЗ-рдзреАрд░реЗ рдмрдврд╝ рд░рд╣реА рд╣реИред рдФрд░ рдЕрдЧрд░ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рд░рд┐рдлрд▓реЗрдХреНрдЯрд░ рдХрд░рдиреЗ рд╕реЗ рдбрд░рддреЗ рд╣реИрдВ, рддреЛ рдЪреАрдЬреЗрдВ рдмрд╣реБрдд рдЦрд░рд╛рдм рд╣реИрдВред
рдЬрд╛рд╡рд╛ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдИ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЕрд╕реНрддрд┐рддреНрд╡ рд╣реИ рдФрд░ рдкрд╣рд┐рдпрд╛ рдХреЛ рд╕реБрджреГрдврд╝ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпреЗ рд╕рдорд╛рдзрд╛рди рдмрд╣реБрдд рднрд╛рд░реА рд╣реИрдВ рдФрд░ рд╣рдореЗрд╢рд╛ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИред рд░реВрдмрд┐рд╕реНрдЯрд┐рд╕реНрдЯ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рдЧрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ, рдореБрдЭреЗ рдЕрднреА рднреА рд╕рдордЭ рдирд╣реАрдВ рдЖрдпрд╛ рдХрд┐ рдХреИрд╕реЗред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдпрд╣ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХреИрд╕реЗ рдХрд┐рдпрд╛ред
рд░реВрдмреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЗрд╕реЗ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЗрд╕рдХрд╛ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдЪрд╛рд░
рдореВрд▓ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдЬрд┐рди рд╡рд╕реНрддреБрдУрдВ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реЛрддреА рд╣реИ, рд╣рдореЗрдВ рдЙрдирдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
class UserService def initialize() @notification_service = NotificationService.new end def block_user(user) user.block! @notification_service.send(user, 'you have been blocked') end end
Block_user рд╡рд┐рдзрд┐ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдПрдХ рдЕрдкреНрд░рд┐рдп рдХреНрд╖рдг рдореЗрдВ рдкрд╛рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ NotificationService рд╕реЗ рд╕реВрдЪрд┐рдд рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдФрд░ рд╣рдо рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреБрдЫ рдиреНрдпреВрдирддрдо рднрд╛рдЧ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рд╣реИрдВред
рдЙрд▓рдЯрд╛ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдпрджрд┐ рд╣рдо рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗрд╡рд╛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:
class UserService def initialize(notification_service = NotificationService.new) @notification_service = notification_service end def block_user(user) user.block! @notification_service.send(user, 'you have been blocked') end end
рдЕрдм, рдЬрдм рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ NotificationService рдореЙрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ block_user рд╕рд╣реА рдХреНрд░рдо рдореЗрдВ рдФрд░ рд╕рд╣реА рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдзрд┐рд╕реВрдЪрдирд╛_ рд╕реЗрд╡рд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЦреАрдВрдЪрддрд╛ рд╣реИред
RSpec.describe UserService, type: :service do let (:notification_service) { instance_double(NotificationService) } let (:service) { UserService.new(notification_service) } describe ".block_user" do let (:user) { instance_double(User) } it "should block user and send notification" do expect(user).to receive :block! expect(notification_service).to receive(:send).with(user, "you have been blocked") service.block_user(user) end end end
рд░реЗрд▓ рдХреЗ рд▓рд┐рдП рдХреЗрд╕ рд╕реНрдЯрдбреА
рдЬрдм рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╕рд░реНрд╡рд┐рд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рд╕рднреА рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╕реНрд╡рдпрдВ рдмрдирд╛рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЛрдб рдХреЛрдб рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рд╕рд╛рде рдмрдврд╝рдиреЗ рд▓рдЧрддрд╛ рд╣реИ рдЬреЛ рдкрдардиреАрдпрддрд╛ рдХреЛ рдХрдо рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ, рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рдореЙрдбреНрдпреВрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реБрдЖ рдЬреЛ рдирд┐рд░реНрднрд░рддрд╛ рдкреНрд░рдмрдВрдзрди рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред
module Services module Injector def self.included(base)
рдПрдХ рдХреИрд╡рд┐рдПрдЯ рд╣реИ, рд╕реЗрд╡рд╛ рд╕рд┐рдВрдЧрд▓рдЯрди рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рддреНред рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╕реЗрд╡рд╛ рд╡рд░реНрдЧ include Singleton
ред
рдЕрдм ApplicationController рдРрдб рдореЗрдВ
require 'services' class ApplicationController < ActionController::Base include Services::Injector end
рдФрд░ рдЕрдм рдХрдВрдЯреНрд░реЛрд▓рд░реНрд╕ рдореЗрдВ рд╣рдо рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
class WelcomeController < ApplicationController inject_service :welcome def index render plain: welcome_service.text end end
рдЗрд╕ рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдХрд▓реНрдкрдирд╛ рдореЗрдВ, рд╣рдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ inst_double (WelcomeService) рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред
RSpec.describe WelcomeController, type: :controller do describe "index" do it "should render text from test service" do allow(controller.welcome_service).to receive(:text).and_return "OK" get :index expect(response).to have_attributes body: "OK" expect(response).to have_http_status 200 end end end
рдХреНрдпрд╛ рд╕реБрдзрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ рдХрд┐ рд╣рдо рдХреИрд╕реЗ рд╕реВрдЪрдирд╛рдПрдВ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рд╛рдд рдореЗрдВ рдпрд╣ рдПрдХ рдкреНрд░рджрд╛рддрд╛ рд╣реЛрдЧрд╛, рдФрд░ рджрд┐рди рдХреЗ рджреМрд░рд╛рди рдПрдХ рдФрд░ред рдЗрд╕реА рд╕рдордп, рдкреНрд░рджрд╛рддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕ рднреЗрдЬрдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реИрдВред
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, NotificationService рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕рдорд╛рди рд░рд╣рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИрдВред
class NightlyNotificationService < NotificationService end class DailyNotificationService < NotificationService end
рдЕрдм рд╣рдо рдПрдХ рд╡рд░реНрдЧ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╕реЗрд╡рд╛рдУрдВ рдХреА рд╕рд╢рд░реНрдд рдорд╛рдирдЪрд┐рддреНрд░рдг рдХрд░реЗрдЧрд╛
class NotificationServiceMapper include Singleton def take now = Time.now ((now.hour >= 00) and (now.hour <= 8)) ? NightlyNotificationService : DailyNotificationService end end
рдЕрдм рдЬрдм рд╣рдо рд╕реЗрд╡рд╛ рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рд▓реЗрддреЗ рд╣реИрдВ :: Helpers :: Service.instance рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ * Mapper рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ, рдФрд░ рдпрджрд┐ рдРрд╕рд╛ рд╣реИ, рддреЛ рдХреНрд▓рд╛рд╕ рдХреЛ рдЯреЗрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдерд┐рд░ рд░рдЦреЗрдВред