Created
January 27, 2012 13:12
-
-
Save aalin/1688705 to your computer and use it in GitHub Desktop.
Any thoughts?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This is not the best example, but imagine a Rails project with lots of complex logic and methods and stuff... | |
| # Imagine that Base is an 500 line ActiveRecord model... :) | |
| require 'rubygems' | |
| require 'active_support/core_ext' | |
| Customer = Struct.new(:id, :first_name, :last_name, :company_name) | |
| ## Implementation directly in the class | |
| # Pros: | |
| # * Easy to find the implementation of all methods | |
| # | |
| # Cons: | |
| # * Could easily turn into a huge, messy file. | |
| class Customer1 < Customer | |
| def name | |
| if company_name.present? | |
| if joined_names.present? | |
| "#{ company_name } (#{ joined_names })" | |
| else | |
| company_name | |
| end | |
| elsif joined_names.present? | |
| joined_names | |
| else | |
| generic_name | |
| end | |
| end | |
| def id_and_name | |
| "#{id}. #{name}" | |
| end | |
| private | |
| def joined_names | |
| [first_name, last_name].reject(&:blank?).join(" ").presence | |
| end | |
| def generic_name | |
| "#{ self.class.name } ##{ id }" | |
| end | |
| end | |
| ## Including modules | |
| # Pros: | |
| # * Small file. | |
| # Cons: | |
| # * Adds an unknown number of methods to the class that might collide with existing method names, | |
| # and you have no clue what's going on. And you go crazy when you try to find why things are broken | |
| # and where they are defined... | |
| module Naming | |
| def name | |
| if company_name.present? | |
| if joined_names.present? | |
| "#{ company_name } (#{ joined_names })" | |
| else | |
| company_name | |
| end | |
| elsif joined_names.present? | |
| joined_names | |
| else | |
| generic_name | |
| end | |
| end | |
| def id_and_name | |
| "#{id}. #{name}" | |
| end | |
| private | |
| def joined_names | |
| [first_name, last_name].reject(&:blank?).join(" ").presence | |
| end | |
| def generic_name | |
| "#{ self.class.name } ##{ id }" | |
| end | |
| end | |
| class Customer2 < Customer | |
| include Naming | |
| end | |
| ## Implementation in another class | |
| # Pros: | |
| # * Puts all logic in another class | |
| # * You can use the same logic with different objects | |
| # * Easy to jump to the classes (with gf in Vim) | |
| # * Easy to test separately | |
| # Cons: | |
| # * Help me out on this one! | |
| class CustomerNaming < Struct.new(:customer) | |
| def name | |
| if company_name.present? | |
| if joined_names.present? | |
| "#{ company_name } (#{ joined_names })" | |
| else | |
| company_name | |
| end | |
| elsif joined_names.present? | |
| joined_names | |
| else | |
| generic_name | |
| end | |
| end | |
| def id_and_name | |
| "#{id}. #{name}" | |
| end | |
| private | |
| def method_missing(method, *args) | |
| customer.send(method, *args) | |
| end | |
| def joined_names | |
| [first_name, last_name].reject(&:blank?).join(" ").presence | |
| end | |
| def generic_name | |
| "#{ self.class.name } ##{ id }" | |
| end | |
| end | |
| class Customer3 < Customer | |
| def naming | |
| CustomerNaming.new(self) | |
| end | |
| end | |
| ## Class with helper method | |
| # Pros: | |
| # * Same as the previous, but shorter. | |
| # * Easy to see which classes are being used. | |
| # Cons: | |
| # * HELP!!! | |
| class Customer | |
| def self.extension(methods_and_classes) | |
| methods_and_classes.each do |method, klass| | |
| define_method(method) { klass.new(self) } | |
| end | |
| end | |
| end | |
| class Customer4 < Customer | |
| extension :naming => CustomerNaming | |
| delegate :name, :id_and_name, :to => :naming | |
| end | |
| ## Usage | |
| puts Customer1.new(123, "First", "One").id_and_name | |
| puts Customer2.new(123, "Second", "Two").id_and_name | |
| puts Customer3.new(123, "Third", "Three").naming.id_and_name | |
| puts Customer4.new(123, "Fourth", "Four").name | |
| puts Customer4.new(123, "Fourth", "Four").id_and_name | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The last example fleshed out: https://gist.github.com/1900793