Specifying the host in Rails performance tests - ruby-on-rails

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

Related

Rails undefined local variable or method `first' for ActiveRecord::NullMutationTracker:Class on local

We are getting this error on all local setups of our project(currently) when we call any method like:
belongs_to :abc
after_create :some_method
def some_method
if self.abc.saved_change_to_parent_id?
...
// or even self.abc.parent_id_before_last_save
end
It gives:
NameError (undefined local variable or method `first' for ActiveRecord::NullMutationTracker:Class):
app/models/model_name.rb:50:in `some_method'
Yes, there is not a full trace with rails internal file paths etc, i only get my project files trace. Maybe its some logger config issue, any help to get full trace will also be appreciated.
There are no such issues i could find on internet, thats why posting here.
PS: Not posted on rails issue tracker(github issues) because i don't have minimal reproduction.
Stack
ruby: 2.4.3
rails: 5.1.5 (also tried on 5.1.7)
OS: Ubuntu 20, also tried on macOS
Thanks in advance.
UPDATE1: Using byebug, i got to this trace, where error is occuring:
/Users/dev/.rvm/gems/ruby-2.4.3/gems/acts_as_singleton-0.0.8/lib/acts_as_singleton.rb:43
which is here, so it is not directly from rails, but a very outdated gem we have in our code for some reason.
As i posted in the update, issue was not with rails or anything, i used byebug to track trace and it was something like:
activemodel-5.1.5/lib/active_model/attribute_methods.rb:384
activerecord-5.1.5/lib/active_record/attribute_methods/dirty.rb:146
activerecord-5.1.5/lib/active_record/attribute_methods/dirty.rb:319
activerecord-5.1.5/lib/active_record/attribute_methods/dirty.rb:315
acts_as_singleton-859f49112c03/lib/acts_as_singleton.rb:43
The last line, should not be there, as we are not using acts_as_singleton on any of the involved models.
So after some tracking, it turned out issue with the gem. I have created a fork and used that fork. Here is the fork: https://github.com/ziaulrehman40/acts_as_singleton (forked it from another fork, which seemingly had some other fixes as well). And you can see my changes here.
What was the issue?
This gem writes a module named Singleton within ActiveRecord module. Which seems ok, unless you realize that there is another module named Singleton already. Whihc is being included in:
gems/activerecord-5.1.5/lib/active_record/attribute_mutation_tracker.rb:83
class NullMutationTracker # :nodoc:
include Singleton
...
So as you can see, this Singleton module gets overriden(or expanded, not sure) un-intentionally by that outdated gem(acts_as_singleton).

Handle a response code in test without polluting ApplicationController

My problem is that we're receiving mysterious 504 errors in SolanoCI, and I'm trying to find a clean way to handle them only in the test environment without adding test-specific code to our ApplicationController.
I've tried stubbing a default handler via the test setup like so:
allow(ApplicationController).to receive(:timeout).and_return {
#do a bunch of stuff to try to pull out request information
}
but I'm finding that it's lacking some important information that's accessible, like the original request url and any stacktrace information.
Any suggestions are welcome.
I think the easiest way for you in this situation would be to ask Solano to run a debugging session on their box for you (they give you ssh access to their server, so you may run tests yourself).
This is a real time saver in a black box situations like this. You may run tests multiple times and use all sorts of debugging tools there. You may have to install them first, since Solano tries not to install extra tools from your Gemfile (such as pry) to minimize test's running time.
Just write them via a contact form and they will give you an access. Don't forget to stop that session after you've done with it, since the time it runs is deducted from worker hours in your plan.
Hope it helps.
EDIT: It seems Anonymous controller feature is perfect for your case:
Use the controller method to define an anonymous controller that will
inherit from the described class. This is useful for specifying
behavior like global error handling.
So, you can do something like this:
RSpec.describe ApplicationController, :type => :controller do
controller(ApplicationController) do
rescue_from Timeout::Error, :with => :log_timeout
def log_timeout(error)
# log error as you wish
end
end
describe "handling timeout exceptions" do
it "writes some logs" do
get :index
expect(response).to have_https_status(504)
end
end
end

How to extend the String class in a command line app?

I primarily work in Rails and I'm using a command line data conversion gem, "Mongify" and I am stumped about how to extend core classes in a Ruby cli app.
I want to extend the String class with an .is_date? method to check whether a string can be converted to a Date. I've got it working in the Rails Console,
I added a string.rb file to lib/ext with the following;
class String
def is_date?
begin
return true if Date.parse(self)
rescue
#do nothing
end
return false
end
end
Then in a Rails console I do a require 'ext/string' and it will work.
But I can't figure out how to get it to work in the Mongify cli app. I copied string.rb into the lib folder of the gem and I've tried adding require 'string' to a number of different files in the gem, but I keep getting undefined method errors.
Can someone point me in the right direction?
How about you require it from lib/mongify.rb like so:
require 'string/extensions.rb'
And then put your code in lib/string/extensions.rb
Let us know the exact undefined method errors you're getting in case this isn't the solution.
To help you with the debugging exercise that would give you the answer you need. Start by putting a breakpoint right before the place of the function call.
In the debugger, load the required document and then step past your breakpoint to the next one after the call has occurred.
Once you have this working, then start earlier in the stack trace – in a file that loaded before that one. Keep moving backwards until you get to a sufficiently early part in the load process of the gem, and make that be the place you load your code.

Running an EventMachine inside of script/runner

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.

First Call to a Controller, Constant is defined, Second call, "uninitialized constant Oauth"?

I am trying to get the OAuth gem to work with Rails 3 and I'm running into this weird problem... (independent of the gem, I think I've run into this once before)
I have a controller called "OauthTestController", and a model called "ConsumerToken". The model looks like this.
require 'oauth/models/consumers/token'
class ConsumerToken < ActiveRecord::Base
include Oauth::Models::Consumers::Token
end
When I go to "/oauth_test/twitter", it loads the Oauth::Models::Consumers::Token module and I'm able to connect to twitter no problem. But the second time I try it (just refresh the /oauth_test/twitter url), it gives me this error:
NameError (uninitialized constant Oauth):
app/models/consumer_token.rb:4
app/models/twitter_token.rb:2
app/controllers/oauth_test_controller.rb:66:in `load_consumer'
Why is that? It has something to do with load paths or being in development mode maybe?
Try using require_or_load instead of require. That forces full load each time when in development and can sometimes help with this sort of issue.
Yeah it's something to do with being in development mode. Setting config.cache_classes = true in your development.rb get's it working (but is a pain in the ass)

Resources