├── README.md ├── extract-class ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── extract-method ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── form-template-method ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── hide-delegate ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── introduce-assertion ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── introduce-null-object ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── move-field ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── parameterize-method ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── preserve-whole-object ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── pull-up-method ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── rename-method ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-array-with-object ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-method-with-method-object ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-temp-with-query ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-type-code-with-module-extension ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-type-code-with-polymorphism ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb ├── replace-type-code-with-state-strategy ├── Rakefile ├── lib │ ├── after.rb │ └── before.rb └── test │ └── test.rb └── separate-query-from-modifier ├── .DS_Store ├── Rakefile ├── lib ├── after.rb └── before.rb └── test └── test.rb /README.md: -------------------------------------------------------------------------------- 1 | # Object-Oriented Design and Refactoring Patterns in Ruby 2 | 3 | This project contains all the examples used in the respective course at Tuts+ 4 | Premium. Each example contains: 5 | 6 | * Two code sample files, _before_ and _after_ refactoring; 7 | * A test suite; 8 | * A `Rakefile` with a test task. 9 | 10 | - To run the tests against the code sample _before_ refactoring, run 11 | `BEFORE=1 rake test`; 12 | - To run the tests against the code sample _before_ refactoring, run `rake 13 | test`; 14 | 15 | ## Course outline 16 | 17 | ### Object-oriented design 18 | 19 | Before you start refactoring, it's important to grasp the basic but most 20 | fundamental aspects of object oriented software development. These principles 21 | will allow you to solve problems in an efficient, cost effective and 22 | change aware fashion. 23 | 24 | ### Code Smells 25 | 26 | Each item in the following list matches a code smell and contains a list of 27 | possible refactoring patterns to solve it. 28 | 29 | * **Duplicate code** 30 | 31 | - Extract Method 32 | - Pull Up Method 33 | - Form Template Method 34 | 35 | * **Long method** 36 | 37 | - Extract Method 38 | - Replace Temp with Query / Replace Temp with Chain 39 | - Introduce Parameter Object / Preserve Whole Object 40 | - Replace Method with Method Object 41 | 42 | * **Feature envy** 43 | 44 | - Extract Method + Move Method 45 | 46 | * **Data clumps** 47 | 48 | - Extract Class 49 | - Introduce Parameter Object / Preserve Whole Object 50 | 51 | * **Comments** 52 | 53 | - Rename Method 54 | - Extract Method 55 | - Introduce Assertion 56 | 57 | * **Divergent change** 58 | 59 | - Extract Class 60 | - Inline Class 61 | - Move Method + Move Field 62 | 63 | * **Primitive Obsession** 64 | 65 | - Replace Type Code with Polymorphism / Module Extension / State|Strategy 66 | - Replace Array with Object 67 | - Introduce Parameter Object 68 | 69 | * **Conditionals (if/else, case/when)** 70 | 71 | - Introduce Null Object 72 | - Replace Type Code with Polymorphism 73 | - Extract Method + Move Method 74 | 75 | ### Refactoring Patterns 76 | 77 | * Extract Class 78 | * Extract Method 79 | * Form Template Method 80 | * Hide Delegate 81 | * Introduce Assertion 82 | * Introduce Null Object 83 | * Separate Query from Modifier 84 | * Move Field 85 | * Parameterize Method 86 | * Preserve Whole Object 87 | * Pull Up Method 88 | * Rename Method 89 | * Replace Array with Object 90 | * Replace Method with Method Object 91 | * Replace Temp with Query 92 | * Replace Type Code with Module Extension 93 | * Replace Type Code with Polymorphism 94 | * Replace Type Code with State/Strategy 95 | -------------------------------------------------------------------------------- /extract-class/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /extract-class/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Student 2 | 3 | attr_reader :terms 4 | 5 | def initialize 6 | @terms = [ 7 | Term.new(:first), 8 | Term.new(:second), 9 | Term.new(:third) 10 | ] 11 | end 12 | 13 | def set_all_grades_to grade 14 | terms.each { |term| term.set_all_grades_to(grade) } 15 | end 16 | 17 | def first_term_grade 18 | term(:first).grade 19 | end 20 | 21 | def second_term_grade 22 | term(:second).grade 23 | end 24 | 25 | def third_term_grade 26 | term(:third).grade 27 | end 28 | 29 | def term reference 30 | terms.find { |term| term.name == reference } 31 | end 32 | end 33 | 34 | class Term 35 | 36 | attr_reader :name, :assiduity, :test, :behavior 37 | 38 | def initialize name 39 | @name = name 40 | @assiduity = 0 41 | @test = 0 42 | @behavior = 0 43 | end 44 | 45 | def set_all_grades_to grade 46 | @assiduity = grade 47 | @test = grade 48 | @behavior = grade 49 | end 50 | 51 | def grade 52 | (assiduity + test + behavior) / 3 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /extract-class/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Student 2 | attr_accessor :first_term_assiduity, :first_term_test, :first_term_behavior 3 | attr_accessor :second_term_assiduity, :second_term_test, :second_term_behavior 4 | attr_accessor :third_term_assiduity, :third_term_test, :third_term_behavior 5 | 6 | def set_all_grades_to grade 7 | %w(first second third).each do |which_term| 8 | %w(assiduity test behavior).each do |criteria| 9 | send "#{which_term}_term_#{criteria}=".to_sym, grade 10 | end 11 | end 12 | end 13 | 14 | def first_term_grade 15 | (first_term_assiduity + first_term_test + first_term_behavior) / 3 16 | end 17 | 18 | def second_term_grade 19 | (second_term_assiduity + second_term_test + second_term_behavior) / 3 20 | end 21 | 22 | def third_term_grade 23 | (third_term_assiduity + third_term_test + third_term_behavior) / 3 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /extract-class/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Student do 8 | it "has a grade for all three terms" do 9 | student = Student.new 10 | student.set_all_grades_to 10 11 | 12 | student.first_term_grade.must_equal 10 13 | student.second_term_grade.must_equal 10 14 | student.third_term_grade.must_equal 10 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /extract-method/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /extract-method/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | 3 | attr_reader :title, :date 4 | 5 | def initialize title, date 6 | @title = title 7 | @date = date 8 | end 9 | 10 | def body 11 | <<-RETURN 12 | RANDOM TEXT Ladyship it daughter securing procured or am moreover mr. Put 13 | sir she exercise vicinity cheerful wondered. Continual say suspicion 14 | provision you neglected sir curiosity unwilling. 15 | RETURN 16 | 17 | end 18 | 19 | def condensed_format 20 | metadata 21 | end 22 | 23 | def full_format 24 | return_string = metadata 25 | return_string << "--\n#{body}" 26 | 27 | return_string 28 | end 29 | 30 | private 31 | 32 | def metadata 33 | return_string = '' 34 | return_string << "Title: #{title}" 35 | return_string << "Date: #{date.strftime "%Y/%m/%d"}" 36 | 37 | return_string 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /extract-method/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | 3 | attr_reader :title, :date 4 | 5 | def initialize title, date 6 | @title = title 7 | @date = date 8 | end 9 | 10 | def body 11 | <<-RETURN 12 | RANDOM TEXT Ladyship it daughter securing procured or am moreover mr. Put 13 | sir she exercise vicinity cheerful wondered. Continual say suspicion 14 | provision you neglected sir curiosity unwilling. 15 | RETURN 16 | 17 | end 18 | 19 | def condensed_format 20 | return_string = '' 21 | return_string << "Title: #{title}" 22 | return_string << "Date: #{date.strftime "%Y/%m/%d"}" 23 | 24 | return_string 25 | end 26 | 27 | def full_format 28 | return_string = '' 29 | return_string << "Title: #{title}" 30 | return_string << "Date: #{date.strftime "%Y/%m/%d"}" 31 | return_string << "--\n#{body}" 32 | 33 | return_string 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /extract-method/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Post do 8 | before do 9 | @date = Time.new(2014,02,28) 10 | @post = Post.new("Fragmented Class", @date) 11 | end 12 | 13 | describe "when requested a condensed format" do 14 | 15 | it "shows the post's title" do 16 | @post.condensed_format.must_include "Fragmented Class" 17 | end 18 | 19 | it "shows the post's date" do 20 | @post.condensed_format.must_include "2014/02/28" 21 | end 22 | 23 | end 24 | 25 | describe "when requested a full format" do 26 | 27 | it "shows the post's title" do 28 | @post.full_format.must_include "Fragmented Class" 29 | end 30 | 31 | it "shows the post's date" do 32 | @post.full_format.must_include "2014/02/28" 33 | end 34 | 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /form-template-method/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /form-template-method/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Ticket 2 | attr_reader :price 3 | 4 | def initialize 5 | @price = 2.0 6 | end 7 | 8 | def price *args 9 | @price * discount 10 | end 11 | 12 | def discount 13 | 1 14 | end 15 | 16 | end 17 | 18 | class SeniorTicket < Ticket 19 | def discount 20 | 0.75 21 | end 22 | end 23 | 24 | class JuniorTicket < Ticket 25 | def discount 26 | 0.5 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /form-template-method/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Ticket 2 | attr_reader :price 3 | 4 | def initialize 5 | @price = 2.0 6 | end 7 | 8 | end 9 | 10 | class SeniorTicket < Ticket 11 | def price 12 | @price * 0.75 13 | end 14 | end 15 | 16 | class JuniorTicket < Ticket 17 | def price 18 | @price * 0.5 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /form-template-method/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Ticket do 8 | it "has a calculated price" do 9 | Ticket.new.price.must_equal 2.0 10 | end 11 | 12 | it "costs less if a senior" do 13 | SeniorTicket.new.price.must_equal 1.5 14 | end 15 | 16 | it "costs less if a junior" do 17 | JuniorTicket.new.price.must_equal 1.0 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /hide-delegate/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /hide-delegate/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Client 2 | attr_reader :clerk 3 | 4 | def initialize clerk 5 | @clerk = clerk 6 | end 7 | end 8 | 9 | class Clerk 10 | attr_reader :department 11 | 12 | def initialize (department) 13 | @department = department 14 | end 15 | 16 | def manager 17 | department.manager 18 | end 19 | end 20 | 21 | class Manager 22 | attr_accessor :department 23 | end 24 | 25 | class Department 26 | attr_reader :manager 27 | def initialize manager 28 | @manager = manager 29 | 30 | manager.department = self 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /hide-delegate/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Client 2 | attr_reader :department, :clerk 3 | 4 | def initialize department, clerk 5 | @department = department 6 | @clerk = clerk 7 | end 8 | end 9 | 10 | class Manager 11 | attr_accessor :department 12 | end 13 | 14 | class Clerk 15 | attr_reader :department 16 | 17 | def initialize(department) 18 | @department = department 19 | end 20 | 21 | def manager 22 | department.manager 23 | end 24 | end 25 | 26 | class Department 27 | attr_reader :manager 28 | def initialize manager 29 | @manager = manager 30 | 31 | manager.department = self 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /hide-delegate/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Client do 8 | let(:manager) { Manager.new } 9 | let(:department) { Department.new(manager) } 10 | let(:clerk) { Clerk.new(department) } 11 | 12 | if ENV["BEFORE"] 13 | it "wants to know about the manager through a department" do 14 | client = Client.new(department, clerk) 15 | 16 | client.department.manager.wont_be_nil 17 | end 18 | 19 | else 20 | it "should rather be guided by a clerk to access that info" do 21 | client = Client.new(clerk) 22 | 23 | client.clerk.manager.wont_be_nil 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /introduce-assertion/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /introduce-assertion/lib/after.rb: -------------------------------------------------------------------------------- 1 | module Assertions 2 | def assert &block 3 | raise ArgumentError unless block.call 4 | end 5 | end 6 | 7 | class SquareRootCalculator 8 | extend Assertions 9 | 10 | def self.calculate number 11 | assert { number > 0 } 12 | Math.sqrt number 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /introduce-assertion/lib/before.rb: -------------------------------------------------------------------------------- 1 | class SquareRootCalculator 2 | class << self 3 | def calculate number 4 | if number > 0 5 | Math.sqrt number 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /introduce-assertion/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe SquareRootCalculator do 8 | it "calculates a square root" do 9 | SquareRootCalculator.calculate(9).must_equal 3 10 | end 11 | 12 | if ENV["BEFORE"] 13 | it "doesn't calculate a negative number's square root" do 14 | SquareRootCalculator.calculate(-9).must_be_nil 15 | end 16 | else # AFTER 17 | it "doesn't calculate a negative number's square root" do 18 | proc { SquareRootCalculator.calculate(-9) }.must_raise ArgumentError 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /introduce-null-object/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /introduce-null-object/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | attr_reader :id, :title, :body, :created_at 3 | def initialize id, title, body, created_at 4 | @id = id 5 | @title = title 6 | @body = body 7 | @created_at = created_at 8 | @published = false 9 | end 10 | 11 | def self.find_and_publish id 12 | # database operation to retrieve data. We'll simulate it for now. 13 | post = POSTS.find { |post| post.id == id } || NullPost.new 14 | post.publish 15 | end 16 | 17 | def publish 18 | @published = true 19 | end 20 | 21 | end 22 | 23 | class NullPost 24 | def publish 25 | # noop 26 | end 27 | end 28 | 29 | POSTS = [ 30 | Post.new( 31 | 1, 32 | "Introduce Null Object Pattern", 33 | "Post body should be here", 34 | Time.new(2013,01,25) 35 | ) 36 | ] 37 | 38 | -------------------------------------------------------------------------------- /introduce-null-object/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | attr_reader :id, :title, :body, :created_at 3 | def initialize id, title, body, created_at 4 | @id = id 5 | @title = title 6 | @body = body 7 | @created_at = created_at 8 | @published = false 9 | end 10 | 11 | def self.find_and_publish id 12 | # database operation to retrieve data. We'll simulate it for now. 13 | post = POSTS.find { |post| post.id == id } 14 | post.publish unless post.nil? 15 | end 16 | 17 | def publish 18 | @published = true 19 | end 20 | 21 | end 22 | 23 | POSTS = [ 24 | Post.new( 25 | 1, 26 | "Introduce Null Object Pattern", 27 | "Post body should be here", 28 | Time.new(2013,01,25) 29 | ) 30 | ] 31 | 32 | -------------------------------------------------------------------------------- /introduce-null-object/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Post do 8 | it "is publishable" do 9 | Post.find_and_publish(1).must_equal true 10 | end 11 | 12 | it "does nothing if post is not found" do 13 | Post.find_and_publish(0) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /move-field/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /move-field/lib/after.rb: -------------------------------------------------------------------------------- 1 | PHONE_CODES = { 2 | en_gb: "44", 3 | pt: "351" 4 | } 5 | 6 | class Phone 7 | attr_reader :number, :locale 8 | 9 | def initialize number, locale 10 | @number = number 11 | @locale = locale 12 | end 13 | 14 | def to_s 15 | PHONE_CODES[locale] + " " + number 16 | end 17 | end 18 | 19 | class Person 20 | attr_reader :phone 21 | 22 | def initialize(locale: :en_gb, phone: nil) 23 | @phone = Phone.new phone, locale 24 | end 25 | 26 | def full_phone 27 | ["+", phone].join 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /move-field/lib/before.rb: -------------------------------------------------------------------------------- 1 | PHONE_CODES = { 2 | en_gb: "44", 3 | pt: "351" 4 | } 5 | 6 | class Phone 7 | attr_reader :number 8 | 9 | def initialize number 10 | @number = number 11 | end 12 | 13 | def to_s 14 | number 15 | end 16 | end 17 | 18 | class Person 19 | attr_reader :locale, :phone 20 | 21 | def initialize(locale: :en_gb, phone: nil) 22 | @locale = locale 23 | @phone = Phone.new phone 24 | end 25 | 26 | def full_phone 27 | ["+", PHONE_CODES[locale], " ", phone].join 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /move-field/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Person do 8 | it "has a phone number" do 9 | person = Person.new(locale: :pt, phone: "555-0342") 10 | person.full_phone.must_equal "+351 555-0342" 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /parameterize-method/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /parameterize-method/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Student 2 | GRADES = { 3 | first: 10, 4 | second: 11, 5 | third: 12 6 | } 7 | 8 | def term_grade index 9 | GRADES[index] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /parameterize-method/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Student 2 | def first_term_grade 3 | 10 4 | end 5 | 6 | def second_term_grade 7 | 11 8 | end 9 | 10 | def third_term_grade 11 | 12 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /parameterize-method/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Student do 8 | if ENV["BEFORE"] 9 | 10 | it "has a first grade" do 11 | Student.new.first_term_grade.must_equal 10 12 | end 13 | it "has a second grade" do 14 | Student.new.second_term_grade.must_equal 11 15 | end 16 | it "has a third grade" do 17 | Student.new.third_term_grade.must_equal 12 18 | end 19 | 20 | else # AFTER 21 | 22 | it "has a first grade" do 23 | Student.new.term_grade(:first).must_equal 10 24 | end 25 | it "has a second grade" do 26 | Student.new.term_grade(:second).must_equal 11 27 | end 28 | it "has a third grade" do 29 | Student.new.term_grade(:third).must_equal 12 30 | end 31 | 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /preserve-whole-object/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /preserve-whole-object/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Item 2 | attr_reader :name, :price, :date 3 | 4 | def initialize name, price, date 5 | @name = name 6 | @price = price 7 | @date = date 8 | end 9 | end 10 | 11 | class Store 12 | def initialize 13 | @items = [] 14 | end 15 | 16 | def contain? item 17 | ! find(item).nil? 18 | end 19 | 20 | def <<(item) 21 | @items << item 22 | end 23 | 24 | def find item 25 | @items.find { |i| i.name == item.name && 26 | i.price == item.price && 27 | i.date == item.date } 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /preserve-whole-object/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Item 2 | attr_reader :name, :price, :date 3 | 4 | def initialize name, price, date 5 | @name = name 6 | @price = price 7 | @date = date 8 | end 9 | end 10 | 11 | class Store 12 | def initialize 13 | @items = [] 14 | end 15 | 16 | def contain? name, price, date 17 | ! find(name,price,date).nil? 18 | end 19 | 20 | def <<(item) 21 | @items << item 22 | end 23 | 24 | def find name, price, date 25 | @items.find { |item| item.name == name && 26 | item.price == price && 27 | item.date == date } 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /preserve-whole-object/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Store do 8 | let(:item) { Item.new "Macbook Pro", 1299.0, Time.new } 9 | 10 | subject { Store.new.tap { |store| store << item } } 11 | 12 | if ENV["BEFORE"] 13 | it "finds an item in the store" do 14 | subject.contain?(item.name,item.price,item.date).must_equal true 15 | end 16 | else 17 | it "finds an item in the store" do 18 | subject.contain?(item).must_equal true 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /pull-up-method/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /pull-up-method/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Person 2 | attr_reader :first_name, :last_name 3 | 4 | def initialize first_name, last_name 5 | @first_name = first_name 6 | @last_name = last_name 7 | end 8 | 9 | def full_name 10 | first_name + " " + last_name 11 | end 12 | end 13 | 14 | class MalePerson < Person 15 | def gender 16 | "M" 17 | end 18 | end 19 | 20 | class FemalePerson < Person 21 | def gender 22 | "F" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /pull-up-method/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Person 2 | attr_reader :first_name, :last_name 3 | 4 | def initialize first_name, last_name 5 | @first_name = first_name 6 | @last_name = last_name 7 | end 8 | 9 | end 10 | 11 | class MalePerson < Person 12 | def full_name 13 | first_name + " " + last_name 14 | end 15 | 16 | def gender 17 | "M" 18 | end 19 | end 20 | 21 | class FemalePerson < Person 22 | def full_name 23 | first_name + " " + last_name 24 | end 25 | 26 | def gender 27 | "F" 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /pull-up-method/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe MalePerson do 8 | it "has a full name" do 9 | MalePerson.new("John", "Smith").full_name.must_equal "John Smith" 10 | end 11 | end 12 | 13 | describe MalePerson do 14 | it "has a full name" do 15 | FemalePerson.new("Michelle", "Smith").full_name.must_equal "Michelle Smith" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /rename-method/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /rename-method/lib/after.rb: -------------------------------------------------------------------------------- 1 | class UserService 2 | USERNAME = "josemota" 3 | PASSWORD = "secret" 4 | 5 | class << self 6 | def sign_in username, password 7 | username == USERNAME && password == PASSWORD 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /rename-method/lib/before.rb: -------------------------------------------------------------------------------- 1 | class UserService 2 | USERNAME = "josemota" 3 | PASSWORD = "secret" 4 | 5 | class << self 6 | def login username, password 7 | username == USERNAME && password == PASSWORD 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /rename-method/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe UserService do 8 | it "can log in" do 9 | if ENV["BEFORE"] 10 | assert UserService.login("josemota", "secret") 11 | else 12 | assert UserService.sign_in("josemota", "secret") 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /replace-array-with-object/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-array-with-object/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Cart 2 | attr_reader :products 3 | 4 | def initialize products 5 | @products = products.map { |product| Product.new *product } 6 | end 7 | 8 | def total 9 | products.inject(0) { |sum, product| sum + product.price } 10 | end 11 | 12 | end 13 | 14 | class Product 15 | attr_reader :name, :color, :price 16 | 17 | def initialize name, color, price 18 | @name = name 19 | @color = color 20 | @price = price 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /replace-array-with-object/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Cart 2 | attr_reader :products 3 | 4 | def initialize products 5 | @products = products 6 | end 7 | 8 | def total 9 | products.inject(0) { |sum, product| 10 | sum + product[2] 11 | } 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /replace-array-with-object/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Cart do 8 | it "has a list of items" do 9 | Cart.new([ 10 | [ "Sweater" , "Pink" , 5.0 ], 11 | [ "Trousers" , "Blue" , 8.0 ], 12 | [ "Golf Club" , "Gray" , 12.0 ] 13 | ]).total.must_equal 25.0 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /replace-method-with-method-object/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-method-with-method-object/lib/after.rb: -------------------------------------------------------------------------------- 1 | class TaxAlgorithm 2 | def initialize(income: nil, expenses: 0, type: :dependent_worker) 3 | @income = income 4 | @expenses = expenses 5 | @type = type 6 | 7 | @return_value = 0 8 | @number_of_people_under_roof = 1 9 | end 10 | 11 | def compute 12 | process_type 13 | process_number_of_people 14 | process_income_expense_difference 15 | deduct_expenses 16 | end 17 | 18 | def process_type 19 | if @type == :dependent_worker 20 | @return_value += @income * 0.02 21 | else 22 | @return_value += @income * 0.04 23 | end 24 | end 25 | 26 | def process_number_of_people 27 | @return_value *= 1.10 if @number_of_people_under_roof > 2 28 | end 29 | 30 | def process_income_expense_difference 31 | @return_value += @expenses * 0.05 if @income - @expenses > @income * 0.05 32 | end 33 | 34 | def deduct_expenses 35 | @return_value -= @expenses * 0.30 36 | end 37 | end 38 | 39 | class TaxSimulator 40 | def initialize person 41 | @person = person 42 | end 43 | 44 | def simulate_return(income: nil, expenses: 0, type: :dependent_worker) 45 | TaxAlgorithm.new(income: income, expenses: expenses, type: type).compute 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /replace-method-with-method-object/lib/before.rb: -------------------------------------------------------------------------------- 1 | class TaxSimulator 2 | def initialize person 3 | @person = person 4 | end 5 | 6 | def simulate_return(income: nil, expenses: 0, type: :dependent_worker) 7 | return_value = 0 8 | number_of_people_under_roof = 1 9 | 10 | if type == :dependent_worker 11 | return_value += income * 0.02 12 | else 13 | return_value += income * 0.04 14 | end 15 | 16 | if number_of_people_under_roof > 2 17 | return_value *= 1.10 18 | end 19 | 20 | if income - expenses > income * 0.05 21 | return_value += expenses * 0.05 22 | end 23 | 24 | return_value -= expenses * 0.30 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /replace-method-with-method-object/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe TaxSimulator do 8 | it "simulates tax returns" do 9 | TaxSimulator.new("Jose Mota").simulate_return( 10 | income: 10000, 11 | expenses: 300, 12 | type: :independent_worker 13 | ).must_equal 325.0 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /replace-temp-with-query/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-temp-with-query/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Cuboid 2 | attr_reader :length, :width, :height 3 | def initialize length, width, height 4 | @length = length 5 | @width = width 6 | @height = height 7 | end 8 | 9 | def volume 10 | area * height 11 | end 12 | 13 | def area 14 | length * width 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /replace-temp-with-query/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Cuboid 2 | attr_reader :length, :width, :height 3 | def initialize length, width, height 4 | @length = length 5 | @width = width 6 | @height = height 7 | end 8 | 9 | def volume 10 | area = length * width 11 | area * height 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /replace-temp-with-query/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Cuboid do 8 | it "has a volume" do 9 | Cuboid.new(2,3,4).volume.must_equal 24 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /replace-type-code-with-module-extension/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-type-code-with-module-extension/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Employee 2 | def initialize(type: :regular) 3 | @type = type 4 | end 5 | 6 | def base_salary 7 | 500.0 8 | end 9 | 10 | def salary 11 | base_salary + bonus 12 | end 13 | 14 | def self.build(type: :regular) 15 | instance = new 16 | instance.extend const_get(type.capitalize) 17 | end 18 | 19 | end 20 | 21 | module Regular 22 | def bonus 23 | 0 24 | end 25 | end 26 | 27 | module Manager 28 | def bonus 29 | 800 30 | end 31 | end 32 | 33 | module Boss 34 | def bonus 35 | 1500 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /replace-type-code-with-module-extension/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Employee 2 | def initialize(type: :regular) 3 | @type = type 4 | end 5 | 6 | def base_salary 7 | 500.0 8 | end 9 | 10 | def salary 11 | base_salary + bonus 12 | end 13 | 14 | private 15 | 16 | def self.build(type: :regular) 17 | new type: type 18 | end 19 | 20 | def bonus 21 | value = case @type 22 | when :regular then 0 23 | when :boss then 1500.0 24 | when :manager then 800.0 25 | end 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /replace-type-code-with-module-extension/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Employee do 8 | describe "a regular one" do 9 | it "has a salary" do 10 | Employee.build.salary.must_equal 500.0 11 | end 12 | end 13 | 14 | describe "a boss" do 15 | it "has a salary" do 16 | Employee.build(type: :boss).salary.must_equal 2000.0 17 | end 18 | end 19 | describe "a manager" do 20 | it "has a salary" do 21 | Employee.build(type: :manager).salary.must_equal 1300.0 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /replace-type-code-with-polymorphism/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-type-code-with-polymorphism/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Employee 2 | def initialize(type: :regular) 3 | @type = type 4 | end 5 | 6 | def base_salary 7 | 500.0 8 | end 9 | 10 | def salary 11 | base_salary + bonus 12 | end 13 | 14 | def self.build(type: :employee) 15 | const_get(type.capitalize).new 16 | end 17 | 18 | def bonus 19 | 0 20 | end 21 | end 22 | 23 | class Manager < Employee 24 | def bonus 25 | 800 26 | end 27 | end 28 | 29 | class Boss < Employee 30 | def bonus 31 | 1500 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /replace-type-code-with-polymorphism/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Employee 2 | def initialize(type: :regular) 3 | @type = type 4 | end 5 | 6 | def base_salary 7 | 500.0 8 | end 9 | 10 | def salary 11 | base_salary + bonus 12 | end 13 | 14 | def self.build(type: :regular) 15 | new type: type 16 | end 17 | 18 | private 19 | 20 | def bonus 21 | value = case @type 22 | when :regular then 0 23 | when :boss then 1500.0 24 | when :manager then 800.0 25 | end 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /replace-type-code-with-polymorphism/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/spec' 2 | require 'minitest/autorun' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Employee do 8 | describe "a regular one" do 9 | it "has a salary" do 10 | Employee.build.salary.must_equal 500.0 11 | end 12 | end 13 | 14 | describe "a boss" do 15 | it "has a salary" do 16 | Employee.build(type: :boss).salary.must_equal 2000.0 17 | end 18 | end 19 | describe "a manager" do 20 | it "has a salary" do 21 | Employee.build(type: :manager).salary.must_equal 1300.0 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /replace-type-code-with-state-strategy/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /replace-type-code-with-state-strategy/lib/after.rb: -------------------------------------------------------------------------------- 1 | STRATEGIES = { 2 | :password => 'Auth::Password', 3 | :public_key => 'Auth::PublicKey', 4 | :oauth => 'Auth::OAuth' 5 | } 6 | 7 | class User 8 | attr_reader :name, :type, :options 9 | 10 | def initialize name, type, options = {} 11 | @name = name 12 | @type = type 13 | @options = options 14 | 15 | @strategy = Class.const_get(STRATEGIES[type]).new(self) 16 | end 17 | 18 | def auth! options 19 | @strategy.auth? options 20 | end 21 | 22 | class << self 23 | def login name, options = {} 24 | user = USERS.find { |u| u.name == name } 25 | 26 | user.auth! options 27 | end 28 | end 29 | end 30 | 31 | module Auth 32 | class Password 33 | def initialize user 34 | @user = user 35 | end 36 | 37 | def auth? options 38 | @user.options[:password] == options[:password] 39 | end 40 | end 41 | 42 | class PublicKey 43 | def initialize user 44 | @user = user 45 | end 46 | 47 | def auth? options 48 | # Do some logic 49 | true 50 | end 51 | end 52 | 53 | class OAuth 54 | def initialize user 55 | @user = user 56 | end 57 | 58 | def auth? options 59 | # Do some logic 60 | true 61 | end 62 | 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /replace-type-code-with-state-strategy/lib/before.rb: -------------------------------------------------------------------------------- 1 | class User 2 | attr_reader :name, :type, :options 3 | 4 | def initialize name, type, options = {} 5 | @name = name 6 | @type = type 7 | @options = options 8 | end 9 | 10 | def public_key_matches? 11 | # Do some logic 12 | true 13 | end 14 | 15 | def oauth_authenticates? 16 | # Do some logic 17 | true 18 | end 19 | 20 | class << self 21 | def login name, options = {} 22 | user = USERS.find { |u| u.name == name } 23 | 24 | case user.type 25 | when :password 26 | return user.options[:password] == options[:password] 27 | when :public_key 28 | return user.public_key_matches? 29 | when :oauth 30 | return user.oauth_authenticates? 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /replace-type-code-with-state-strategy/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | require 'minitest/pride' 4 | 5 | require 'before' if ENV["BEFORE"] 6 | require 'after' unless ENV["BEFORE"] 7 | 8 | USERS = [ 9 | User.new("Regular user", :password, password: "secret"), 10 | User.new("Public key user", :public_key, key_location: "assets/id_rsa.pub"), 11 | User.new("OAuth user", :oauth, provider: :twitter) 12 | ] 13 | 14 | describe User do 15 | it "can log in by default via user/pass combo" do 16 | assert User.login("Regular user", password: "secret") 17 | end 18 | 19 | it "can log in via a public key" do 20 | assert User.login("Public key user") 21 | end 22 | 23 | it "can log in via oauth" do 24 | assert User.login("OAuth user") 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /separate-query-from-modifier/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/ruby-refactoring/6364b7ac9548a22e7423d34b188e443b4e0b379c/separate-query-from-modifier/.DS_Store -------------------------------------------------------------------------------- /separate-query-from-modifier/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*test.rb' 5 | end 6 | -------------------------------------------------------------------------------- /separate-query-from-modifier/lib/after.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | attr_reader :id, :title, :body, :created_at 3 | def initialize id, title, body, created_at 4 | @id = id 5 | @title = title 6 | @body = body 7 | @created_at = created_at 8 | @published = false 9 | end 10 | 11 | def self.find id 12 | # database operation to retrieve data. We'll simulate it for now. 13 | post = POSTS.find { |post| post.id == id } 14 | end 15 | 16 | def self.unpublished 17 | return POSTS.count { |post| !post.published? } 18 | end 19 | 20 | def publish 21 | @published = true 22 | end 23 | 24 | def unpublish 25 | @published = false 26 | end 27 | 28 | def published? 29 | @published 30 | end 31 | 32 | end 33 | 34 | ### Sample data 35 | 36 | POSTS = [ 37 | Post.new( 38 | 1, 39 | "Introduce Null Object Pattern", 40 | "Post body should be here", 41 | Time.new(2013,01,25) 42 | ), 43 | Post.new( 44 | 2, 45 | "Introduce Assertion", 46 | "Post body should be here", 47 | Time.new(2012,02,26) 48 | ), 49 | Post.new( 50 | 3, 51 | "Extract Method", 52 | "Post body should be here", 53 | Time.new(2014,01,27) 54 | ), 55 | Post.new( 56 | 4, 57 | "Replace Type Code with Polymorphism", 58 | "Post body should be here", 59 | Time.new(2015,10,12) 60 | ) 61 | ] 62 | 63 | -------------------------------------------------------------------------------- /separate-query-from-modifier/lib/before.rb: -------------------------------------------------------------------------------- 1 | class Post 2 | attr_reader :id, :title, :body, :created_at 3 | def initialize id, title, body, created_at 4 | @id = id 5 | @title = title 6 | @body = body 7 | @created_at = created_at 8 | @published = false 9 | end 10 | 11 | def self.find id 12 | # database operation to retrieve data. We'll simulate it for now. 13 | post = POSTS.find { |post| post.id == id } 14 | end 15 | 16 | def publish 17 | @published = true 18 | return POSTS.count { |post| !post.published? } 19 | end 20 | 21 | def unpublish 22 | @published = false 23 | end 24 | 25 | def published? 26 | @published 27 | end 28 | 29 | end 30 | 31 | ### Sample data 32 | 33 | POSTS = [ 34 | Post.new( 35 | 1, 36 | "Introduce Null Object Pattern", 37 | "Post body should be here", 38 | Time.new(2013,01,25) 39 | ), 40 | Post.new( 41 | 2, 42 | "Introduce Assertion", 43 | "Post body should be here", 44 | Time.new(2012,02,26) 45 | ), 46 | Post.new( 47 | 3, 48 | "Extract Method", 49 | "Post body should be here", 50 | Time.new(2014,01,27) 51 | ), 52 | Post.new( 53 | 4, 54 | "Replace Type Code with Polymorphism", 55 | "Post body should be here", 56 | Time.new(2015,10,12) 57 | ) 58 | ] 59 | 60 | -------------------------------------------------------------------------------- /separate-query-from-modifier/test/test.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'minitest/spec' 3 | 4 | require 'before' if ENV["BEFORE"] 5 | require 'after' unless ENV["BEFORE"] 6 | 7 | describe Post do 8 | 9 | before :each do 10 | POSTS.each { |post| post.unpublish } 11 | end 12 | 13 | if ENV["BEFORE"] 14 | it "is publishable and retrieves all unpublished posts count" do 15 | post = Post.find(1) 16 | post.publish.must_equal 3 17 | end 18 | 19 | else # AFTER 20 | 21 | it "is publishable" do 22 | post = Post.find(1) 23 | post.publish.must_equal true 24 | end 25 | 26 | it "retrieves all unpublished posts count" do 27 | Post.unpublished.must_equal 4 28 | end 29 | 30 | end 31 | end 32 | --------------------------------------------------------------------------------