agencies, conferences - former GitLab developer advocate - teaching junior developers at goodprogrammer.ru - online internships for rubyists, Skillgrid virtual agency - live in Serbia
:address validates_confirmation_of :email, on: :create validates_acceptance_of :terms_of_service, on: :create validates_presence_of :profession, :workplace if: :in_moderation_mode? geocoded_by :address before_save :geocode, on: :create before_validation :strip_and_downcase_username, on: :create before_validation :set_default_color_theme, on: :create def in_moderation_mode? !!moderation_mode end def strip_and_downcase_username; end def set_default_color_theme; end end
:address) x x x x validates_confirmation_of(:email) x x validates_acceptance_of(terms_of_service) x x validates_presence_of(:profession, :workspace) x x geocode x x save x x x x create_organization x x Create Update Moderation Create Update
validates_presence_of :username, :email, :address validates_confirmation_of :email, on: :create validates_acceptance_of :terms_of_service, on: :create validates_presence_of :profession, :workplace if: :in_moderation_mode? geocoded_by :address before_save :geocode, on: :create before_validation :strip_and_downcase_username, on: :create before_validation :set_default_color_theme, on: :create after_save :create_default_organization if: :create_organization? def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end def in_moderation_mode? !!moderation_mode end def create_organization? !!create_an_organization end def strip_and_downcase_username; end def set_default_color_theme; end end FOUR DIFFERENT SCENARIOS
create? && !in_moderation_mode? validate(:email, :tos) if create? validate(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end
@income = 0 @credit_history = 0 @requested_amount = 0 @sum = 0 end def calculate #... end def result #... end end def calculate(age, sex, income, credit_history, requested_amount) sum = 0 if(age >= 21 && age <= 40) sum += 10 elsif(age > 40) sum += 20 end if(sex == "w") sum += 10 end if(income >= 20001 && income <= 40000) sum += 10 elsif(income > 40000) sum += 20 end if(credit_history == "y") sum += 20 end if(requested_amount < 20000) sum += 20 elsif(requested_amount > 20000 && requested_amount <= 40000) sum += 10 end @sum = sum end SIMPLE TASK
credit_history, requested_amount) #… end def result if(@sum >= 50) puts "Credit request approved" else puts "Credit request declined" end end end SIMPLE TASK
credit_history, requested_amount) #… end def result if(@sum >= 50) STDOUT.puts "Credit request approved" else STDOUT.puts "Credit request declined" end end end SIMPLE TASK
sex, income, credit_history, requested_amount) #… end def result if(@sum >= 50) STDOUT.puts "Credit request approved" else STDOUT.puts "Credit request declined" end end end
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end APPLICATION-LOGIC VALIDATIONS
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end INTERACTION WITH EXTERNAL SERVICE
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end COMPLEX INTERACTION WITH OTHER MODEL(S)
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end DATA FILTERING
if create? && !in_moderation_mode? validates_presence_of(:username, :email, :address) validates_confirmation_of(:email) if create? validates_acceptance_of(terms_of_service) if create? validates_presence_of(:profession, :workspace) if in_moderation_mode? geocode if create? save create_organization if create? && create_organization? end def create_default_organization Organization.create(address: address, title: "#{username}'s organization", person: self) end end SETTING DEFAULT VALUE
belongs_to :organization validates_presence_of :username, :email, :address end class PersonService def create(params) lat, lng = Geocoder.coordinates(params[:address]) username = params[:username].strip.downcase color = params[:color] || Person::DEFAULT_COLOR prepared_params = params.merge(lat: lat, lng: lng, color: color, username: username) person = Person.create(prepared_params) end end
:email validates_acceptance_of :terms_of_service end class PeopleController < ApplicationController def create p = PersonRegistrationForm.new(person_params) if p.valid? PersonService.create(person_params) redirect_to p else render :new end end end
long = Geocoder.coordinates(params[:address]) username = params[:username].strip.downcase color = params[:color] || Person::DEFAULT_COLOR prepared_params = params.merge(lat: lat, lng: long, color: color, username: username) person = Person.create(prepared_params).save! OrganizationMutator.create_deafult(person) if params[:create_an_organization] end end class OrganizationMutator def create_default(person) Organization.create(address: person.address, title: "#{person.username}'s organization", person: person) end end
params[:username].strip.downcase color = params[:color] || Person::DEFAULT_COLOR prepared_params = params.merge(color: color, username: username) person = Person.create(prepared_params).save! person end end class PersonService def create(params) lat, lng = Geocoder.coordinates(params[:address]) person = PersonMutator.create(params.merge(lat: lat, lng: lng)).save! OrganizationMutator.create(person) if params[:create_an_organization] end end
validates_acceptance_of :terms_of_service validates_presence_of :profession, :workplace end def create p = ModerationPersonRegistrationForm.new(person_params) if p.valid? PersonService.create(person_params) redirect_to p else render :new end end def update p = ModerationPersonRegistrationForm.find(params[:id]) if p.valid? p.update(person_params) redirect_to p else render :new end end
business rules Mutators to handle creation/editing/deletion logic (so that we always operate with objects in correct state) Services to handle business operations logic and interaction with external services Form objects application logic, use-case validation specific rules, defaults and filters THE PURPOSE OF LAYERS