Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Upcoming SlideShare
Loading in...5
×
 

Reusable Ruby • Rt 9 Ruby Group • Jun 2012

on

  • 717 views

 

Statistics

Views

Total Views
717
Views on SlideShare
717
Embed Views
0

Actions

Likes
0
Downloads
1
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Reusable Ruby • Rt 9 Ruby Group • Jun 2012 Reusable Ruby • Rt 9 Ruby Group • Jun 2012 Presentation Transcript

  • REUSABLE RUBY ROUTE 9 RUBY GROUP – JUNE 20, 2012 BLAKE CARLSON BLAKE@COIN-OPERATED.NET • @SKINANDBONESGITHUB.COM/SKINANDBONES • LINKEDIN.COM/IN/BLAKECARLSON
  • WHY GO REUSABLE? sloth love reusable ruby‣ D-R-Y‣ Maintainability‣ Leads to better solutions‣ Make large projects adaptable to change‣ Your co-workers will love you‣ Make gems, share code
  • OUR REUSABLE RUBY TOOLBOX* * this list is not everything, okay‣ Inheritance‣ Modules‣ Composition‣ Gems & Bundler
  • STAY CLASSY RUBY‣ Class inheritance‣ ActiveRecord, ActionController, etc.‣ Meant for things that can be instantiated or inherited‣ Sorry, NO Interfaces or Abstract Classes in Ruby (sad face?)
  • WE ♥ MODULES‣ Namespaces‣ Inject a bucket o’ instance methods into something else‣ The included callback‣ ActiveSupport::Concern‣ Testing‣ Pitfalls
  • MODULES: NAMESPACES # Namespaces module Foo class Widget # ... one thing ... end end module Bar class Widget # ... something else ... end end x = Foo::Widget.new y = Bar::Widget.new
  • MODULES: METHOD INJECTIONmodule Sluggable def generate_slug(str) str.to_s.strip.downcase.gsub(/[^a-z0-9s]/, ).gsub(/s+/, -) endendclass Post < ActiveRecord::Base include Sluggable before_validation :update_slug private def update_slug self.slug = generate_slug(title) endend# Note (1): this is a super naive solution# Note (2): check out the stringex gem for things like String#to_url.
  • MODULES: THE BASICSLet’s make generate_slug available to all AR modelsPut this code into a file like lib/sluggable.rb ... module Sluggable # ... end ActiveRecord::Base.send :include, SluggableSomewhere, like in config/initializers ... require sluggable
  • MODULES: COMMON IDIOMS module Sluggable module ClassMethods def find_by_slug(str) # ... end end module InstanceMethods def generate_slug(str) # ... end private def update_slug # ... end end def self.included(base) base.extend ClassMethods base.send :include, InstanceMethods base.before_validation :update_slug end end
  • ACTIVESUPPORT::CONCERN Bring THE PRETTY require active_support/concern module Sluggable extend ActiveSupport::Concern included do before_validation :update_slug end module ClassMethods def find_by_slug(str) # ... end end private def update_slug # ... end endhttps://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb
  • ACTIVESUPPORT::CONCERN What about module dependencies? module Foo def self.included(base) base.class_eval do def self.method_injected_by_foo # ... end end end end module Bar def self.included(base) base.method_injected_by_foo end end class Host include Foo # We need to include this dependency for Bar include Bar # Bar is the module that Host really needs endhttps://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb
  • ACTIVESUPPORT::CONCERN require active_support/concern module Foo extend ActiveSupport::Concern included do class_eval do def self.method_injected_by_foo # ... end end end end module Bar extend ActiveSupport::Concern include Foo included do self.method_injected_by_foo end end class Host include Bar # works, Bar takes care now of its dependencies endhttps://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb
  • MODULES: TESTINGTest just the module, stub aggressively, use a Dummy class # sluggable_test.rb require spec_helper class Dummy include ActiveModel::Validations extend ActiveModel::Callbacks include Sluggable define_model_callbacks :validation attr_accessor :title, :slug def initialize(title) self.title = title end end describe Sluggable do let(:dummy) { Dummy.new(a special title) } it "should update the slug when validated" do dummy.valid? dummy.slug.should eq(a-special-title) end end
  • MODULES: THE DARK SIDE Classes that use too many modules can become a handful. 1. Which module defined which method? 2. What methods are defined in the class? 3. Method name collisions when including modules 4. You can’t reference a modularized entity, you must pass around the object that contains it.
  • MODULES: THE DARK SIDE‣ Over-engineering / pre-awesome-ization‣ Which module defined which method?‣ What methods are defined in the class?‣ Method name collisions when including modules‣ You can’t reference a modularized entity, you must pass around the object that contains it.
  • COMPOSITION:WRANGLE THOSE MODULES‣ A.K.A. aggregation‣ A class is composed of several other classes, use delegation
  • Example: Composition class Avatar class Person < ActiveRecord::Base attr_reader :master # ... def initialize(master) def avatar @master = master @avatar ||= Avatar.new(self) end end def exists? def avatar_exists? master.has_avatar? avatar.exists? end end def create(file) end master.update_attribute :has_avatar, true # thumbnail and install the given avatar end def destroy master.update_attribute :has_avatar, false # delete avatar file end # etc. endhttp://37signals.com/svn/posts/1553-models-vs-modules
  • GEMS & BUNDLER‣ NO FEAR, make private gems to share code between projects‣ Use Bundler to bootstrap gem creation https://github.com/radar/guides/blob/master/ gem-development.md‣ Use :git in your Gemfile to use gems directly from git repositories http://gembundler.com/git.html
  • THE END
  • RESOURCES‣ http://www.fakingfantastic.com/2010/09/20/concerning-yourself-with-active- support-concern/‣ http://yehudakatz.com/2009/11/12/better-ruby-idioms/‣ http://metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby/‣ http://37signals.com/svn/posts/1553-models-vs-modules‣ http://andrzejonsoftware.blogspot.com/2011/01/code-reuse-in-ruby-why- composition-is.html‣ https://github.com/rails/rails/blob/master/activesupport/lib/active_support/ concern.rb‣ https://github.com/rails/rails/tree/master/activemodel