使用散列长度作为迭代器多次调用其他方法的方法

时间:2017-10-26 13:08:56

标签: ruby

我想要多次调用两种方法。我想要呼叫它们的次数取决于我使用的哈希计数。我试图创建一个调用其他2的新方法,并重复哈希计数的长度。我的问题是我收到了错误

"findfiles2.rb:61:in` `chdir': no implicit conversion of Enumerator into String (TypeError)
from findfiles2.rb:61:in `store_directories'
from findfiles2.rb:138:in `block in repeat'
from findfiles2.rb:134:in `loop'
from findfiles2.rb:134:in `repeat'
from findfiles2.rb:153:in `<main>'"

这是我的代码:

require 'date'
require "mail"

options = { :address              => "smtp.gmail.com",
            :port                 => 587,
            :domain               => 'gmail.com',
            :user_name            => 'username',
            :password             => 'password/',
            :authentication       => 'plain',
            :enable_starttls_auto => true  }

mail_sender = "somename@gmail.com"
mail_recipient = "somename@yahoo.com"


directories = {
  "directory1" => "/path/to/folder1/",
  "directory2" => "/path/to/folder2/",
  "directory3" => "/path/to/folder3/",
  "directory4" => "/path/to/folder4/",
  "directory5" => "/path/to/folder5/"
}

directory_count = directories.count.to_i


file_output = "/path/to/output/"
exclude_folder = 'sample'

output_file_name = "directory_list"
output_file_extension = ".csv"

date_today = Date.today.to_s

log_file_path = "/path/to/output/"
log_name = "script_log_" + date_today + ".txt"
log_file_name = log_file_path + log_name




# starts log file
def start_log(file_output, log_name)
  Dir.chdir(file_output)
  log_output = File.open(log_name, 'a+')

  $stdout = log_output
  puts Time.now.to_s + "  >  " + "Starting Script..."
  puts "_______________________________________________"
end




# stores subdirectory contents into an array
def store_directories(directory, folder_to_exclude)
  # changes working directory to the directory variable

  puts Time.now.to_s + "  >  " +  "Updating search directory..."

  Dir.chdir(directory)

  # outputs only subdirectories with a creation date of older than 24 hours, except for folders names 'test'

  Dir.glob("*.*").map(&File.method(:realpath))
  puts Time.now.to_s + "  >  " +  "Gathering subdirectories..."

  subdir_list=Dir.glob("*").map(&File.method(:realpath)).reject{|files| (not File.directory?(files) && (File.mtime(files) < (Time.now - (60*1440))) && (not files == directory + folder_to_exclude)) }
  return subdir_list
end





# checks to see if there are any directories in the array
def directory_check(directory_list, save_to_file, today_date, output_file, output_extension)

  if directory_list.empty? == false

    # changes the working directory to the file output directory for the file
    Dir.chdir(save_to_file)

    # writes the array contents into a new file
    file_name = output_file + "_" + today_date + output_extension
    puts Time.now.to_s + "  >  " +  "Saving contents to:  " + file_name
    File.open(file_name, "a+") do |f| 
      directory_list.each { |element| f.puts(element) }


    end

  else
    puts Time.now.to_s + "  >  " +  "This directory does not contain any subdirectories that are older than 24 hours"
    exit
  end
end 





# sends an email containing today's report if a file was created today 
def send_email(today_date, output_file_path, output_file_name, output_file_extension, mail_options, email_sender, email_recipient)
 backlog_file = output_file_path + output_file_name + "_" + today_date + output_file_extension

  if File.exist?(backlog_file) == true
    puts Time.now.to_s + "  >  " +  "Sending email report to: " + email_recipient + "..." 

    Mail.defaults do
      delivery_method :smtp, mail_options
    end

    Mail.deliver do
           to email_recipient
         from email_sender
      subject 'Backlog for ' + today_date
         body 'Attached is a report showing any batches that have not been processed within the last 24 hours.'
         add_file backlog_file
       end
   else
    puts Time.now.to_s + "  >  " +  "No batches older than 24 hours to report"
    exit
  end
 end  

这是给我带来麻烦的方法

def repeat(directory, times, exclude_folder)
  # fail "times must be 1 or more" if times < 1
  counter = 1
  # counter_string = counter.to_s
  # puts counter_string
  # directory_counter = directory + counter_string
  loop do
    if counter != times


      subdir_list_contents = store_directories(directory, exclude_folder)
      directory_check(subdir_list_contents, file_output, date_today, output_file_name, output_file_extension)

      counter = counter + 1

    else
      break
    end
  end
end

这是我开始运行一切的地方。

# Starting log file...
start_log(file_output, log_name)

repeat(directories.each, directory_count, exclude_folder)


# # outputs contents of directory 1 to the file (I want to perform this for the amount of times equal to the hash length, which is what I'm creating the repeat method for)
subdir_list_contents = store_directories(directory1, exclude_folder)
directory_check(subdir_list_contents, file_output, date_today, output_file_name, output_file_extension)


# # # If there is a new file from today, sends an email with file as attachment
send_email(date_today, file_output, output_file_name, output_file_extension, options, mail_sender, mail_recipient)

1 个答案:

答案 0 :(得分:0)

你的代码太长了。如你所见,没有人会帮助你。

$ ruby -w t.rb 
t.rb:125: warning: mismatched indentations at 'end' with 'def' at 104
t.rb:37: warning: assigned but unused variable - log_file_name
/Users/b/.rvm/rubies/ruby-2.4.0-rc1/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:
in `require': cannot load such file -- mail (LoadError)

我们可以运行的邮政编码。我不打算安装整个邮件服务器。所以我发表评论

#require "mail"

然后

t.rb:44:in `chdir': No such file or directory @ dir_chdir - /path/to/output/ (Errno::ENOENT)

等等。

请按照错误消息:

t.rb:62:in `chdir': no implicit conversion of Enumerator into String (TypeError)
    from t.rb:62:in `store_directories'
    from t.rb:139:in `block in repeat'
    from t.rb:136:in `loop'
    from t.rb:136:in `repeat'
    from t.rb:149:in `<main>'

您需要跟踪的所有内容都是repeatstore_directories,因此您可以将发布的代码缩减到此严格的最小值以重现错误:

directories = {
  "directory1" => "/path/to/folder1/",
  "directory2" => "/path/to/folder2/",
}

directory_count = directories.count.to_i
exclude_folder = 'sample'

# stores subdirectory contents into an array
def store_directories(directory, folder_to_exclude)
  puts "directory=#{directory.inspect} folder_to_exclude=#{folder_to_exclude}"
  Dir.chdir(directory)
end

def repeat(directory, times, exclude_folder)
  store_directories(directory, exclude_folder)
end

repeat(directories.each, directory_count, exclude_folder)

执行:

$ ruby -w t.rb 
directory=#<Enumerator: {"directory1"=>"/path/to/folder1/", "directory2"=>"/path/to/folder2/"}:each> folder_to_exclude=sample
t.rb:12:in `chdir': no implicit conversion of Enumerator into String (TypeError)
    from t.rb:12:in `store_directories'
    from t.rb:16:in `repeat'
    from t.rb:19:in `<main>'

如果你这样做了,你甚至不必发一个问题,因为错误的原因是显而易见的。在

repeat(directories.each, directory_count, exclude_folder)

directories.each返回一个枚举器。删除each

$ ruby -w t.rb 
directory={"directory1"=>"/path/to/folder1/", "directory2"=>"/path/to/folder2/"} folder_to_exclude=sample
t.rb:12:in `chdir': no implicit conversion of Hash into String (TypeError)
    from t.rb:12:in `store_directories'
    from t.rb:16:in `repeat'
    from t.rb:20:in `<main>'

我想您想要做的就是为每个目录调用repeat一次:

def repeat(directory, exclude_folder)
  puts "in repeat directory=#{directory} exclude_folder=#{exclude_folder}"
  store_directories(directory, exclude_folder)
end

directories.each { | _key, directory | repeat(directory, exclude_folder) }

执行:

$ ruby -w t.rb 
in repeat directory=dir1 exclude_folder=sample
in store_directories directory="dir1" folder_to_exclude=sample
in repeat directory=dir2 exclude_folder=sample
in store_directories directory="dir2" folder_to_exclude=sample
t.rb:18:in `chdir': No such file or directory @ dir_chdir - dir2 (Errno::ENOENT)
    from t.rb:18:in `store_directories'
    from t.rb:53:in `repeat'

chdir有副作用:它会更改当前目录,下次它将开始在新的当前目录中搜索。为避免这种情况,您需要恢复以前的状态:

def store_directories(directory, folder_to_exclude)
  puts "in store_directories directory=#{directory.inspect} folder_to_exclude=#{folder_to_exclude}"
  current_directory = Dir.getwd
  Dir.chdir(directory)
  # ...
    # Restore the directory that was current when entering the method.
    # Without it, the next chdir will start from the directory left by the previous chdir.
  Dir.chdir(current_directory)
end

现在可行:

$ ruby -w t.rb 
in repeat directory=dir1 exclude_folder=sample
in store_directories directory="dir1" folder_to_exclude=sample
in repeat directory=dir2 exclude_folder=sample
in store_directories directory="dir2" folder_to_exclude=sample

经过几次更改后,我最终得到了这个:

require 'date'

directories = {
  "directory1" => 'dir1',
  "directory2" => 'dir2'
}

exclude_folder         = 'sample'
@file_output           = '.'
@date_today            = Date.today.to_s
@output_file_name      = 'directory_list'
@output_file_extension = '.csv'

# stores subdirectory contents into an array
def store_directories(directory, folder_to_exclude)
  puts "in store_directories directory=#{directory.inspect} folder_to_exclude=#{folder_to_exclude}"
  current_directory = Dir.getwd
  puts Time.now.to_s + "  >  " +  "Updating search directory..."

  # changes working directory to the directory variable
  Dir.chdir(directory)

  # outputs only subdirectories with a creation date of older than 24 hours, except for folders names 'test'

  puts Time.now.to_s + "  >  " +  "Gathering subdirectories..."

  subdir_list = Dir.glob("*").map { | file | File.realpath(file) }
  puts "all files : subdir_list=#{subdir_list}"
  puts "directory + folder_to_exclude=#{directory + folder_to_exclude}" # nonsense

  subdir_list = subdir_list.reject do | file |
         not File.directory?(file) \
      && File.mtime(file) < Time.now - 86400 \
      && (not file == folder_to_exclude)
  end
  puts "after reject : subdir_list=#{subdir_list}"

    # Restore the directory that was current when entering the method.
    # Without it, the next chdir will start from the directory left by the previous chdir.
  Dir.chdir(current_directory)
  puts "subdir_list=#{subdir_list.inspect}"
  subdir_list
end

# checks to see if there are any directories in the array
def directory_check(directory_list, save_to_file, today_date, output_file, output_extension)

  if directory_list.empty? == false

    # changes the working directory to the file output directory for the file
    Dir.chdir(save_to_file) # <----------------- problem !!!!

    # writes the array contents into a new file
    file_name = output_file + "_" + today_date + output_extension
    puts Time.now.to_s + "  >  " +  "Saving contents to:  " + file_name
    File.open(file_name, "a+") do |f| 
      directory_list.each { |element| f.puts(element) }
    end
  else
    puts Time.now.to_s + "  >  " +  "This directory does not contain any subdirectories that are older than 24 hours"
  end
end 

def repeat(directory, exclude_folder)
  puts "in repeat directory=#{directory} exclude_folder=#{exclude_folder}"
  subdir_list_contents = store_directories(directory, exclude_folder)
  directory_check(subdir_list_contents, @file_output, @date_today, @output_file_name, @output_file_extension)
end

directories.each { | _key, directory | repeat(directory, exclude_folder) }

执行:

$ ruby -w t.rb 
in repeat directory=dir1 exclude_folder=sample
in store_directories directory="dir1" folder_to_exclude=sample
2017-10-27 08:05:24 +0200  >  Updating search directory...
2017-10-27 08:05:24 +0200  >  Gathering subdirectories...
all files : subdir_list=["/userdata/devl/ruby/zintlist/directories/dir1/x1.txt", "/userdata/devl/ruby/zintlist/directories/dir1/x2.txt"]
directory + folder_to_exclude=dir1sample
after reject : subdir_list=[]
subdir_list=[]
2017-10-27 08:05:24 +0200  >  This directory does not contain any subdirectories that are older than 24 hours
in repeat directory=dir2 exclude_folder=sample
in store_directories directory="dir2" folder_to_exclude=sample
2017-10-27 08:05:24 +0200  >  Updating search directory...
2017-10-27 08:05:24 +0200  >  Gathering subdirectories...
all files : subdir_list=["/userdata/devl/ruby/zintlist/directories/dir2/x3.txt"]
directory + folder_to_exclude=dir2sample
after reject : subdir_list=[]
subdir_list=[]
2017-10-27 08:05:24 +0200  >  This directory does not contain any subdirectories that are older than 24 hours