rake任务中的def块

时间:2011-09-04 08:25:42

标签: ruby-on-rails ruby methods rake

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

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:21)

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

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

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

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

答案 2 :(得分:0)

您可以使用Proc来获得相同的效果,而无需使用全局方法声明。例如,

include Geokit::Geocoders

namespace :geocode do
  desc "Geocode to get latitude, longitude and address"
  task :all => :environment do

    address_geo = Proc.new do
      arr = []
      arr << address if @spot.address
      arr << city if @spot.city
      arr << country if @spot.country
      arr.reject{|y|y==""}.join(", ")
    end
    @spot = Spot.find(:first)
    if @spot.latitude.blank? && !@spot.address.blank?
      puts address_geo.call
    end
  end
end