the worst ruby codes i’ve seen in my life - rubykaigi 2015
TRANSCRIPT
![Page 1: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/1.jpg)
The worst Ruby codes I’ve seen in my life
RubyKaigi 2015
@Prodis
![Page 2: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/2.jpg)
Fernando Hamasaki de Amorim @Prodis
• Developing web applications for 15 years
• Writing Ruby code since 2009
• Working at Locaweb, the biggest hosting company in Brazil
• Playing basketball at the free time
![Page 3: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/3.jpg)
WOP
![Page 4: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/4.jpg)
WOP Workaround Oriented Programming
![Page 5: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/5.jpg)
WOPWorkaround Oriented Programming is an advance
technique of software development that uses of any
kind of workaround, patch e all of evil a code can have.
WOP is based on code duplication, redundant flows,
unnecessary tasks and wheels reinvention.
![Page 6: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/6.jpg)
The worst Ruby codes I’ve seen in my life
"The names have been changed to protect the innocent."
![Page 7: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/7.jpg)
A first example of WOP: masking credit card
numbers
![Page 8: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/8.jpg)
describe '#mask_credit_card' do let(:number) { '5464193830403276' }
it 'returns masked credit card number' do masked = mask_credit_card(number) expect(masked).to eq '************3276' end end
![Page 9: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/9.jpg)
def mask_credit_card(number) limit = number.length - 4 “#{'*' * limit}#{number[limit..-1]}” end
![Page 10: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/10.jpg)
def mask_credit_card_wop(number) (number.length - 4).times do |i| number[i] = '*' end
number end
![Page 11: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/11.jpg)
describe '#mask_credit_card_wop' do let(:number) { '5464193830403276' }
it 'returns masked credit card number' do masked = mask_credit_card_wop(number)
expect(masked).to eq '************3276' end
it 'does not change number variable' do mask_credit_card_wop(number) expect(number).to eq '5464193830403276' end end
![Page 12: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/12.jpg)
#mask_credit_card_wop returns masked credit card number does not change number variable (FAILED - 1)
Failures:
1) #mask_credit_card_wop does not change number variable Failure/Error: expect(number).to eq '5464193830403276'
expected: "5464193830403276" got: "************3276"
(compared using ==) # ./spec/mask_credit_card/mask_credit_card_spec.rb:23:in `block (2 levels) in <top (required)>'
Finished in 0.0202 seconds (files took 0.17324 seconds to load) 2 examples, 1 failure
![Page 13: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/13.jpg)
def mask_credit_card_wop(number) (number.length - 4).times do |i| number[i] = '*' end
number end
![Page 14: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/14.jpg)
Unclear flow
![Page 15: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/15.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 16: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/16.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 17: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/17.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 18: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/18.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 19: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/19.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 20: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/20.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
if site.blank? flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return else domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
if domain.save flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path return else flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end end end end
![Page 21: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/21.jpg)
How to fix it?
![Page 22: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/22.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
unless site flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return end
domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
unless domain.save flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end
flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path end end
![Page 23: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/23.jpg)
class Support::DomainsController < Support::BaseController def create site = Site.find_by(name: params[:domain][:site])
unless site flash[:alert] = I18n.t('support.domains.errors.without_site') redirect_to new_support_domain_path return end
domain = site.domains.build(address: params[:domain][:address]) domain.support_create = true
unless domain.save flash[:alert] = I18n.t('support.domains.errors.invalid') redirect_to new_support_domain_path return end
flash[:success] = I18n.t('support.domains.success') redirect_to support_domains_path end end
![Page 24: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/24.jpg)
No Ruby way
![Page 25: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/25.jpg)
class PaymentGatewayWOP def initialize(options = {}) raise ArgumentError if options[:email].to_s.strip.empty? raise ArgumentError if options[:token].to_s.strip.empty?
@options = options end
def email @options[:email] end
def token @options[:token] end
def identification @options[:identification] end
def billing_type @options[:billing_type] end
def billing_status @options[:billing_status] end
def message @options[:message] end
def exists? @options[:message] =~ /Account found/ end
def is_active? @options[:billing_status] == 'active' end
def is_seller? @options[:billing_type] == 'seller' || @options[:billing_type] == 'company' end
# other methods omitted end
![Page 26: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/26.jpg)
class PaymentGatewayWOP def initialize(options = {}) raise ArgumentError if options[:email].to_s.strip.empty? raise ArgumentError if options[:token].to_s.strip.empty?
@options = options end
def email @options[:email] end
def token @options[:token] end
def identification @options[:identification] end
def billing_type @options[:billing_type] end
# other methods omitted end
![Page 27: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/27.jpg)
class PaymentGatewayWOP def initialize(options = {}) raise ArgumentError if options[:email].to_s.strip.empty? raise ArgumentError if options[:token].to_s.strip.empty?
@options = options end
def email @options[:email] end
def token @options[:token] end
def identification @options[:identification] end
def billing_type @options[:billing_type] end
# other methods omitted end
![Page 28: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/28.jpg)
class PaymentGateway attr_reader :email, :token
def initialize(options = {}) @email = options.fetch(:email) @token = options.fetch(:token) @options = options end
def identification options[:identification] end
def billing_type options[:billing_type] end
# other public methods omitted
private
attr_reader :options
# other methods omitted end
![Page 29: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/29.jpg)
class PaymentGateway attr_reader :email, :token
def initialize(options = {}) @email = options.fetch(:email) @token = options.fetch(:token) @options = options end
def identification options[:identification] end
def billing_type options[:billing_type] end
# other public methods omitted
private
attr_reader :options
# other methods omitted end
![Page 30: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/30.jpg)
class PaymentGateway attr_reader :email, :token
def initialize(options = {}) @email = options.fetch(:email) @token = options.fetch(:token) @options = options end
[:identification,:billing_type, :billing_status, :message].each do |method| define_method(method) do options[method] end end
# other public methods omitted
private
attr_reader :options
# other methods omitted end
![Page 31: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/31.jpg)
class PaymentGateway attr_reader :email, :token
# constructor omitted
[:identification, :billing_type, :billing_status, :message].each do |method| define_method(method) do options[method] end end
def exists? message =~ /Account found/ end
def is_active? billing_status == 'active' end
def is_seller? billing_type == 'seller' || billing_type == 'company' end
private
attr_reader :options
# other methods omitted end
![Page 32: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/32.jpg)
class PaymentGateway attr_reader :email, :token
# other methods omitted
def exists? message =~ /Account found/ end
def active? billing_status == 'active' end
def seller? billing_type == 'seller' || billing_type == 'company' end
private
attr_reader :options
# other methods omitted end
![Page 33: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/33.jpg)
class PaymentGatewayWOP def initialize(options = {}) raise ArgumentError if options[:email].to_s.strip.empty? raise ArgumentError if options[:token].to_s.strip.empty?
@options = options end
def email @options[:email] end
def token @options[:token] end
def identification @options[:identification] end
def billing_type @options[:billing_type] end
def billing_status @options[:billing_status] end
def message @options[:message] end
def exists? @options[:message] =~ /Account found/ end
def is_active? @options[:billing_status] == 'active' end
def is_seller? @options[:billing_type] == 'seller' || @options[:billing_type] == 'company' end
# other methods omitted end
![Page 34: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/34.jpg)
class PaymentGateway attr_reader :email, :token
def initialize(options = {}) @email = options.fetch(:email) @token = options.fetch(:token) @options = options end
[:identification, :billing_type, :billing_status, :message].each do |method| define_method(method) do options[method] end end
def exists? message =~ /Account found/ end
def active? billing_status == 'active' end
def seller? billing_type == 'seller' || billing_type == 'company' end
private
attr_reader :options
# other methods end
![Page 35: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/35.jpg)
Naming issues
![Page 36: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/36.jpg)
class ImageWidgetImporter < WidgetImporter def import(img_element, row_number, position) return if img_element.blank? || img_element['src'].blank? create_image_widget(img_element, row_number, position) end
def import! @page.widgets.where(kind: 'text').each do |widget| content = Nokogiri::HTML(widget.content, nil, 'UTF-8') next unless has_internal_image?(content)
images = content.css('img').select do |image| internal_image?(image) end
images.each { |image| download_and_change_image_src(image) } widget.update_attribute(:content, content.inner_html) end end
private
def kind 'image' end
def create_image_widget(img_element, row_number, position) widget = create(row_number: row_number, position: position, remote_image_url: img_element['src']) source = (AppConfig.assets_host + widget.image.url) widget.content = @template_adapter.render_widget_content('image', alt: '', src: source) widget.save!
widget end
# Create widget_image to Text Widget def create_widget_image(url) widget_image = WidgetImage.new remote_image_url: url widget_image.site_id = @page.site.id widget_image.save!
widget_image end
# other methods omitted end
![Page 37: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/37.jpg)
class ImageWidgetImporter < WidgetImporter def import(img_element, row_number, position) return if img_element.blank? || img_element['src'].blank? create_image_widget(img_element, row_number, position) end
def import! @page.widgets.where(kind: 'text').each do |widget| content = Nokogiri::HTML(widget.content, nil, 'UTF-8') next unless has_internal_image?(content)
images = content.css('img').select do |image| internal_image?(image) end
images.each { |image| download_and_change_image_src(image) } widget.update_attribute(:content, content.inner_html) end end
private
def kind 'image' end
# other methods omitted end
![Page 38: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/38.jpg)
class ImageWidgetImporter < WidgetImporter def import(img_element, row_number, position) return if img_element.blank? || img_element['src'].blank? create_image_widget(img_element, row_number, position) end
def import! @page.widgets.where(kind: 'text').each do |widget| content = Nokogiri::HTML(widget.content, nil, 'UTF-8') next unless has_internal_image?(content)
images = content.css('img').select do |image| internal_image?(image) end
images.each { |image| download_and_change_image_src(image) } widget.update_attribute(:content, content.inner_html) end end
private
def kind 'image' end
# other methods omitted end
![Page 39: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/39.jpg)
class ImageWidgetImporter < WidgetImporter def import(img_element, row_number, position) return if img_element.blank? || img_element['src'].blank? create_image_widget(img_element, row_number, position) end
def import_from_text_widget @page.widgets.where(kind: 'text').each do |widget| content = Nokogiri::HTML(widget.content, nil, 'UTF-8') next unless has_internal_image?(content)
images = content.css('img').select do |image| internal_image?(image) end
images.each { |image| download_and_change_image_src(image) } widget.update_attribute(:content, content.inner_html) end end
private
def kind 'image' end
# other methods omitted end
![Page 40: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/40.jpg)
class ImageWidgetImporter < WidgetImporter # other public methods omitted
private
def create_image_widget(img_element, row_number, position) widget = create(row_number: row_number, position: position, remote_image_url: img_element['src']) source = (AppConfig.assets_host + widget.image.url) widget.content = @template_adapter.render_widget_content('image', alt: '', src: source) widget.save!
widget end
# Create image widget to text widget def create_widget_image(url) widget_image = WidgetImage.new remote_image_url: url widget_image.site_id = @page.site.id widget_image.save!
widget_image end
# other methods omitted end
![Page 41: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/41.jpg)
class ImageWidgetImporter < WidgetImporter # other public methods omitted
private
def create_image_widget(img_element, row_number, position) widget = create(row_number: row_number, position: position, remote_image_url: img_element['src']) source = (AppConfig.assets_host + widget.image.url) widget.content = @template_adapter.render_widget_content('image', alt: '', src: source) widget.save!
widget end
# Create image widget to text widget def create_widget_image(url) widget_image = WidgetImage.new remote_image_url: url widget_image.site_id = @page.site.id widget_image.save!
widget_image end
# other methods omitted end
![Page 42: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/42.jpg)
class ImageWidgetImporter < WidgetImporter # other public methods omitted
private
def create_image_widget(img_element, row_number, position) widget = create(row_number: row_number, position: position, remote_image_url: img_element['src']) source = (AppConfig.assets_host + widget.image.url) widget.content = @template_adapter.render_widget_content('image', alt: '', src: source) widget.save!
widget end
def create_image_widget_to_text_widget(url) widget_image = WidgetImage.new remote_image_url: url widget_image.site_id = @page.site.id widget_image.save!
widget_image end
# other methods omitted end
![Page 43: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/43.jpg)
OOP
![Page 44: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/44.jpg)
OOP Inheritance for the purpose
of code reuse
![Page 45: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/45.jpg)
class Installation::FromFeed < Installation::FromBase def install(args) # implementation omitted end end
class Installation::FromHosting < Installation::FromBase def install(args) # implementation omitted end end
class Installation::FromMigration < Installation::FromBase def install(args) # implementation omitted end end
![Page 46: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/46.jpg)
class Installation::FromBase include Rails::LabeledLog::Logging
attr_writer :customers_api, :installer, :mailer
def install(args) raise NotImplementedError end
def customers_api @customers_api ||= CustomersApi.new end
def installer @installer ||= Installation::Installer.new end
def mailer @mailer ||= Installation::Mailer.new end end
![Page 47: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/47.jpg)
How to fix it?
![Page 48: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/48.jpg)
module Installation::Infra include Rails::LabeledLog::Logging
attr_writer :customers_api, :installer, :mailer
def customers_api @customers_api ||= CustomersApi.new end
def installer @installer ||= Provisioner::Installation::Installer.new end
def mailer @mailer ||= Provisioner::Installation::Mailer.new end end
![Page 49: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/49.jpg)
class Installation::FromFeed include Installation::Infra
def install(args) # implementation omitted end end
class Installation::FromHosting include Installation::Infra
def install(args) # implementation omitted end end
class Installation::FromMigration include Installation::Infra
def install(args) # implementation omitted end end
![Page 50: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/50.jpg)
OOP Inheritance mistake
![Page 51: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/51.jpg)
DNS A quick introduction
![Page 52: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/52.jpg)
![Page 53: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/53.jpg)
class WsDns attr_reader :host, :user, :timeout
def initialize(options) @host = options[:host] @user = options[:user] @timeout = options.fetch(:timeout, 5) end
def create_entry(options) # implementation omitted end
def delete_entry(options) # implementation omitted end
def get_entry(options) # implementation omitted end
def has_entry?(options) # implementation omitted end
# other methods to DNS zone end
![Page 54: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/54.jpg)
class CnameWsDns attr_reader :ws_dns, :zone, :content
def initialize(options) @ws_dns = WsDns.new(options) @zone = options[:zone] @content = options.fetch(:content, zone) end
def create_entry(subdomain) ws_dns.create_entry(type: type, content: content, name: subdomain, zone: zone) end
def delete_entry(subdomain) ws_dns.delete_entry(type: type, content: content, name: subdomain, zone: zone) end
def has_entry?(subdomain) ws_dns.has_entry?(type: type, name: subdomain, zone: zone) end
protected
def type 'CNAME' end end
![Page 55: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/55.jpg)
class AWsDns < CnameWsDns protected
def type 'A' end end
![Page 56: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/56.jpg)
class TxtWsDns < CnameWsDns protected
def type 'TXT' end end
![Page 57: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/57.jpg)
![Page 58: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/58.jpg)
How to fix it?
![Page 59: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/59.jpg)
![Page 60: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/60.jpg)
OOP Parent knowing your children
![Page 61: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/61.jpg)
class TransactionResponseParser attr_reader :xml
def initialize(xml) @xml = xml end
def parse # omitted implementation end
private
# specific transaction methods omitted end
![Page 62: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/62.jpg)
class ResponseParser attr_reader :xml
def initialize(xml) @xml = xml end
def parse # omitted implementation end
# omitted protected methods end
![Page 63: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/63.jpg)
class TransactionResponseParser < ResponseParser
private
# specific transaction methods omitted end
class AccountResponseParser < ResponseParser
private
# specific account methods omitted end
![Page 64: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/64.jpg)
class ResponseParser def self.transaction?(xml) xml.include?('<transaction>') end
def self.get_parser(xml) ResponseParser.transaction?(xml) ? TransactionResponseParser.new(xml) : AccountResponseParser.new(xml) end
def initialize(xml) @xml = xml end
def parse # omitted implementation
end end
![Page 65: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/65.jpg)
How to fix it?
![Page 66: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/66.jpg)
module ResponseParserFactory def self.build(xml) if xml.include?('<transaction>') TransactionResponseParser.new(xml) else AccountResponseParser.new(xml) end end end
![Page 67: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/67.jpg)
The worst class
![Page 68: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/68.jpg)
class DomainChecker extend Memoist
DOMAIN_REGEXP = /^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)+$/
attr_accessor :domain
def initialize(args = {}) @domain = args[:domain] end
def check_new check_existing end
def status if dns_adapter.ns_locaweb? a_entry_locaweb = dns_adapter.a_entry_locaweb if a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites return :ok elsif a_entry_locaweb == false return :unavailable else return :already_using end end
if domain_checker_result["error"] == "generic" return :generic_error end
if domain_checker_result["error"] == "unsupported_tld" return :unsupported_tld end
if domain_checker_result["available"] return :register end
if dns_adapter.a_value == AppConfig.ip_lvs_criador_de_sites return :ok else return :config_dns end end memoize :status
def available_domain_by_user(user) if domain.blank? return {valid: false, notice: :invalid, message: :blank} end
if !domain.match(DOMAIN_REGEXP) return {valid: false, notice: :invalid, message: :invalid} end
if forbidden_domain? return {valid: false, notice: :invalid, message: :forbidden_domain} end
if Domain.where(address: domain).count > 0 current_domain = Domain.where(address: domain).first if (current_domain.site.account.users.include?(user) rescue false) return {valid: false, notice: :invalid, message: :already_using} else return {valid: false, notice: :invalid, message: :already_exists} end end
if !domain_checker_result["valid"] && domain_checker_result["error"] != "unsupported_tld" return {valid: false, notice: :invalid, message: :invalid} end
if domain_checker_result["error"] == "unsupported_tld" return {valid: true, notice: :unsupported_tld} end
if domain_checker_result["available"] return {valid: true, notice: :register} end
if domain_checker_result["customer_login"].blank? return {valid: true, notice: :config_dns} end
if domain_checker_result["customer_login"].downcase == user.username.downcase Rails.logger.info "user owner domain"
if dns_adapter.a_entry_locaweb? if dns_adapter.a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites_old return {valid: true, notice: :old_csit} else return {valid: true, notice: :already_using} end else Rails.logger.info "Without entry A" return {valid: true, notice: :owner_domain} end else Rails.logger.info "user does not owner domain" return {valid: false, notice: :not_owner} end end
def details { entry_a: dns_adapter.a_value, entry_ns: dns_adapter.ns_value, entry_cname: dns_adapter.cname_value }.merge(domain_checker_result) end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check end
private
def dns_adapter DnsAdapter.new(domain: CGI.escape(domain)) end memoize :dns_adapter
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
def get_token WsAuthentication.new(AppConfig.wsauthentication.url).authenticate(AppConfig.wsauthentication.user, AppConfig.wsauthentication.pass) end memoize :get_token
def external_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/external_check" begin JSON(http_get(url)) rescue RestClient::NotImplemented return { "valid" => false, "available" => false, "error" => 'unsupported_tld' } rescue RestClient::InternalServerError => exception Rails.logger.error "[ERROR] GET #{url}: #{exception.message}\n" \ "Response: #{exception.http_body}" return { "valid" => false, "available" => false, "error" => 'generic' } rescue => exception Rails.logger.error exception.print raise exception end end memoize :external_check
def internal_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/internal_check" JSON(http_get(url)) end memoize :internal_check
def forbidden_domain? uri = "#{AppConfig.registro_domain_url}/domain/#{domain}/check"
begin response = JSON(CasSaas::CasRestClient.new.get(uri))
!response["valid"] rescue => e Rails.logger.info e.message true end end memoize :forbidden_domain?
def http_get(url, headers = {}) Rails.logger.info "chamando GET #{url}, headers: #{headers}" response = RestClient.get url, headers Rails.logger.info "response #{response}" response end end
![Page 69: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/69.jpg)
Business scenario for DomainChecker class
![Page 70: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/70.jpg)
class DomainChecker # ...
def check_new # omitted implementation end
def status # omitted implementation end memoize :status
def available_domain_by_user(user) # omitted implementation end
def details # omitted implementation end
def check_existing # omitted implementation end
# ... end
![Page 71: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/71.jpg)
class DomainChecker extend Memoist
attr_accessor :domain
def initialize(args = {}) @domain = args[:domain] end
# ... end
![Page 72: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/72.jpg)
class DomainChecker extend Memoist
# ...
def check_new check_existing end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check
end
# ... end
![Page 73: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/73.jpg)
class DomainChecker extend Memoist
attr_accessor :domain
def initialize(args = {}) @domain = args[:domain] end
# ... end
![Page 74: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/74.jpg)
def status if dns_adapter.ns_locaweb? a_entry_locaweb = dns_adapter.a_entry_locaweb if a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites return :ok elsif a_entry_locaweb == false return :unavailable else return :already_using end end
if domain_checker_result["error"] == "generic" return :generic_error end
if domain_checker_result["error"] == "unsupported_tld" return :unsupported_tld end
if domain_checker_result["available"] return :register end
if dns_adapter.a_value == AppConfig.ip_lvs_criador_de_sites return :ok else return :config_dns end end memoize :status
![Page 75: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/75.jpg)
def dns_adapter DnsAdapter.new(domain: CGI.escape(domain)) end memoize :dns_adapter
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
![Page 76: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/76.jpg)
def get_token WsAuthentication.new(AppConfig.wsauthentication.url).authenticate(AppConfig.wsauthentication.user, AppConfig.wsauthentication.pass)
end memoize :get_token
def external_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/external_check" begin JSON(http_get(url)) rescue RestClient::NotImplemented return { "valid" => false, "available" => false, "error" => 'unsupported_tld' } rescue RestClient::InternalServerError => exception Rails.logger.error "[ERROR] GET #{url}: #{exception.message}\n" \ "Response: #{exception.http_body}" return { "valid" => false, "available" => false, "error" => 'generic' } rescue => exception Rails.logger.error exception.print raise exception end end memoize :external_check
![Page 77: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/77.jpg)
def internal_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/internal_check" JSON(http_get(url)) end memoize :internal_check
def forbidden_domain? uri = "#{AppConfig.registro_domain_url}/domain/#{domain}/check"
begin response = JSON(CasSaas::CasRestClient.new.get(uri)) !response["valid"] rescue => e Rails.logger.info e.message true end end memoize :forbidden_domain?
![Page 78: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/78.jpg)
class DomainChecker extend Memoist
attr_accessor :domain
def initialize(args = {}) @domain = args[:domain] end
# ... end
![Page 79: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/79.jpg)
def status if dns_adapter.ns_locaweb? a_entry_locaweb = dns_adapter.a_entry_locaweb if a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites return :ok elsif a_entry_locaweb == false return :unavailable else return :already_using end end
if domain_checker_result["error"] == "generic" return :generic_error end
if domain_checker_result["error"] == "unsupported_tld" return :unsupported_tld end
if domain_checker_result["available"] return :register end
if dns_adapter.a_value == AppConfig.ip_lvs_criador_de_sites return :ok else return :config_dns end end memoize :status
![Page 80: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/80.jpg)
def available_domain_by_user(user) if domain.blank? return {valid: false, notice: :invalid, message: :blank} end
if !domain.match(DOMAIN_REGEXP) return {valid: false, notice: :invalid, message: :invalid} end
if forbidden_domain? return {valid: false, notice: :invalid, message: :forbidden_domain} end
if Domain.where(address: domain).count > 0 current_domain = Domain.where(address: domain).first if (current_domain.site.account.users.include?(user) rescue false) return {valid: false, notice: :invalid, message: :already_using} else return {valid: false, notice: :invalid, message: :already_exists} end end
if !domain_checker_result["valid"] && domain_checker_result["error"] != "unsupported_tld" return {valid: false, notice: :invalid, message: :invalid} end
if domain_checker_result["error"] == "unsupported_tld" return {valid: true, notice: :unsupported_tld} end
if domain_checker_result["available"] return {valid: true, notice: :register} end
if domain_checker_result["customer_login"].blank? return {valid: true, notice: :config_dns} end
if domain_checker_result["customer_login"].downcase == user.username.downcase Rails.logger.info "user owner domain"
if dns_adapter.a_entry_locaweb? if dns_adapter.a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites_old return {valid: true, notice: :old_csit} else return {valid: true, notice: :already_using} end else Rails.logger.info "Without entry A" return {valid: true, notice: :owner_domain} end else Rails.logger.info "user does not owner domain" return {valid: false, notice: :not_owner} end end
![Page 81: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/81.jpg)
def available_domain_by_user(user) if domain.blank? return {valid: false, notice: :invalid, message: :blank} end
if !domain.match(DOMAIN_REGEXP) return {valid: false, notice: :invalid, message: :invalid} end
if forbidden_domain? return {valid: false, notice: :invalid, message: :forbidden_domain} end
if Domain.where(address: domain).count > 0 current_domain = Domain.where(address: domain).first if (current_domain.site.account.users.include?(user) rescue false) return {valid: false, notice: :invalid, message: :already_using} else return {valid: false, notice: :invalid, message: :already_exists} end end
# ... end
![Page 82: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/82.jpg)
def available_domain_by_user(user) if domain.blank? return {valid: false, notice: :invalid, message: :blank} end
if !domain.match(DOMAIN_REGEXP) return {valid: false, notice: :invalid, message: :invalid} end
if forbidden_domain? return {valid: false, notice: :invalid, message: :forbidden_domain} end
if Domain.where(address: domain).count > 0 current_domain = Domain.where(address: domain).first if (current_domain.site.account.users.include?(user) rescue false) return {valid: false, notice: :invalid, message: :already_using} else return {valid: false, notice: :invalid, message: :already_exists} end end
# ... end
![Page 83: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/83.jpg)
def available_domain_by_user(user) if domain.blank? return {valid: false, notice: :invalid, message: :blank} end
if !domain.match(DOMAIN_REGEXP) return {valid: false, notice: :invalid, message: :invalid} end
if forbidden_domain? return {valid: false, notice: :invalid, message: :forbidden_domain} end
if Domain.where(address: domain).count > 0 current_domain = Domain.where(address: domain).first if (current_domain.site.account.users.include?(user) rescue false) return {valid: false, notice: :invalid, message: :already_using} else return {valid: false, notice: :invalid, message: :already_exists} end end
# ... end
![Page 84: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/84.jpg)
def available_domain_by_user(user) # …
if domain_checker_result["customer_login"].downcase == user.username.downcase Rails.logger.info "user owner domain"
if dns_adapter.a_entry_locaweb? if dns_adapter.a_entry_locaweb == AppConfig.ip_lvs_criador_de_sites_old return {valid: true, notice: :old_csit} else return {valid: true, notice: :already_using} end else Rails.logger.info "Without entry A" return {valid: true, notice: :owner_domain} end else Rails.logger.info "user does not owner domain" return {valid: false, notice: :not_owner} end end
![Page 85: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/85.jpg)
def available_domain_by_user(user) # …
if !domain_checker_result["valid"] && domain_checker_result["error"] != "unsupported_tld" return {valid: false, notice: :invalid, message: :invalid} end
if domain_checker_result["error"] == "unsupported_tld" return {valid: true, notice: :unsupported_tld} end
if domain_checker_result["available"] return {valid: true, notice: :register} end
if domain_checker_result["customer_login"].blank? return {valid: true, notice: :config_dns} end
# … end
![Page 86: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/86.jpg)
class DomainChecker # ...
def check_new check_existing end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check end
private
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
# ... end
![Page 87: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/87.jpg)
class DomainChecker # ...
def check_new check_existing end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check end
private
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
# ... end
![Page 88: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/88.jpg)
def external_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/external_check" begin JSON(http_get(url)) rescue RestClient::NotImplemented return { "valid" => false, "available" => false, "error" => 'unsupported_tld' } rescue RestClient::InternalServerError => exception Rails.logger.error "[ERROR] GET #{url}: #{exception.message}\n" \ "Response: #{exception.http_body}" return { "valid" => false, "available" => false, "error" => 'generic' } rescue => exception Rails.logger.error exception.print raise exception end end memoize :external_check
def internal_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/internal_check" JSON(http_get(url)) end memoize :internal_check
![Page 89: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/89.jpg)
class DomainChecker # ...
def http_get(url, headers = {}) Rails.logger.info "chamando GET #{url}, headers: #{headers}" response = RestClient.get url, headers Rails.logger.info "response #{response}" response end end
![Page 90: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/90.jpg)
class DomainChecker # ...
def check_new check_existing end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check end
private
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
# ... end
![Page 91: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/91.jpg)
def external_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/external_check" begin JSON(http_get(url)) rescue RestClient::NotImplemented return { "valid" => false, "available" => false, "error" => 'unsupported_tld' } rescue RestClient::InternalServerError => exception Rails.logger.error "[ERROR] GET #{url}: #{exception.message}\n" \ "Response: #{exception.http_body}" return { "valid" => false, "available" => false, "error" => 'generic' } rescue => exception Rails.logger.error exception.print raise exception end end memoize :external_check
def internal_check url = "#{AppConfig.registro_service_url}/domain_availability/#{domain}/internal_check" JSON(http_get(url)) end memoize :internal_check
![Page 92: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/92.jpg)
class DomainChecker # ...
def check_new check_existing end
def check_existing return external_check if external_check["error"] == "generic" return external_check if external_check["error"] == "invalid_domain" return external_check if external_check["error"] == "unsupported_tld" return external_check if external_check["available"] return external_check if internal_check["available"] internal_check end
private
def domain_checker_result domain_checker = DomainChecker.new(domain: CGI.escape(domain)) domain_checker_result = domain_checker.check_new end memoize :domain_checker_result
# ... end
![Page 93: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/93.jpg)
class DomainChecker # ...
def details { entry_a: dns_adapter.a_value, entry_ns: dns_adapter.ns_value, entry_cname: dns_adapter.cname_value }.merge(domain_checker_result) end
private
def dns_adapter DnsAdapter.new(domain: CGI.escape(domain)) end memoize :dns_adapter
#... end
![Page 94: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/94.jpg)
class DomainChecker # ... private
def get_token WsAuthentication.new(AppConfig.wsauthentication.url).authenticate(AppConfig.wsauthentication.user, AppConfig.wsauthentication.pass)
end memoize :get_token end
![Page 95: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/95.jpg)
DomainChecker class problems
![Page 96: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/96.jpg)
Long class
DomainChecker class problems
![Page 97: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/97.jpg)
Constructor with hash parameter, but only use
one key of the hash.
DomainChecker class problems
![Page 98: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/98.jpg)
A method implementation that only call a private
method without parameters
DomainChecker class problems
![Page 99: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/99.jpg)
Memoize (hell) dependency: memoized methods used
like variables.
DomainChecker class problems
![Page 100: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/100.jpg)
A lot ifs: ifs with ifs with else with if with else
(it’s hard until to explain)
DomainChecker class problems
![Page 101: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/101.jpg)
Code hard to understand
(internal x external checks)
DomainChecker class problems
![Page 102: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/102.jpg)
An unused private method
DomainChecker class problems
![Page 103: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/103.jpg)
Instance method creates another instance of itself
DomainChecker class problems
![Page 104: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/104.jpg)
• Many responsibilities:
✴ Validate domain format
✴ Validate domain logic
✴ Format return to use in view
✴ Do HTTP requests
✴ Parse HTTP responses
DomainChecker class problems
![Page 105: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/105.jpg)
DomainChecker class problems introduces new patterns and principles
![Page 106: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/106.jpg)
Write-only codeOnce write no one can read
DomainChecker class introducesnew patterns and principles
![Page 107: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/107.jpg)
Close Closed PrincipleClosed for modification,
more closed for extension.
DomainChecker class introducesnew patterns and principles
![Page 108: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/108.jpg)
Inception PatternWhere an instance of a class creates
a new instance of itself and aggregates the new instance state to your state
DomainChecker class introducesnew patterns and principles
![Page 109: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/109.jpg)
DomainChecker class probably is the worst Ruby class
I've seen in my life
![Page 110: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/110.jpg)
How did we fix it?
![Page 111: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/111.jpg)
![Page 112: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/112.jpg)
Why is WOP applied?
![Page 113: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/113.jpg)
Lack of knowledge
Causes of WOP
![Page 114: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/114.jpg)
Immaturity in software development
Causes of WOP
![Page 115: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/115.jpg)
No collaborative environment
Causes of WOP
![Page 116: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/116.jpg)
No coaching
Causes of WOP
![Page 117: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/117.jpg)
Tight deadlines
Causes of WOP
![Page 118: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/118.jpg)
Why simplify if you can complicate?
Causes of WOP
![Page 119: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/119.jpg)
To use "cool things" because they are cool, even
if they are not a solution.
Causes of WOP
![Page 120: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/120.jpg)
Some mysteries of the human mind
(that we can't explain)
Causes of WOP
![Page 121: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/121.jpg)
How to avoid WOP?
![Page 122: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/122.jpg)
Read a lot
How to avoid WOP?
![Page 123: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/123.jpg)
How to avoid WOP?
![Page 124: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/124.jpg)
But do not learn only Ruby
How to avoid WOP?
![Page 125: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/125.jpg)
How to avoid WOP?
![Page 126: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/126.jpg)
Use code review
How to avoid WOP?
![Page 127: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/127.jpg)
Read code from others programmers
How to avoid WOP?
![Page 128: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/128.jpg)
Write code yourself can read in the future
How to avoid WOP?
![Page 129: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/129.jpg)
Participate of open source projects: contributing, discussing, reading.
How to avoid WOP?
![Page 130: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/130.jpg)
Do coaching of less experienced developers (teaching is a good way to learn too)
How to avoid WOP?
![Page 131: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/131.jpg)
Do not write code for you: write it to the application,
to the team.
How to avoid WOP?
![Page 132: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/132.jpg)
Exchange experiences, ask.
How to avoid WOP?
![Page 133: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/133.jpg)
Use pair programming (not 100% IMHO)
How to avoid WOP?
![Page 134: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/134.jpg)
Learn from your mistakes and others
How to avoid WOP?
![Page 135: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/135.jpg)
Face bad code as an opportunity to get better
How to avoid WOP?
![Page 136: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/136.jpg)
Do not face bad code with complaints or
making fun of the authors
How to avoid WOP?
![Page 137: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/137.jpg)
This funny code causes waste of time, resources
and money
How to avoid WOP?
![Page 138: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/138.jpg)
Instead, show the authors of bad code the right way
How to avoid WOP?
![Page 139: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/139.jpg)
Show them the Ruby way
How to avoid WOP?
![Page 140: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/140.jpg)
Thank you! I hope you enjoyed
@Prodis
![Page 141: The worst Ruby codes I’ve seen in my life - RubyKaigi 2015](https://reader034.vdocuments.net/reader034/viewer/2022051502/5873229c1a28ab673e8b7c7b/html5/thumbnails/141.jpg)
The worst Ruby codes I’ve seen in my life
RubyKaigi 2015
@Prodis