Rails:如何在rake任务中定义函数

时间:2014-09-28 09:21:50

标签: ruby-on-rails ruby rake

在我的任务文件post.rake中,我想重用一个函数

  def save_post(title, href, source)
    post = Post.new(title: title, url: href, source: source)
    if post.save
      puts title + 'saved'
    else
      puts title + 'not saved'
    end
  end

但是,当我在此文件中定义并重新使用它时,它会返回

NoMethodError: undefined method `save_post' for main:Object

post.rake看起来像这样:

task :fetch_post => :environment do
  require 'nokogiri'
  require 'open-uri'

  url = 'http://example.com'
  doc = Nokogiri::HTML(open(url) )
  puts doc.css("title").text
  doc.css(".a").each do |item_info|
    title = item_info.text
    href = item_info['href']
    save_post(title, href)
  end

  def save_post(title, href)
    post = Post.new(title: title, url: href)
    if post.save
      puts title + 'saved'
    else
      puts title + 'not saved'
    end
  end
end

内容抓取部分有效。我只是将保存后的代码移出,想要抽象出方法。

我应该在哪里放def method

3 个答案:

答案 0 :(得分:3)

task :fetch_post => :environment do
  require 'nokogiri'
  require 'open-uri'

  def save_post(title, href)
    post = Post.new(title: title, url: href)
    if post.save
      puts title + 'saved'
    else
      puts title + 'not saved'
    end
  end

  url = 'http://example.com'
  doc = Nokogiri::HTML(open(url) )
  puts doc.css("title").text
  doc.css(".a").each do |item_info|
    title = item_info.text
    href = item_info['href']
    save_post(title, href)
  end
end

答案 1 :(得分:3)

如果您在rake任务中定义方法,则它们可以全局访问,这可能会产生不良副作用。更简洁的方法是使用内联lambda(或将方法移动到应用程序中的某个类)

task :fetch_post => :environment do
  require 'nokogiri'
  require 'open-uri'

  save_post = ->(title, href) {
    post = Post.new(title: title, url: href)
    if post.save
      puts title + 'saved'
    else
      puts title + 'not saved'
    end
  }

  url = 'http://example.com'
  doc = Nokogiri::HTML(open(url) )
  puts doc.css("title").text
  doc.css(".a").each do |item_info|
    title = item_info.text
    href = item_info['href']
    save_post.call(title, href)
  end

end

答案 2 :(得分:2)

您应该在任务之前和之外定义方法:

task :fetch_post => :environment do
  require 'nokogiri'
  require 'open-uri'

  url = 'http://example.com'
  doc = Nokogiri::HTML(open(url) )
  puts doc.css("title").text
  doc.css(".a").each do |item_info|
    title = item_info.text
    href = item_info['href']
    save_post(title, href)
  end
end

def save_post(title, href)
  post = Post.new(title: title, url: href)
  if post.save
    puts title + 'saved'
  else
    puts title + 'not saved'
  end
end

但我认为这种逻辑应该在模型中。

#app/models/post.rb

class Post < ActiveRecord::Base

  def self.save_post(title, href)
    post = Post.new(title: title, url: href)
    if post.save
      puts title + 'saved'
    else
      puts title + 'not saved'
    end
   end
 end