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

Building Extractable Libraries in Rails

Building Extractable Libraries in Rails

Talk given at LVRUG about some conventions for making /lib more agreeable to library extraction.

Patrick Robertson

May 03, 2012
Tweet

More Decks by Patrick Robertson

Other Decks in Technology

Transcript

  1. HELLO THERE! I’ m @patricksroberts; I push bits at @iorahealth

    and herd cats at @bostonrb. Thursday, May 3, 12
  2. # config/application.rb # Custom directories with classes and modules you

    want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) Thursday, May 3, 12
  3. # config/application.rb # Custom directories with classes and modules you

    want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) Thursday, May 3, 12
  4. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  5. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  6. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  7. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  8. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  9. # lib/twitter_wrangler/configuration.rb module TwitterWrangler class Configuration attr_accessor :oauth_key def initialize

    self.oauth_key = nil end end class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) if block_given? end end Thursday, May 3, 12
  10. Chaos is hard to undo on a large library; starting

    with order is easy. At any moment that code in /lib might need to be a gem. Thursday, May 3, 12
  11. # lib/twitter_wrangler/roles/tweeting_patient.rb module TwitterWrangler::Roles::TweetingPatient def bmi_twitter_message “Today my BMI is

    #{body_mass_index} and I’m #{percent_of_body_mass_index_goal} from my goal of #{body_mass_index_goal}!” end end Thursday, May 3, 12
  12. # lib/twitter_wrangler/roles/tweeting_patient.rb module TwitterWrangler::Roles::TweetingPatient def bmi_twitter_message “Today my BMI is

    #{body_mass_index} and I’m #{percent_of_body_mass_index_goal} from my goal of #{body_mass_index_goal}!” end end Thursday, May 3, 12
  13. # lib/twitter_wrangler/roles/tweeting_patient.rb module TwitterWrangler::Roles::TweetingPatient def bmi_twitter_message “Today my BMI is

    #{body_mass_index} and I’m #{percent_of_body_mass_index_goal} from my goal of #{body_mass_index_goal}!” end end Thursday, May 3, 12
  14. # lib/twitter_wrangler/support/fake_patient.rb class FakePatient def body_mass_index;27;end def percent_of_body_mass_index_goal;”95%”;end def body_mass_index_goal;25;end

    end # spec/twitter_wrangler/roles/tweeting_patient_spec.rb describe TweetingPatient do let(:patient) { FakePatient.new } before { FakePatient.extend TweetingPatient } it ‘asserts some fantastic things’ do #GLORIOUS SPECS end end Thursday, May 3, 12
  15. # spec/twitter_wrangler/roles/tweeting_patient_spec.rb describe TweetingPatient do let(:patient) { mock() } before

    do patient.stubs({body_mass_index: 27, percent_of_body_mass_index_goal: “95%” body_mass_index_goal: 25 }) patient.extend TweetingPatient end it ‘asserts some fantastic things’ do #GLORIOUS SPECS end end Thursday, May 3, 12
  16. # lib/twitter_wrangler/Contexts/BMITwitterUpdate.rb module TwitterWrangler::Contexts class BMITwitterUpdate attr_accessor: patient def initialize(patient)

    @patient = patient @patient.extend TweetingPatient end def call TwitterWranglerQueue.add @patient.bmi_twitter_message end end end Thursday, May 3, 12
  17. # lib/twitter_wrangler/Contexts/BMITwitterUpdate.rb module TwitterWrangler::Contexts class BMITwitterUpdate attr_accessor: patient def initialize(patient)

    @patient = patient @patient.extend TweetingPatient end def call TwitterWranglerQueue.add @patient.bmi_twitter_message end end end Thursday, May 3, 12
  18. # lib/twitter_wrangler/Contexts/BMITwitterUpdate.rb module TwitterWrangler::Contexts class BMITwitterUpdate attr_accessor: patient def initialize(patient)

    @patient = patient @patient.extend TweetingPatient end def call TwitterWranglerQueue.add @patient.bmi_twitter_message end end end Thursday, May 3, 12
  19. # lib/twitter_wrangler/Contexts/BMITwitterUpdate.rb module TwitterWrangler::Contexts class BMITwitterUpdate attr_accessor: patient def initialize(patient)

    @patient = patient @patient.extend TweetingPatient end def call TwitterWranglerQueue.add @patient.bmi_twitter_message end end end Thursday, May 3, 12
  20. # lib/twitter_wrangler/Contexts/BMITwitterUpdate.rb module TwitterWrangler::Contexts class BMITwitterUpdate attr_accessor: patient def initialize(patient)

    @patient = patient @patient.extend TweetingPatient end def call TwitterWranglerQueue.add @patient.bmi_twitter_message end end end Thursday, May 3, 12
  21. # spec/models/patient_bmi_observer_spec.rb describe PatientBMIObserver do let(:bmi_update) { mock() } before

    do BMITwitterUpdate.stubs(:new).returns bmi_update bmi_update.stubs :call end it ‘sends a twitter update on mah BMI’ do # expect #call to have been called once end end Thursday, May 3, 12
  22. # spec/models/patient_bmi_observer_spec.rb describe PatientBMIObserver do let(:bmi_update) { mock() } before

    do BMITwitterUpdate.stubs(:new).returns bmi_update bmi_update.stubs :call end it ‘sends a twitter update on mah BMI’ do # expect #call to have been called once end end Thursday, May 3, 12
  23. Web App Library body mass index tweet called Authorization Twitter

    message Authentication Queueing User sees tweet Thursday, May 3, 12
  24. Big Win: Freedom to implement with Google +. (If we

    were Google employeees) Thursday, May 3, 12
  25. Treat /lib with love and respect. Use common sense composition

    to focus your domain models. Thursday, May 3, 12