Reputation: 21513
In my task file post.rake
, I want to reuse a function
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
However, when I define it in this file and re-use it, it returns
NoMethodError: undefined method `save_post' for main:Object
The post.rake
looks like this:
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
The content-scraping part works. I just move the post-saving code out, wanting to abstract the method out.
Where should I put the def method
?
Upvotes: 4
Views: 5199
Reputation: 933
OOOH~~~,function postion is wrong, like this, it works:
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
Upvotes: 4
Reputation: 44360
You should define method before and outside of task:
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
But i think this logic should be in model.
#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
Upvotes: 1
Reputation: 230286
If you define methods in a rake task, they become accessible globally, which may have undesired side-effects. A cleaner approach is to use an inline lambda (or move the method to some class in the app)
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
Upvotes: 8