Rake task works in development, but not in production - ruby-on-rails

I've got a rake task that changes data on the homepage every few hours. I've tested it out and it works fine in development. But it doesn't work in production. What do I have to do to get the changes I want to see? Should I add a command that restarts the server? Would that make the server acknowledge the change? Is there a smarter way to do this?
The rake task is below. It'll be run by heroku's scheduler add on, so it's currently in the lib/tasks/scheduler.rake file.
desc 'changes the meta tags'
task :mixup_meta_tags => :environment do
regex = /#meta_tag/
file = File.open('app/controllers/site_controller.rb', 'r')
lines = []
file.each_line do |line|
(line =~ regex) ? (lines << replace_line(line)) : (lines << line)
end
file.close
file = File.open('app/controllers/site_controller.rb', 'w')
lines.each{|line| file.write line}
file.close
end
def replace_line(line)
meta_tags = MetaTag.all.map { |tag| tag["tag"] }
new_tag = meta_tags.sample(1)[0]
line = " #meta_tag = \"#{new_tag}\" \n" # added the newline
end

Yes, changes to your Rails application in Production require a restart for them to get picked up by the server. To get this to work on the fly you might want to try the solution mentioned in this post why-does-code-need-to-be-reloaded-in-rails-3

Related

Disable db/schema.rb comments in Rails application

I've been getting sick of seeing the "helpful" comments in the db/schema.rb after each migration. I've figured out how to disable it.
To stop this from happening create the following file in lib/tasks/schema_cleanup.rake (note the .rake):
namespace :db do
def cleanup_schema
filename = "db/schema.rb"
schema = File.read(filename)
.split("\n")
.select { |l| not l.strip.starts_with? "#" }
.slice(1..-1)
.push("")
.join("\n")
File.open(filename, 'w') do |file|
file.write(schema)
end
end
task :migrate do
cleanup_schema
end
end
Now each time you run the command the comments will be removed.

My Ruby script (automated using Whenever gem) isn't running..what am I doing wrong?

The script is in the file fxrates_scraper.rb, code below.
The scheduler i'm using is in the schedule.rb file, code below.
I'm using the whenever gem, and when i type in 'bundle exec whenever' i see the task as scheduled, it seems fine. but it doesn't work: it isn't executing the script.
what am I doing wrong? note i haven't setup capistrano or anything, i just want the script to run on my local drive. also: when i execute the script manually, it runs just fine. it's just the automation bit that isn't working.
FXRATES_SCRAPER.RB
require 'open-uri'
require 'nokogiri'
require 'csv'
# Store URL to be scraped
url = "https://deliveroo.co.uk/restaurants/london/maida-vale?postcode=W92DE"
# Parse the page with Nokogiri
page = Nokogiri::HTML(open(url))
# Display output onto the screen
name =[]
page.css('span.list-item-title.restaurant-name').each do |line|
name << line.text.strip
end
category = []
page.css('span.restaurant-detail.detail-cat').each do |line|
category << line.text.strip
end
delivery_time = []
page.css('span.restaurant-detail.detail-time').each do |line|
delivery_time << line.text.strip
end
distance = []
page.css('span.restaurant-detail.detail-distance').each do |line|
distance << line.text.strip
end
status = []
page.css('li.restaurant--details').each do |line|
if line.attr("class").include? "unavailable"
sts = "closed"
else
sts = "open"
end
status << sts
end
# Write data to CSV file
CSV.open("deliveroo.csv", "w") do |file|
file << ["Name", "Category", "Delivery Time", "Distance", "Status"]
name.length.times do |i|
file << [name[i], category[i], delivery_time[i], distance[i], status[i]]
end
end
SCHEDULE.RB
set :output, "#{path}/log/cron.log"
every 2.minutes do
command "ruby '#{path}/fxrates_scraper.rb'"
end
OUTPUT FROM RUNNING 'BUNDLE EXEC WHENEVER' COMMAND
Faisals-Air:whatrate fkhalid2008$ bundle exec whenever
0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'ruby '\''/Users/fkhalid2008/whatrate/fxrates_scraper.rb'\'' >> /Users/fkhalid2008/whatrate/log/cron.log 2>&1'
## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
Running 'whenever -i' command fixed this.
IMO, you have to set environment when run whenever:
bundle exec whenever --update-crontab --set environment='development'

Ruby I/O: Rails rake task is trying to find and replace certain lines of code, but doesn't

I'm working on a rake task that changes the meta tags for certain pages. These tags are defined in the controller. The rake task is meant to open the controller file, find any line with the phrase "#meta_tag" in it, and then re-write that line per the replace_line(line) method. When I run the rake task, I don't get any errors, but it also doesn't make any changes.
I think my problem is in the 'r+' line. Do I need to open the file in one line and write to it in another line of code?
require 'rake'
namespace :meta_tags do
desc 'changes the meta tags'
task :update => :environment do
regex = /#meta_tag/
found = false
file = File.open('app/controllers/site_controller.rb', 'r+')
file.each_line do |line|
replace_line(line) if(found)
found = true if(line =~ regex)
end
end
def replace_line(line)
meta_tags = MetaTag.all.map { |tag| tag["tag"] }
new_tag = meta_tags.sample(1)[0]
line = "#meta_tag = #{new_tag}"
end
end
If you see what I'm doing wrong, please let me know.
Well you don't actually write to the file anywhere. each_line does just what it says, it iterates over each line in the file (actually it reads until there is a newline and then yields this line to the block you provide).
But just using file.write now isn't a really good idea since inplace file-writing doesn't work like you would expect. Because files are byte/character based, a replacementline would have to be exactly as long as the old one.
So you should go with the normally used practice of reading then writing. Also your current code would alter the line after the
#meta_tag occurrence, although your question suggests that this is not what
you want.
Here is an example applied to your situation:
require 'rake'
namespace :meta_tags do
desc 'changes the meta tags'
task :update => :environment do
regex = /#meta_tag/
# only 'r' since you will only read the file,
# although you could use 'r+' and just change the lineno
# back to 0 when finished reading...
file = File.open('app/controllers/site_controller.rb', 'r')
lines = []
file.each_line do |line|
# i don't think you need the found variable,
# it is simple if-then/else
(line =~ regex) ? (lines << replace_line(line)) : (lines << line)
end
file.close
file = File.open('app/controllers/site_controller.rb', 'w')
# you could also join the array beforehand,
# and use one big write-operation,
# i don't know which approach would be faster...
lines.each{|line| file.write line}
file.close
end
def replace_line(line)
meta_tags = MetaTag.all.map { |tag| tag["tag"] }
new_tag = meta_tags.sample(1)[0]
line = "#meta_tag = #{new_tag}\n" # added the newline
end
end

Creating Database Values in a Rake Task - Rails

I have the following script, which I want to automatically update my database.
require 'feedzirra'
require 'sanitize'
namespace :db do
task :update_pitzer => :environment do
feed = Feedzirra::Feed.fetch_and_parse('http://www.cafebonappetit.com/rss/menu/219')
feed.entries.each do |entry|
date = Sanitize::clean(entry.title)
summary = Sanitize::clean(entry.summary)
summary.gsub!(/\s{2}/, " ").to_s
summary.gsub!(/\s{2}/, "").to_s
summary.gsub!("&", "&")
puts "#{date}"
theDay = Day.create(date: date)
#theDay.collins_meals.create()
array = summary.split(/\[/)
array.collect! {|x| "[" + x}
array.reject! {|x| x == "[ "}
array.to_s
puts array
end
end
end
When I run rake db:update_pitzer at the command line, I get:
(in /Users/Alex/rails_projects/dining_hall_api)
rake aborted!
Don't know how to build task 'db:update_pitzer'
Thoughts?
Code seems proper. Make sure you have put 'update_pitzer.rb' file under 'lib/tasks' folder in your rails application

Ruby script to save records into Rails

I am trying to run a ruby script that parses a text file with album name, artist name, year on each line. It should then save a new record into a Rails model called Album.
(buildDB.rb)
fh = File.open('albums.txt')
while line = fh.gets
if ( line =~ /^(.+)\~\s(.+) \(\'(\d\d)\)/ )
a = Album.new
a.name = $1
a.artist = $2
a.year = $3
a.save
end
end
I am running ruby buildDB.rb in terminal which produces the message
buildDb.rb:12:in '<main>': uninitialized constant Album (NameError)
This made me think that the script could not find the model. So I tried loading the rails environment by using
require "C:/ruby192/www/Project02/config/environment.rb"
at the top of the ruby script. The script will run without errors but nothing is committed to the sqlite database. I can also run find on the already existing Albums, it just seems I can't create new ones.
I am a rails noob so, there probably is a better way to do this (seeds.rb or a rake task maybe). Any help or a direction to look into would be greatly appreciated.
I would use a rake task:
task :create_albums => :environment do
fh = File.open('albums.txt')
while line = fh.gets
if ( line =~ /^(.+)\~\s(.+) \(\'(\d\d)\)/ )
a = Album.new
a.name = $1
a.artist = $2
a.year = $3
a.save!
end
end
fh.close
end
I added a ! to the save method so that any errors will throw an exeception. Also, make sure you close your files.
Rake task is the way ahead. I would use FasterCSV as it will handle some of the data import for you.
namespace :import do
desc "Import from a csv file"
task :album_csv, [:filename] => :environment do |task, args|
lines = FasterCSV.read(args[:filename]) rescue nil
if lines
lines.slice!(0) # remove the CSV header if there is one
puts "# Processing #{lines.count} records"
lines.each do |line|
a = Album.new
a.name = line[0]
a.artist = line[1]
a.year = line[2]
a.save!
end
end
end
You can then call your rake task as:
rake import:album_csv[filename]

Resources