def block in rake task

前端 未结 3 566
清歌不尽
清歌不尽 2021-02-01 13:37

I got undefined local variable or method \'address_geo\' for main:Object with the following rake task. What\'s the problem with it?

include Geokit::         


        
相关标签:
3条回答
  • 2021-02-01 13:46

    Update: Gotcha

    This potentially adds the method to global scope and will conflict with any other method with the same name. Look at @Hula_Zell's answer https://stackoverflow.com/a/44294243/584440 for a better way.

    Original answer

    You are defining the method inside the rake task. For getting the function, you should define outside the rake task (outside the task block). Try this:

    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
    
    0 讨论(0)
  • 2021-02-01 13:50

    Careful: Methods defined in rake files end up defined on the global namespace.

    I would propose to extract the methods into a module or class. This is because methods defined in rake files end up defined on the global namespace. i.e. they can then be called from anywhere, not just within that rake file (even if it is namespaced!).

    This also means that if you have two methods with the same name in two different rake tasks, one of them will be overwritten without you knowing it. Very deadly.

    A great explanation is available here: https://kevinjalbert.com/defined_methods-in-rake-tasks-you-re-gonna-have-a-bad-time/

    0 讨论(0)
  • 2021-02-01 13:51

    You can use a Proc to get the same effect without having a global method declaration. e.g.,

    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
    
    0 讨论(0)
提交回复
热议问题