Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rediscovering OOP in Rails World

Rediscovering OOP in Rails World

A quick talk about application design, methods to improve your software. Evento Stack U, in Quito, Ecuador.

Filipe Costa

February 22, 2014
Tweet

More Decks by Filipe Costa

Other Decks in Programming

Transcript

  1. class Dealer < ActiveRecord::Base default_scope order('lower(name)') ! belongs_to :provider, conditions:

    { mobile: false } belongs_to :mobile_provider, class_name: 'Provider', conditions: { mobile: true } ! belongs_to :ftp_user, :dependent => :delete has_many :inventory_uploads, through: :ftp_user ! accepts_nested_attributes_for :ftp_user ! validates_associated :ftp_user ! has_many :inventories, :dependent => :delete_all ! before_destroy :purge_inventories ! has_many :error_log_entries ! # All cars (also from old inventory uploads) associated with this dealer. # Almost always you'll be interested in cars from most recent inventory via #recent_cars has_many :cars, through: :inventories ! belongs_to :autosocial_group ! has_many :performance_logs, :dependent => :delete_all, :class_name => 'CampaignPerformanceLog' ! has_many :dealer_ad_templates, order: "ad_template_type DESC", dependent: :destroy has_many :ad_templates, through: :dealer_ad_templates ! has_many :ad_groups, :dependent => :delete_all has_many :ads, :through => :ad_groups has_many :keywords, :through => :ad_groups has_many :group_negatives, :through => :ad_groups has_many :competitors, dependent: :destroy has_many :regions, dependent: :destroy has_many :dealer_makes, dependent: :destroy has_many :makes, through: :dealer_makes has_many :models, through: :dealer_makes has_one :dynamic_campaign, class_name: 'AdWordsCampaign', dependent: :destroy, conditions: { campaign_type: "Dynamic" } has_one :managed_campaign, class_name: 'AdWordsCampaign', dependent: :destroy, conditions: { campaign_type: "Managed" } has_many :ad_words_campaigns ! Is this familiar to you?
  2. return if purging? update_attribute(:purge_queued_at, Time.now) Resque.enqueue(ProcessDealerPurge, self.id) end ! def

    enqueue_destroy return if deleted? update_attribute(:deleted, true) Resque.enqueue(ProcessDealerDestroy, self.id) end ! def purging? not purge_queued_at.nil? end ! def self.find_dealers(search_query) dealers = self.scoped dealers = dealers.merge(self.where('name ILIKE ?', "%#{search_query}%")) unless search_query.blank? dealers end ! def import_locations Haystack::AdWords::LocationsImporter.new(self).import end ! def google_campaign_id dynamic_campaign.try(:remote_campaign_id) end ! delegate :display_url, :destination_url, :mobile_bid_adjustment, :mobile_destination_url, to: :dynamic_campaign ! def models_titles_grouped_by_makes models.order(:title).each_with_object({}) do |model, result| result[model.make_title] ||= [] result[model.make_title] << model.title end end ! private ! def assign_templates Haystack::AdTemplates::Generator.new.assign_default_templates_for(self) end ! def adwords_account_missing? has_google_ads? && account_id.blank? end ! end Is this familiar to you?
  3. S O L I D ingle Responsibility pen/Closed iskov Substituition

    nterface Segregation ependency Inversion
  4. S O L I D ingle Responsibility pen/Closed iskov Substituition

    nterface Segregation ependency Inversion
  5. class Invetory < ActiveRecord::Base def self.process file = download_file CSV.readlines(file)

    do |line| description, price = line self.create(description: description, price: price.to_d) end end ! private def download_file Net::HTTP.start("www.my-super-server.com") do |http| response = http.get("/path/to/file.csv") open("my-local-file.csv", "wb") do |file| file.write(response.body) end end end end
  6. class Car < ActiveRecord::Base def self.process file = SuperDownloader.new.download_file CSV.foreach(file)

    do |line| description, price = line self.create(description: description, price: price) end end end ! class SuperDownloader def download_file # Download from interwebs end end !
  7. class Car < ActiveRecord::Base def self.process file = SuperDownloader.new.download_file CSV.foreach(file)

    do |line| description, price = line self.create(description: description, price: price) end end end ! class SuperDownloader def download_file # Download from interwebs end end !
  8. class Car < ActiveRecord::Base def self.process(downloader = SuperDownloader.new) file =

    downloader.download_file CSV.foreach(file) do |line| description, price = line self.create(description: description, price: price) end end end ! class SuperDownloader def download_file # Download from interwebs end end ! class S3Downloader < SuperDownloader def download_file # Now we're cool and user S3 to store our inventories end end !
  9. class FtpDownloader < GeneralDownloader def download_file # Here we do

    all the FTP connection to download our file end end ! class S3Downloader < GeneralDownloader def download_file # Now we're cool and user S3 to store our inventories end end ! class GeneralDownloader def download_file # get any url and download, more like wget end end
  10. class User < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable,

    :validatable end class Admin < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :trackable, :validatable end
  11. public class RemoteControl { public RemoteControl(TV tv) { this.tv =

    tv; } ! public void pressPowerButton() { if (this.tv.isOn()) { this.tv.off(); System.out.println("turning off!"); } else { this.tv.on(); System.out.println("turning on!"); } } }
  12. public class RemoteControl { public RemoteControl(TurnableOnOff obj) { this.obj =

    obj; } ! public void pressPowerButton() { if (this.obj.isOn()) { this.obj.off(); System.out.println("turning off!"); } else { this.obj.on(); System.out.println("turning on!"); } } } ! public interface TurnableOnOff { public void off(); public boolean isOn(); public void on(); } ! public class TV implements TurnableOnOff { // ... }
  13. class RemoteControl def initialize(turnable_on_off) @obj = turnable_on_off end ! def

    press_power_button obj.on? ? obj.off : obj.on end end ! class TV def on? ; end def on ; end def off ; end end ! class Radio def on? ; end def on ; end def off ; end end