0

I am new guy for write ruby file

I have wrote a task in ruby script, but there is a lot of repeated code in that task. So i need write a common method for that.

This is my task in ruby file

    install_projects = [ 
  'Cooperativa.Hermes.Application.Host.Console', 
  'Cooperativa.Hermes.Denormalizer.Host.Console', 
  'Cooperativa.Hermes.WebApi.Host.Console',
]

setup_projects = [ 
  'Cooperativa.Hermes.Setup.Console' 
]

replay_projects = [
  'Cooperativa.Hermes.EventReplayer.Console'
]

task :restore do

 install_projects.each do |project|
    restore_folder = "#{install}/#{project}"
    FileUtils.rm_rf restore_folder
    FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
  end  
  setup_projects.each do |project|
    restore_folder = "#{install}/#{project}"
    FileUtils.rm_rf restore_folder
    FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
  end   
  replay_projects.each do |project|
    restore_folder = "#{install}/#{project}"
    FileUtils.rm_rf restore_folder
    FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
  end    
end

See

 restore_folder = "#{install}/#{project}"
        FileUtils.rm_rf restore_folder
        FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)

the above code is a repeated code.

I need re-factored into a separate method or common method. How can i do this? have you any idea?

How to write a method in ruby script for my task?

Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234

2 Answers2

2

You can either:

#refactor the proc

anonymous = lambda do |project|
  restore_folder = "#{install}/#{project}"
  FileUtils.rm_rf restore_folder
  FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
end

install_projects.each &anonymous

Or loop everything at once:

( install_projects + setup_projects + replay_projects).each do |project|

Otherwise, what about extracting everything into a class where you can have your own methods and variables?

class RestoreData

  attr_reader :install, :backup_root

  def initialize(install, backup_root)
    @install     = install
    @backup_root = backup_root
  end

  def call
    projects.each do |project|
      clean_project_folder(project)
      restore_backup(project)
    end   
  end

  private

  def clean_project_folder(project)
    FileUtils.rm_rf restore_folder(project)
  end

  def restore_backup(project)
    FileUtils.cp_r(backup_folder(project), restore_folder(project))
  end

  def backup_folder(project)
    "#{backup_root}/#{project}"
  end

  def restore_folder(project)
    "#{install}/#{project}"
  end

  def projects
    install_projects + setup_projects + replay_projects
  end

  def install_projects
    [
      'Cooperativa.Hermes.Application.Host.Console', 
      'Cooperativa.Hermes.Denormalizer.Host.Console', 
      'Cooperativa.Hermes.WebApi.Host.Console',
    ]
  end

  def setup_projects
    [ 
      'Cooperativa.Hermes.Setup.Console' 
    ]
  end

  def replay_projects
    [
      'Cooperativa.Hermes.EventReplayer.Console'
    ]
  end
end

and your rake task:

task :restore do
  RestoreData.new(install, backup_folder).call
end
apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • The `install_projects and setup_projects and replay_projects` is a array, So is it working? I think the each loop is a just risk for me. So can you give me a method, with pass parameter? – Ramesh Rajendran Feb 27 '14 at 12:55
  • +1 but this one a good idea. I need a method, if that not possible, then i will do your idea . Thanks – Ramesh Rajendran Feb 27 '14 at 12:56
  • 1
    a cheap way would be to define the method in the same file but I dont recommend this, if you need abstraction, create a dedicated file/class – apneadiving Feb 27 '14 at 13:09
1

This is using a method:

def do_restore(project, install, backup_folder)
  restore_folder = "#{install}/#{project}"
  FileUtils.rm_rf restore_folder
  FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
end

task :restore do

  install_projects.each { |project| do_restore(project, install, backup_folder) }
  setup_projects.each { |project| do_restore(project, install, backup_folder) }
  replay_projects.each { |project| do_restore(project, install, backup_folder) }

end

Though I think this might be a better solution for you (as suggested by @apneadiving):

(install_projects + setup_projects + replay_projects).each do |project|
  restore_folder = "#{install}/#{project}"
  FileUtils.rm_rf restore_folder
  FileUtils.cp_r("#{backup_folder}/#{project}", restore_folder)
end

Since you are actually iterating over three arrays, doing the same thing, this is just like if you added the three arrays together, and iterated over the joined array. To join two arrays together, you can use the + operator - [1,2]+[3,4]==[1,2,3,4], so install_projects + setup_projects + replay_projects is simply a long list of projects, concatenated together:

install_projects = [ 
  'Cooperativa.Hermes.Application.Host.Console', 
  'Cooperativa.Hermes.Denormalizer.Host.Console', 
  'Cooperativa.Hermes.WebApi.Host.Console',
]

setup_projects = [ 
  'Cooperativa.Hermes.Setup.Console' 
]

replay_projects = [
  'Cooperativa.Hermes.EventReplayer.Console'
]

(install_projects + setup_projects + replay_projects) == [
  'Cooperativa.Hermes.Application.Host.Console', 
  'Cooperativa.Hermes.Denormalizer.Host.Console', 
  'Cooperativa.Hermes.WebApi.Host.Console',
  'Cooperativa.Hermes.Setup.Console',
  'Cooperativa.Hermes.EventReplayer.Console'
]
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93