rake任务中的def块

Vic*_*tor 40 ruby methods rake ruby-on-rails

我得到undefined local variable or method 'address_geo' for main:Object了以下rake任务.有什么问题呢?

include Geokit::Geocoders

namespace :geocode do
  desc "Geocode to get latitude, longitude and address"
  task :all => :environment do
    @spot = Spot.find(:first)
    if @spot.latitude.blank? && !@spot.address.blank?
      puts address_geo
    end

    def address_geo
      arr = []
      arr << address if @spot.address
      arr << city if @spot.city
      arr << country if @spot.country
      arr.reject{|y|y==""}.join(", ")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

rub*_*nce 97

您正在rake任务中定义方法.要获得该功能,您应该在rake任务之外定义(在任务块之外).试试这个:

include Geokit::Geocoders

namespace :geocode do
  desc "Geocode to get latitude, longitude and address"
  task :all => :environment do
    @spot = Spot.find(:first)
    if @spot.latitude.blank? && !@spot.address.blank?
      puts address_geo
    end
  end

  def address_geo
    arr = []
    arr << address if @spot.address
    arr << city if @spot.city
    arr << country if @spot.country
    arr.reject{|y|y==""}.join(", ")
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我这样做,我的方法可用于所有rake任务,你知道我怎么能避免这个? (7认同)
  • 这种方法在所有rake任务中都可用,并且不安全.Hula_Zell的解决方案更好. (3认同)
  • @WilliamWeckl 您可以在 rake 任务中定义 lambdas。 (2认同)
  • @justingordon你是什么意思?该怎么办? (2认同)

Hul*_*ell 24

小心:rake文件中定义的方法最终在全局命名空间中定义.

我建议将方法提取到模块或类中.这是因为rake文件中定义的方法最终在全局命名空间中定义.也就是说,然后可以从任何地方调用它们,而不仅仅是在那个rake文件中(即使它是命名空间!).

这也意味着如果在两个不同的rake任务中有两个具有相同名称的方法,则其中一个将在您不知情的情况下被覆盖.非常致命.

这里有一个很好的解释:https://kevinjalbert.com/defined_methods-in-rake-tasks-you-re-gonna-have-a-bad-time/

  • 我也认为这是将方法提取到模块或类中的最佳实践. (4认同)