Running an EventMachine inside of script/runner - ruby-on-rails

I successfully used em-dir-watcher as shown in its example.rb file from the command line, but I found myself needing to call a method from another class and so I opted to go the script/runner route instead, invoking rails.
I copy/pasted the example code and placed inside of a self.methodName and encountered this error:
myapp/vendor/rails/railties/lib/commands/runner.rb:48: undefined method `watch' for EventMachine:Module (NoMethodError)
Even if I run something totally simple like:
def self.watcher
EM.run {
dw = EMDirWatcher.watch '.' do |paths|
paths.each do |path|
puts path
end
end
puts "Monitoring"
}
end
and invoke script/runner:
script/runner "require 'rubygems'; require 'em-dir-watcher'; Myclass.watcher"
I still get the error. What am I doing wrong?

After spending another day trying to sort through the stack, I've concluded that there's some inherently weird interaction between em-dir-watcher and script/runner. After moving over to another eventmachine-based gem that could do the same task (directory_watcher), everything worked great.
I know that there are performance and feature tradeoffs between the two gems, but for my purposes, I don't notice a difference.

Related

How to Find a String in a Directory of Files Using grep and glob?

So I've been messing with this for the last hour and a half or so and just can not figure out how to do this.
In my Ruby test.rake file, which gets called from another project after a Snapshot Gem is created, I need to check to see if a dependency for Capybara exists in the Rakefile for the other project, since we have since deprecated Capybara and are replacing it with something else.
So, I included a simple check to see if the project contains Feature/Capybara tests, and if so, to scan through each spec test and see if it has dependency for Capybara in it, and if so log a warning to tell the user that Capybara has been deprecated.
My problem is, I can not get this to work at all. When I attach this to a Jenkins job and run it, I keep getting the unexpected Print statement in the else clause.
Am I missing something here? From what I understand, my code is doing the following things:
Checking if the spec/features directory exists
Using glob to select all of the files in the directory that end with .rb (Spec tests), with each file instance being assigned to file
Take the current instance of file, read each line of it, and use grep to find any instances of the word "capybara" in them, and print out the right message if found.
Else, if the word is NOT found, print the error message in the else clause.
I'm somewhat new to Ruby so I feel like maybe I am missing something with the syntax, but other than that I'm stumped! Any help would be greatly appreciated! Here is what the code and the Rakefile I am trying to parse through look like:
test.rake:
if Dir.exist?('spec/features')
path = 'spec/features/'
Dir.glob(path + '*.rb') {|file|
if File.readlines(file).grep(/capybara/).any?
print "The capybara dependency has been found!"
else
print "SOMETHING WENT WRONG"
end
}
end
Rakefile:
#!/usr/bin/env rake
# frozen_string_literal: true
require 'roll_out/rake_tasks'
require 'roll_out/security'
require 'roll_out/jira'
require 'REDACTED/philter/lint_results'
require 'roll_out/capybara'
load 'REDACTED/tasks/REDACTED.rake'
Your code looks almost good except .each missing
i did my test and it works fine.
Dir.glob('spec/features/*.rb').each do |f|
puts 'haha' if File.readlines(f).any?{|line| line.include?('capybara')}
end

Specifying the host in Rails performance tests

I have been trying to use the Rails profiling tools. I am using a very simple example taken from the docs at http://guides.rubyonrails.org/performance_testing.html that looks like this
require 'test_helper'
require 'rails/performance_test_help'
# Profiling results for each test method are written to tmp/performance.
class BrowsingTest < ActionDispatch::PerformanceTest
def test_homepage
get '/'
end
end
I then run the test using
rake test:profile
but it crashes with the following error
Error during failsafe response: undefined method `controller_name' for nil:NilClass
I suspect that the problem is that the app serves multiple domains and so simply using get '/' is not enough information to resolve the url back to a controller/action - it needs a host as well. However the usual ways of specifying a host (#host, #request.host, default_url_options[:host]) either don't work or cause another error (eg #request is nil).
I have also tried entering the full url. I have the different hosts defined as constants in the test environment so this looked something like
get "http://#{HOST_1}/"
In this case the rake task completed successfully but no profiling information appeared on the command line and no files were generated.
I haven't really used the profiling tools in Rails much so I am hoping I am missing something obvious. Any pointers would be much appreciated.
Cheers

How can I override a method in a ConnectionAdapter class in Rails 3 for use in a rake task?

In order to override the table_exists? method in the Rails PostgreSQL adapter I have tried the following in an initializer file:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
def table_exists?(name)
raise 'got here'
end
end
This will raise the the following error:
uninitialized constant ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
I believe this would have worked in previous versions of rails and I even found a small plugin that did something like this in Rails 2.3.6. Also I only encounter this error when I am trying to run a rake task like db:migrate and not when I start my application server.
Could someone show me the right way to do this and / or explain why PostgreSQLAdapter doesn't seem to be loaded when I am in an initializer file?
Instead of config/initializers, place that code in lib/ folder.
While this means that the active_record is loaded after the rails initializers, which is unusual. I ll update this with more detail, once I am done investigating the whole flow. If you want some more details about the rails 3 initialization process, check out this link:
http://ryanbigg.com/guides/initialization.html
I had success by moving this code into a Rails plugin. It is a little bit more overhead, but it is working consistently when I run rails s and when I run rake db:migrate.
I just followed the rails guide page on the topic and ran
rails generate plugin rails_patches --with-generator
and moved my init.rb file into rails as recommended.
~vendor/
`~plugins/
`~rails_patches/
|~lib/
| `-rails_patches.rb
|~rails/
| `-init.rb
|+test/
|-install.rb
|-MIT-LICENSE
|-Rakefile
|-README
`-uninstall.rb
I put this code in init.rb:
require 'rails_patches'
I put this code in rails_patches.rb:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
def table_exists?(name)
raise 'got here'
end
end
This now behaves as I expected.

Ruby on rails, run a method on server start 2.3

I want to run a method, on the startup of the rails server. It's a model method.
I tried using config/initializers/myfile.rb, but the method was invoked during migrations, so it SELECTed from a nonexistant table.
Tried environment.rb also, but the class does not exist yet (and will probably have the same problem with migrations)
I don't know where to put that method, so it'll run only on server startup and not during migrations.
There are some things you could do to actually improve this a bit. The issue is that you are running this code when rake loads your environment, but you really only want to run this when the environment is loaded by an instance of your web server. One way to get around this is to set a value when rake loads your environment, and when that value is set, to not execute your initializer code. You can do this as follows:
task :environment => :disable_initializer
task :disable_initializer do
ENV['DISABLE_INITIALIZER_FROM_RAKE'] = 'true'
end
#In your initializer:
ENV['DISABLE_INITIALIZER_FROM_RAKE'] || MyModel.method_call
There is no way to avoid this from my understanding. You can put the initializer code that relies on the new table in a rescue block to quiet things down so others can run migrations.
Try putting your method call in boot.rb, in the run method after the Rails::initializer call. I don't have rails in front of me right now because I'm at work but I think that the whole environment should be loaded by that point and you can run methods on the framework.
I found this to work quite well:
if File.basename($0) == "rails" && ARGV == []
It also detects "rails generate .."

How do I use a custom log for my rake tasks in Ruby on Rails?

I have a rake task that calls functions like this:
namespace :blah do
task :hello_world => :environment do
logger.info("Hello World")
helloworld2
end
end
def helloworld2
logger.info("Hello Again, World")
end
I want the log output to a custom log, and I really don't want to have to pass a log reference every time I make a function call. I found this somewhere (can't find it again):
def logger
##logger ||= Logger.new("#{RAILS_HOME}/log/blah.log")
end
But this does not work for me and I am not sure what it even does because I grabbed the code a long time ago and haven't used it until now. I can't search for ## on google (tried +"##" rails) to see what it does. Any help on this issue would be great. I am hoping for a quick solution and not having to install a gem or plugin (unless there is a really really good reason to.
Thanks!
rake disables logging in production mode. make sure you're running in development mode if you want it to log
What do you mean by "does not work for me"? I just tried this same code and it worked - created a new log file and put some text in it.
##logger is a class variable, it's a language issue, not Rails' one. I believe there's no need in further explanations :)
You've probably mistaken typing "function helloworld2" :)
Advanced Rails Recipes Recipe 84 from #topfunky shows how to define a custom logger. He has some code in the environment config file (production would look like this): RAILS_ROOT/config/environments/production.rb:
config.logger = RAILS_DEFAULT_LOGGER = Logger.new(config.log_path)
I'd test that out instead of redefining the class variable as you have. He might have something on http://nubyonrails.com to check as well.

Resources