【问题标题】:Ruby block returning inappropriate valueRuby 块返回不适当的值
【发布时间】:2023-03-03 00:36:01
【问题描述】:

跟进这个screencast,如果有Product记录,它会以某种方式返回2..3

def save
    puts "--- imported_products: #{imported_products.inspect}"
    // --- imported_products: 2..3
    if imported_products.map(&:valid?).all?
      imported_products.each(&:save!)
      true
    else
      imported_products.each_with_index do |product, index|
        product.errors.full_messages.each do |message|
          errors.add :base, "Row #{index+2}: #{message}"
        end
      end
      false
    end
 end

 def imported_products
   @imported_products ||= load_imported_products
 end

 def load_imported_products
   spreadsheet = open_spreadsheet
   header = spreadsheet.row(1)
   (2..spreadsheet.last_row).each do |i|
     row = Hash[[header, spreadsheet.row(i)].transpose]
     product = Product.find_by_id(row['id']) || Product.new
     product.attributes = row.to_hash.slice(*accessible_attributes)
     product
   end
 end

【问题讨论】:

    标签: ruby ruby-on-rails-4 ruby-2.1


    【解决方案1】:

    您的 load_imported_products 方法包含一个 each 块。该块是方法的最后“行”,因此块的返回值成为方法的返回值。

    尝试以下方法:

    def load_imported_products
      spreadsheet = open_spreadsheet
      header = spreadsheet.row(1)
      products = []
      (2..spreadsheet.last_row).each do |i|
        row = Hash[[header, spreadsheet.row(i)].transpose]
        product = Product.find_by_id(row['id']) || Product.new
        product.attributes = row.to_hash.slice(*accessible_attributes)
        products << product
      end
      products
    end
    

    【讨论】:

    【解决方案2】:

    如果您在谈论 load_imported_products 方法,请尝试将每个产品添加到数组中,然后返回数组。

    我不确定该方法返回的确切内容,但您可能需要显式返回产品集合。

    所以

    def load_imported_products
       products = []
       spreadsheet = open_spreadsheet
       header = spreadsheet.row(1)
       (2..spreadsheet.last_row).each do |i|
         row = Hash[[header, spreadsheet.row(i)].transpose]
         product = Product.find_by_id(row['id']) || Product.new
         product.attributes = row.to_hash.slice(*accessible_attributes)
         products << product
       end
       return products
     end
    

    【讨论】:

    • 在 ruby​​ 中不需要显式返回,因为 ruby​​ 总是返回最后一个语句。(所以只要 products 就足够了)除非在 setter 方法的情况下,在这种情况下它返回值集。
    • 谢谢,你是对的。我知道这是不必要的,但我认为它有助于提高可读性,特别是因为问题是问为什么该方法没有返回它应该返回的内容。出于好奇,当您想从方法中返回一个值时,为什么不输入“return”?它可能会节省几次击键,但是否值得更清楚地表明您希望返回该值?
    • 它只是不被认为是正确的约定。确实没有什么问题,有些人在循环或条件语句中使用它,但通常显式返回会产生白话代码的味道,并表明可能有更好的方法来编写代码来避免这种情况。
    【解决方案3】:

    或者使用地图

    def load_imported_products
      spreadsheet = open_spreadsheet
      header = spreadsheet.row(1)
      products = (2..spreadsheet.last_row).map do |i|
        row = Hash[[header, spreadsheet.row(i)].transpose]
        product = Product.find(row['id'].to_i) || Product.new
        product.attributes = row.to_hash.slice(*accessible_attributes)
        product
      end
    end
    

    也不需要 find_by_id find 方法使用 id 尽管我将它强制为整数以防万一它是 nil 或存储为 string

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 2014-03-14
      • 1970-01-01
      • 2019-11-02
      • 2021-10-01
      相关资源
      最近更新 更多