EDIT-我重新添加了注释部分,包括了我试图解决这个问题的其他方法,希望能为我的过程提供更多的洞察力.到目前为止,这个程序是有效的,但它发送我的本地Electron 表格作为附件,而不是"临时"文件,我需要从谷歌工作表生成并附加.这显然是我有问题的部分,我需要知道如何添加我的代码相应地下载和附加临时文件与处理的数据…

您好,提前感谢您的帮助.当我试图下载一个表格文件并将其附加到邮箱中时,我的Ruby程序遇到了一个问题.该程序应该添加要从本地Electron 表格重新订购的单位,并将其添加到Sheets文件中,然后应下载该文件并以附件的形式通过邮箱发送.我可以让程序发送一封邮箱,在邮箱的正文中相应的SKU和数量作为文本,我可以让程序将SKU和数量添加到指定的Google工作表,但我无法下载工作表文件并将其作为附件通过邮箱发送.我收到的确切错误如下:

C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/signet-0.18.0/lib/signet/oauth_2/client.rb:420:in `scope=': Expected Array or String, got Hash (TypeError)

          raise TypeError, "Expected Array or String, got #{new_scope.class}"
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/signet-0.18.0/lib/signet/oauth_2/client.rb:193:in `update!'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/signet-0.18.0/lib/signet/oauth_2/client.rb:115:in `initialize'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/googleauth-0.17.1/lib/googleauth/service_account.rb:105:in `initialize'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/googleauth-0.17.1/lib/googleauth/service_account.rb:80:in `new'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/googleauth-0.17.1/lib/googleauth/service_account.rb:80:in `make_creds'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/google_drive-3.0.7/lib/google_drive/session.rb:89:in `from_service_account_key'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/google_drive-3.0.7/lib/google_drive/session.rb:86:in `block in from_service_account_key'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/google_drive-3.0.7/lib/google_drive/session.rb:85:in `open'
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/google_drive-3.0.7/lib/google_drive/session.rb:85:in `from_service_account_key'
        from ex5.rb:38:in `insert_data'
        from ex5.rb:83:in `process_order'
        from ex5.rb:144:in `<main>'

有人能判断一下我的代码并告诉我哪里做错了吗?

require 'bundler'
require 'google_drive'
require 'roo'
require 'google/apis/sheets_v4'
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'mail'
Bundler.require

begin
def read_spreadsheet(file_path)
  spreadsheet = Roo::Excelx.new(file_path)
  header = spreadsheet.row(2)
  data = []
  (3..spreadsheet.last_row).each do |i|
    row = Hash[[header, spreadsheet.row(i)].transpose]
    data << row
  end
  data
end

def format_data_plain_text(data)
  formatted_data = ""

  data.each do |row|
    unless row['REORDER QTY'].to_i.zero? || row['AC SKU'].to_s.empty?
      sku = row['AC SKU'].to_s
      quantity = row['REORDER QTY'].to_s

      formatted_data += "#{sku}\t#{quantity}\n"
    end
  end
  formatted_data.to_s
end


def insert_data(file_path, formatted_data)
  session = GoogleDrive::Session.from_service_account_key("client_secret.json")

  spreadsheet_title = "Reorder Details"
  spreadsheet = session.spreadsheet_by_title(spreadsheet_title)
  worksheet = spreadsheet.worksheets.first

  first_empty_row = 1
  while !worksheet[first_empty_row, 1].empty? && first_empty_row <= worksheet.num_rows
    first_empty_row += 1
  end

if first_empty_row == 1
  worksheet[first_empty_row, 1] = "SKU"
  worksheet[first_empty_row, 2] = "QUANTITY"
  first_empty_row += 1
end

puts formatted_data.class
  data_lines = formatted_data.split("\n")
  data_lines.each_with_index do |line, index|
    columns = line.split("\t")
    worksheet[first_empty_row + index, 1] = columns[0]
    worksheet[first_empty_row + index, 2] = columns[1]
  end

  worksheet.save
end

def download_google_sheet(sheet_id)
  session = GoogleDrive::Session.from_service_account_key("client_secret.json")
  spreadsheet = session.spreadsheet_by_key(sheet_id)

  worksheet = spreadsheet.worksheets.first

  temp_file = Tempfile.new(['google_sheet', '.xlsx'], encoding: 'UTF-8')
  worksheet.export_as_file(temp_file.path)

  temp_file.path
  temp_file.close
end

def process_order(file_path)
  order_details = read_spreadsheet(file_path)
  formatted_data = format_data_plain_text(order_details)

  insert_data(file_path, formatted_data)

  puts "Data inserted into Google Sheets."

  sheet_id = 'numbersandletters'
  temp_file_path = download_google_sheet(sheet_id)

  send_email(file_path, temp_file_path)
end

def send_email(file_path, temp_file_path)
    # Configure your email settings
    options = {
      address: 'smtp.gmail.com',
      port: 587,
      user_name: 'email@email.com',
      password: 'password',
      domain: 'domain.com',
      authentication: 'plain',
      enable_starttls_auto: true
    }
    Mail.defaults do
      delivery_method :smtp, options
    end

    order_details = read_spreadsheet(file_path)
    formatted_data = format_data_plain_text(order_details)

    #temp_file_content = File.read(temp_file_path)

    #Specify the email content
    mail = Mail.new do
      from    'Email@email.com'
      to      'email@email.com'
      subject "Order Details:"
      body    "Hey Tim. Hope you're doing well! I just need to place an order for the following items:\n\nThis will be using Net Terms.\n\nPlease let me know if you need anything else from me! Have a great week!"
      add_file(file_path)
    end
    # Send the email
    mail.deliver!
end

#def send_email(file_path)
#  gmail = Gmail.connect("email@email.com", "password")
#
#  subject = "Reorder Details"
#  body = "Please find the attached Google Sheet with reorder details."
#
#  gmail.deliver do
#    to "email@email.com"
#    subject subject
#    text_part do
#      body body
#    end
#    add_file file_path
#  end

#  gmail.logout
#end

file_path = 'path\to\file'
process_order(file_path)



#def export_google_sheet(file_id, export_format, export_directory)
#  session = GoogleDrive::Session.from_service_account_key('path\to\cliet_secret.json')
#
#  spreadsheet = session.file_by_id(file_id)
#  export_filename = "AC_Order_#{Time.now.strftime('%Y-%m-%d')}.#{export_format.split('/').last}"
#  export_path = File.join(export_directory, export_filename)
#
#  spreadsheet.export_as_file(export_format, export_path)
#
#    puts "File exported to: #{export_path}"
#end

#file_id = 'randomnumbersandletters'
#export_format = 'pdf'
#export_directory = '\path\to\export'

#export_google_sheet(file_id, export_format, export_directory)

end

我try 在"Format_Data_Plain_Text"方法的末尾添加Format_data.to_S,以确保数据被转换为字符串.我还try 添加"TEMP_FILE_CONTENT=File.Read(TEMP_FILE_PATH)",但它必须是其他内容,因为不管添加这些内容,都会返回相同的错误.

推荐答案

GoogleDrive::Session.from_service_account_key具有以下方法签名:

def self.from_service_account_key(
    json_key_path_or_io, scope = DEFAULT_SCOPE, client_options = nil,
    request_options = nil
)

4个位置参数是:

  • json_key_path_or_io(必填)
  • scope(可选,默认为DEFAULT_SCOPE)
  • client_options(可选)
  • request_options(可选)

如果您拨打:

GoogleDrive::Session.from_service_account_key("client_secret.json", timeout_sec: 300)

timeout_sec: 300被视为scope参数的散列,因此出现类型错误.

为了提供第三个参数,您还必须传递第二个参数:

GoogleDrive::Session.from_service_account_key(
  "client_secret.json",
  GoogleDrive::Session::DEFAULT_SCOPE,
  timeout_sec: 300
)

这是立场论据的一个缺点.如果他们使用关键字参数,这会更容易.

Ruby相关问答推荐

Ruby错误-应为数组或字符串,已获取哈希

鲁比.METHOD_MISSING+SEND对于带有命名参数的混合参数失败

Rbenv说未安装已安装的版本

如何解密在 sjcl.js 中使用 ruby​​ 创建的 AES-256-GCM

ruby:rubocop 抱怨将 if else 转换为 case 语句

如何从 DateTime 值中删除区域?

Ruby 的 Object#taint 和 Object#trust 方法是什么?

Ruby 中的发送方法

我不明白Ruby本地范围(local scope)

与 String 相比,在 Ruby 中使用 StringIO 有哪些优势?

获取Ruby中数组的差异

如何将值保存到 YAML 文件中?

在 Ruby 中,有没有办法使用 hash.each_with_index do |[k,v], i| 之类的东西?

文字数字中的下划线是什么意思?

在 ruby​​ 的超类中调用另一个方法

在 Ruby 中按名称获取一个类?

`File` 对象访问模式的区别(即 w+, r+)

向实例对象添加方法

Ruby中的urldecode?

更好的 ruby​​ markdown 解释器?