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

Code Refactoring - Ruby

Code Refactoring - Ruby

- How to refactor code in Ruby

Rohan Pujari

July 25, 2016
Tweet

Other Decks in Programming

Transcript

  1. Why do we do code refactoring? - To satisfy our

    ego as a developer. - So that no one can point fingers at our code. - Someone told us to do so. - So that we can brag about it. - For code climate score.
  2. # Original code puts 'Batsmen' if !bowler? # Refactored code

    puts 'Batsmen' unless bowler? #Refactored code bowler? or puts 'Batsmen' #Original code puts "Hi" # Refactored code puts 'Hi'
  3. Spreadsheet::Import('tax.csv', {city: 0, tax_rate: 1}, start_row: 1, end_row: 120).import(Tax) def

    initialize(file_url, mapping, options) @file_url = file_url @mapping = mapping @start_row = options.fetch(:start_row, 0) @end_row = options.fetch(:end_row, 100) end
  4. What if i want to use simple-spreadsheet gem methods? spreadsheet

    = SimpleSpreadsheet::Workbook.read(file_url) last_row = spreadsheet.last_row spreadsheet.cell(last_row, 1) spreadsheet.cell(last_row, 2)
  5. attr_accessor :file_url, :mapping, :start_row, :end_row, :spreadsheet def initialize(file_url, mapping, options)

    @file_url = file_url @mapping = mapping @start_row = options.fetch(:start_row, 0) @end_row = options.fetch(:end_row, 100) @reader = SimpleSpreadsheet::Workbook.read(file_url) End import = Spreadsheet::Import('tax.csv', {city: 0, tax_rate: 1}, start_row: 1, end_row: 120) last_row = import.reader.last_row import.reader.cell(last_row, 1) import.reader.cell(last_row, 2)
  6. What if we do not want to use simple-spreadsheet gem?

    - Dependency injection comes to rescue.
  7. Tips - Always depend on abstract things rather than concrete

    things. - Isolate code which have higher chances of changing from other code.
  8. We are not done yet. - What does Spreadsheet::Import class

    do? - Does it have single responsibility?
  9. Things to do to make code flexible and extensible. -

    Leave some room to accommodate changes. - Do not predict the future, but plan for it.
  10. Let see some code. class User < ActiveRecord::Base # create_table

    :user do |t| # t.string :name # t.admin :boolean, default: true # end end class UsersController < ApplicationController def index if current_user.admin? else end end end
  11. class User < ActiveRecord::Base # create_table :users do |t| #

    t.string :name # t.references :role # end end class Role < ActiveRecord::Base # create_table :roles do |t| # t.integer :role_id # end end # Somewhere in controller current_user.role.role_id == 1 ? do_admin_work : do_normal_user_work
  12. class User < ActiveRecord::Base def admin? role.role_id == 1 end

    end # Somewhere in controller current_user.admin?
  13. Questions? - Should User model know what does role_id ==

    1 means? - Should it be the responsibility of role model instead? - If we have several roles do we have to write all the method for different role? eg:) moderator?
  14. class Role < ActiveRecord::Base ROLE_HASH = { normal_user: 0, admin:

    1 } ROLE_HASH.each do |role_name, role_value| define_method("#{role_name}?") do role_id == role_value end end end # Somewhere in controller current_user.role.admin?
  15. class Video create_tables :videos do |t| t.string :youtube_video_id end end

    # In views <iframe width="600" height="340" src=<%= "https://www.youtube.com/embed/{product.video.youtube_video_id}" %> https://github. com/Kiprosh/memobed/pull/26/commits/a4c1491ed095f5d117ace7ad5c6b767b6477e6ed
  16. Tip - Writing logical code in view and controller is

    cruel. It can’t be reused. - Add logic to model. But don’t make it a dumping ground for everything. - Move things away from model which doesn’t belong there.
  17. Few other tips. - Use helper method only if you

    need some rails inbuilt view helper. If possible use presenter pattern. - Create separate class or module for function which does not require rails view helpers. - Helpers should be a pure function. Should not depend on instance variable
  18. Probably you won’t open this link. Time's up https://github. com/Kiprosh/memobed/commit/e5db37ab7ed00e40ff22c89cf82a987b223a9535#diff-

    127a850b7d7b20173ad3fba88f8a25e3R19 https://github.com/Kiprosh/memobed/blob/master/lib/currency.rb
  19. I said Time's up. class ProductController < Applicationcontroller def show

    @description = Product.find(params[:id).description.text end end module ProductHelper def product_description @description.capitalize.truncate() end end