Ruby Daemons causing ActiveRecord logger IOError - ruby

I'm writing a project at the moment in Ruby which makes use of the ActiveRecord gem for database interaction and I'm trying to log all the database activity using the ActiveRecord::Base.logger attribute with the following code
ActiveRecord::Base.logger = Logger.new(File.open('logs/database.log', 'a'))
This works fine for migrations etc (which for some reason seem to require that logging be enabled as it gives a NilClass error when it's disabled) but when I try to run the project which includes a threaded daemon calling the ActiveRecord object the script fails with the following error
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/logger.rb:504:in `write': closed stream (IOError)
Any ideas on how to solve this problem would be greatly appreciated. For the moment I've started to look through other code to see if people have other ways of implementing ActiveRecord logging in a more thread-safe manner
Thanks
Patrick

I ran into the same issue. You need to daemonize first, and then load the Rails environment.

the delayed_job have used daemons and activerecord,
before daemonize,get the files have opend,and then reopen in daemonize
#files_to_reopen = []
ObjectSpace.each_object(File) do |file|
#files_to_reopen << file unless file.closed?
end
Daemons.run_proc("xxxxx_name",:dir=>pid_file,:dir_mode=>:normal) do
Dir.chdir(Rails.root)
# Re-open file handles
#files_to_reopen.each do |file|
begin
file.reopen file.path
file.sync = true
rescue ::Exception
end
end
end

It turns out that for migrations to work the ActiveRecord::Base.logger variable cannot be nil, which explains the first half of the problem. I am as yet unable to fix the IOError though when a file is used instead of STDERR.

Related

Rails 4 Delayed_job error - Job failed to load: undefined class/module CustomJob

I've spent several days on this and about 100 hours but can't get the fix.
Here's my setup (using Rails 4.2.8)
class CustomJob < ActiveJob::Base
def perform(*args)
filename = args.first
data = File.read(filename)
# process that data
end
end
When I run Delayed::Job.enqueue CustomJob.new('filename'), I get the error mentioned in the subject. The job is created and added to the db, but the error message is "Job failed..."
I have this line:
require 'custom_job'
in several places including script/delayed_job.rb, config/initializers/delayed_jobs.rb, config/initializers/custom_job.rb and the file in which I'm calling the job.
I also added this:
config.autoload_paths+=Dir[Rails.root.join('app','jobs')]
config.active_job.queue_adapter = :delayed_job
to my config/application.rb file
And this:
config.threadsafe! unless defined? ($rails_rake_task) && $rails_rake_task
I've also restarted my server after every change. And verified that delayed_job was running using:
dir$ RAILS_ENV=development script/delayed_job status
delayed_job: running [pid 64503]
Sources:
delayed_job fails jobs when running as a daemon. Runs fine when using rake jobs:work
DelayedJob: "Job failed to load: uninitialized constant Syck::Syck"
Rails Custom Delayed Job - uninitialized constant
model classes not loading in Delayed Job when using threadsafe
Can you also try adding this line into config/application.rb file
config.eager_load_paths+=Dir[Rails.root.join('app','jobs')]
I always feel like the answer is obvious...AFTER I figure it out.
The problem was that I was using a shared database and there were existing workers accessing this DB. Though I was restarting and refreshing my local instance of the server, the other instances were trying to run my jobs and the OTHER workers were causing the error, not my local instance.
Solution: Ensure that other instances of delayed_job are using the same table as the code you're testing/building/using. If so, use another DB if possible.

Database cleaner not working with vim-rspec plugin

I use vim-rspec plugin to be able to run rspec tests from within vim, and it was working very well so far. But suddenly the database_cleaner gem stopped working.
Here is my configuration:
# spec/rspec_rails.rb
Rspec.configure do |config|
config.before(:suite) do
puts "Setting up the database cleaner."
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
puts "Cleaning the database"
DatabaseCleaner.cleaning do
example.run
end
end
end
I put those two messages to find out if the two blocks run. but they don't. Even if I stop spring than I run again it does not correct it. The strange thing is that if I run the rspec command from the command line every thing works well and I get both of the messages and the database cleaned, the first one time on running, and the second on every example run.
Problem might be in spring itself, remove it and try again. Also you can take a look at a g:rspec_command in your .vimrc file, maybe you bind any specific script to it?

Why won't my Rails function abort?

I'm trying to debug an application that someone else wrote. In my production.log, I see:
Processing by Friendster::AppsController#home as HTML
Parameters: {SOMESTUFF}
Completed 500 Internal Server Error in 3ms
So I go to the app/controller/friendster/apps_controllers and look at the home function and it is:
def home
show_app_container
end
So I changed it to:
def home
puts "container"
abort "SHAMOON"
show_app_container
end
Just so I can see some sort of error or log. But nothing shows up anywhere. Nothing renders differently. I don't know if there's caching going on or if I'm in the right function. Any help debugging this would be greatly appreciated.
I also ran a bundle exec rake routes and got:
friendster_app_home POST /publishers/:publisher_id/apps/:app_id/home(.:format) {:action=>"home", :controller=>"friendster/apps"}
GET /publishers/:publisher_id/apps/:app_id/home(.:format) {:action=>"home", :controller=>"friendster/apps"}
Although there are quite a few routes with GET /publishers/:publisher_id/apps/:app_id/home(.:format), so I'm not sure what that means. This is the only friendster one.
EDIT: Adding Base controller parent
class Friendster::BaseController < AppsController
protected
end
Any help debugging this would be greatly appreciated.
Include the pry gem, call binding.pry inside of #home and Pry will spawn an interactive debugger in the console.
def home
binding.pry
show_app_container
end

What is ths error in Ruby Watir (WIN32OLERuntimeError: unknown property or method `document')?

I have this code in Ruby waitr ..
$LOAD_PATH.unshift File.join(File.dirname(__FILE__),'..') if $0 == __FILE__
require 'test/unit'
require 'Watir'
require 'Watir/contrib/enabled_popup'
class TC_Dialog_Test<Test::Unit::TestCase
$ie=Watir::IE.new
$ie.bring_to_front()
$myDir = File.expand_path(File.dirname(__FILE__))
def setup
$ie.goto "file://#{$myDir}/aa.html"
end
def test_confirm_OK
sleep(3)
$ie.button(:id, 'btnConfirm').click_no_wait
$hwnd = $ie.enable_popup(5)
if ($hwnd)
$popup =WinClicker.new
$popup.makeWindowsActive($hwnd)
sleep(3)
# $popup.clickWindowsButton($hwnd,"OK")
puts "you pressed Comfirm-ok"
sleep(3)
end
end
end
when runnung this code get this error results ...
test_confirm_OK(TC_Dialog_Test):
WIN32OLERuntimeError: unknown property or method `document'
HRESULT error code:0x800706b5
The interface is unknown.
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/ie.rb:417:in `method_missing'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/ie.rb:417:in `document'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/container.rb:767:in `ole_inner_elements'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/container.rb:838:in `locate_input_element'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/input_elements.rb:10:in `locate'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:47:in `assert_exists'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:278:in `enabled?'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:53:in `assert_enabled'
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.5.3/./watir/element.rb:214:in `click_no_wait'
Mo.rb:16:in `test_confirm_OK'
You are using Watir 1.5.3, but the current stable is 1.8.1. I suggest you to update your gem to the latest and try again. There is a good chance that the WIN32OLE object for IE has changed it's behavior and old gem is conflicting with it. (Have you updated IE or smth since last successful run?)
I got the same error using Watir 1.8.1. I don't know if there is anything wrong with your code, but in my case the tests ran fine on other machines.
I am running my tests in RubyMine 3.1.x. Running RubyMine as Administrator allowed Ruby to have the rights to interact with IE properly and the problem went away.
Edit:
Found the forum post which originally helped me solve the problem.

Testing a rake task in rspec (and cucumber)

I'm new to Ruby, and I've been trying to learn Rake, RSpec, and Cucumber. I found some code that will help me test my Rake tasks, but I'm having trouble getting it to work. I was told here: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ to drop this:
def describe_rake_task(task_name, filename, &block)
require "rake"
describe "Rake task #{task_name}" do
attr_reader :task
before(:all) do
#rake = Rake::Application.new
Rake.application = #rake
load filename
#task = Rake::Task[task_name]
end
after(:all) do
Rake.application = nil
end
def invoke!
for action in task.instance_eval { #actions }
instance_eval(&action)
end
end
instance_eval(&block)
end
end
into my spec_helper.rb file.
I've managed to take this code out and run it in my cucumber steps like this:
When /^I run the update_installers task$/ do
#rake = Rake::Application.new
Rake.application = #rake
load "lib/tasks/rakefile.rb"
#task = Rake::Task["update_installers"]
for action in #task.instance_eval { #actions }
instance_eval(&action)
end
instance_eval(&block)
Rake.application = nil
end
but when I try to get things working in rspec, I get the following error.
ArgumentError in 'Rake task
install_grapevine should install to
the mygrapevine directory'
wrong number of arguments (1 for 2)
/spec/spec_helper.rb: 21:in instance_eval'
/spec/spec_helper.rb: 21:inblock in invoke!'
/spec/spec_helper.rb: 20:in each'
/spec/spec_helper.rb: 20:ininvoke!'
/spec/tasks/rakefile_spec.rb:12:in `block (2 levels) in
'
Unfortunately, I've got just under a week of ruby under by belt, so the metaprogramming stuff is over my head. Could anyone point me in the right direction?
This works for me: (Rails3/ Ruby 1.9.2)
When /^the system does it's automated tasks$/ do
require "rake"
#rake = Rake::Application.new
Rake.application = #rake
Rake.application.rake_require "tasks/cron"
Rake::Task.define_task(:environment)
#rake['cron'].invoke
end
Substitute your rake task name here and also note that your require may be "lib/tasks/cron" if you don't have the lib folder in your load path.
I agree that you should only do minimal work in the Rake task and push the rest to models for ease of testing. That being said I think it's important to ensure that the code is ACTUALLY run in my cron tasks during my integration tests so I think very mild testing of the rake tasks is justified.
Since testing rake is just too much for me, I tend to move this problem around. Whenever I find myself with a long rake task that I want to test, I create a module/class in lib/ and move all the code from the task there. This leaves the task to a single line of Ruby code, that delegates to something more testable (class, module, you name it). The only thing that remains untested is whether the rake task invokes the right line of code (and passes the right parameters), but I think that is OK.
It might be useful to tell us which is the 21nd line of your spec_helper.rb. But given that the approach you posted digs deep in rake (referring to its instance variables), I would entirely abandon it for what I suggested in the previous paragraph.
I've just spent a little while getting cucumber to run a rake task so I thought I'd share my approach. Note: This is using Ruby 2.0.0 and Rake 10.0.4, but I don't think the behaviour has changed since previous versions.
There are two parts to this. The first is easy: with a properly set up instance of Rake::Application then we can access tasks on it by calling #[] (eg rake['data:import']). Once we have a task we can run it by calling #invoke and passing in the arguments (eg rake['data:import'].invoke('path/to/my/file.csv').
The second part is more awkward: properly setting up an instance of Rake::Application to work with. Once we've done require 'rake' we have access to the Rake module. It already has an application instance, available from Rake.application, but it's not yet set up — it doesn't know about any of our rake tasks. It does, however, know where to find our Rakefile, assuming we've used one of the standard file names: rakefile, Rakefile, rakefile.rb or Rakefile.rb.
To load the rakefile we just need to call #load_rakefile on the application, but before we can do that we need to call #handle_options. The call to #handle_options populates options.rakelib with a default value. If options.rakelib is not set then the #load_rakefile method will blow up, as it expects options.rakelib to be enumerable.
Here's the helper I've ended up with:
module RakeHelper
def run_rake_task(task_name, *args)
rake_application[task_name].invoke(*args)
end
def rake_application
require 'rake'
#rake_application ||= Rake.application.tap do |app|
app.handle_options
app.load_rakefile
end
end
end
World(RakeHelper)
Pop that code into a file in features/support/ and then just use run_rake_task in your steps, eg:
When /^I import data from a CSV$/ do
run_rake_task 'data:import', 'path/to/my/file.csv'
end
The behavior might have changed since the correct answer was posted. I was experiencing problems executing two scenarios that needed to run the same rake task (only one was being executed despite me using .execute instead of .invoke). I thought to share my approach to solve the issue (Rails 4.2.5 and Ruby 2.3.0).
I tagged all the scenarios that require rake with #rake and I defined a hook to setup rake only once.
# hooks.rb
Before('#rake') do |scenario|
unless $rake
require 'rake'
Rake.application.rake_require "tasks/daily_digest"
# and require other tasks
Rake::Task.define_task(:environment)
$rake = Rake::Task
end
end
(Using a global variable is suggested here: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)
In the step definition I simply called $rake
# step definition
Then(/^the daily digest task is run$/) do
$rake['collector:daily_digest'].execute
end
Any feedback is welcome.

Resources