org.jruby.exceptions.RaiseException: (NameError) uninitialized constant - ruby

I'm getting the following error from a JRuby wrapping of the ActiveMerchant library:
org.jruby.exceptions.RaiseException: (NameError) uninitialized constant ActiveMerchant::Billing::SecurePayAuGateway
at org.jruby.RubyModule.const_missing(org/jruby/RubyModule.java:3345)
at org.jruby.RubyModule.const_get(org/jruby/RubyModule.java:3290)
at RUBY.createGateway(classpath:/scripts/main.rb:79)
The code initiating it is:
gateway = ActiveMerchant::Billing::const_get(name).new(options)
I think this is happening because there is some dynamic loading of the gateways happening in gateways.rb:
module ActiveMerchant
module Billing
load_path = Pathname.new(__FILE__ + '/../../..')
Dir[File.dirname(__FILE__) + '/gateways/**/*.rb'].each do |filename|
gateway_name = File.basename(filename, '.rb')
gateway_classname = "#{gateway_name}_gateway".camelize
gateway_filename = Pathname.new(filename).relative_path_from(load_path).sub_ext('')
autoload(gateway_classname, gateway_filename)
end
end
end
This works during unit tests because the Ruby files are real files in my target directory. However in the final application, the Ruby files are contained within a Jar which is in a Jar.
Anyone know why this is happening and how to get it to work?

Which gateway are you trying to teach? From Active Merchant's github there is no
ActiveMerchant::Billing::SecurePayAuGateway
But there is a
ActiveMerchant::Billing::SecurePayGateway
And a
ActiveMerchant::Billing::SecurePayTechGateway
To test, instead of
gateway = ActiveMerchant::Billing::const_get(name).new(options)
Try
gateway = ActiveMerchant::Billing::SecurePayGateway
If this works, you know the problem is your gateway = method and you can fix this accordingly

Related

Not able to call method in a gem

This might be an easy question but I was unfortunately not able to find the answer on Google.
Context:
I am working on a project of my own, and I am externalizing some code in a gem (FrenchTaxSystem). It is the first I create a gem and I have difficulties using it properly.
Problem:
When calling a method (like testit) defined in the main file (french_tax_system.rb) of my gem I get a "NoMethodError: undefined method `testit' for FrenchTaxSystem:Module", though I can call constants from this same file (like FISCAL_NB_PARTS_FOR_MARRIED_COUPLE) and it puzzles me.
E.g in IRB I get that when calling a method:
[
And it is the same in my Rspecs tests inside my gem
However when calling a constant I have no error:
Main file in my gem:
french_tax_system.rb
module FrenchTaxSystem
class Error < StandardError; end
# Constants
...
FISCAL_NB_PARTS_FOR_MARRIED_COUPLE = 2
...
# Methods
## Main method
def testit
"test me"
end
end
Gem file structure:
Thank you in advance for your help,
Mth0158
This should work:
module FrenchTaxSystem
def self.testit
"test me"
end
end

Ruby uniniatialized constant in Calabash Step

I am writing some interface tests using Cucumber as skeleton for Android-Calabash. The tests are written in Ruby.
I am receiving the following execution error:
uninitialized constant MultiTouchGesture
The code generating it is:
require 'calabash-android/calabash_steps'
require 'calabash-android/gestures'
When(/^When I touch the spaceship and an asteroid at the same time$/) do
gest = []
multi_touch = MultiTouchGesture.new(gest)
gestures.add_touch(touch("* id:'spaceship'"), 0)
gestures.add_touch(touch("* id:'asteroid'"), 1)
end
I guess Ruby does not find gestures.rb where MultiTouchGesture class is, even if I have imported it using 'require'. I have checked for gestures.rb and it is not missing in my computer, it is in the following path:
C:\Ruby23-x64\lib\ruby\gems\2.3.0\gems\calabash-android-0.9.0\lib\calabash-android
What can I do to make Ruby find the class?
Here is the documentation for MultiTouchGesture class:
http://www.rubydoc.info/gems/calabash-android/Calabash/Android/Gestures/MultiTouchGesture
Thank you,
Héctor

Cucumber: Unable to see methods of a module included in the World?

I'm working with cucumber/ruby and I wanted to create a new module with some methods to use them in my step definitions.
I was reading how to do this here, https://github.com/cucumber/cucumber/wiki/A-Whole-New-World. But when I've tried the following I get an error:
create the new module under /root_location/lib/new_module.rb
create the module as:
.
module Newmodule
def here
puts "here"
end
end
World(Newmodule)
However, when I then try to use the 'here' method from my steps definition, I just get:
undefined local variable or method `here' for # (NameError)
Any idea what I am doing wrong?
The module needs to be located in features, otherwise it won't be added into World. Cucumber does not look outside of features for anything unless you specifically tell it to.
Put this code either in features/support or features/step_definitions

Broken precompiled assets in Rails 3.1 when deploying to a sub-URI

I'm in the process of updating a Rails 3 app to use Rails 3.1 and as part of that, am making use of the new asset pipeline. So far, I've got everything working apart from one rather annoying problem I can't solve.
The application and all its assets works fine in development, but in production it is deployed to a sub-URI using Passenger (http://the-host/sub-uri/). The problem with this is that the assets are pre-compiled during deployment and one of my CSS (well, it's a .css.scss file) files is making use of the image-url helper from the sass-rails gem. Since during the pre-compilation process, the paths are hard-coded into the precompiled CSS file, the sub-uri is not taken account of:
In my .css.scss file:
body { background-image: image-url("bg.png"); }
The result in the compiled application-<md5-hash-here>.css file:
body { background-image: url(/assets/bg.png); }
What it should be to make it work correctly:
body { background-image: url(/sub-uri/assets/bg.png); }
Is this scenario just asking too much? If so, I'll have to switch back to the old non-asset-pipelined way and just serve my images and CSS from public. However it seems like something which should have been thought about and solved...? Am I missing the solution?
Edit 1: I should note that using the erb solution instead yields the same result, as one would expect.
Edit 2: in response to Benoit Garret's comment
No, the problem isn't related to the config.assets.prefix. I tried setting that (to /sub-uri/assets rather than the default of /assets) but it turned out that was the wrong thing to do - it seems like this setting is already in relation to the root of the Rails app, not the server. Removing that (and thus returning to the default) has fixed all the weird issues that caused (and there were many, all the assets ended up in /sub-uri/sub-uri/assets - it was all very strange). The only problem is that the image-url helper and friends do not pick up the sub-URI when they are pre-compiled. Needless to say, this is logical since when it is pre-compiled, it couldn't possibly know that when it's running under Passenger, it'll be configured in this way. My question is how to inform it of this and thus end up with the correct paths in the precompiled result. If indeed it can be done.
My current workaround is to reference the iamge in the CSS like this: url(../images/bg.png) and place it in the non-pipelined public/images location. Hardly ideal since it doesn't benefit from the fingerprinting and everything which the pipeline provides.
Finally I've worked out a couple of workarounds/solutions.
1) From https://github.com/rails/sass-rails/issues/17 it looks like this could get fixed in sass-rails. I've monkey-patched helpers.rb myself along the lines of the proposed patch in the link above. I simply set the required environment variable in the asset precompile line in deploy.rb.
I do all my monkey patching in a single file config/initializers/gem_patches.rb. In this file I patched this method as:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
path = options[:custom][:resolver].public_path(asset, kind.pluralize)
path = ENV['PRODUCTION_URI'] + path if ENV['PRODUCTION_URI']
path
end
end
end
end
2) Alternatively if you are ok to embed images in the CSS, changing the stylesheet to have a .erb extension, and replacing the image-url("bg.png") with url(<%= asset_data_uri "bg.png" %>) will work without any need to change sass-rails. asset-data-uri doesn't exist as a pure Sass function so you have to use the Rails helper asset_data_uri.
In the latest Rails 3.1.3 you need to monkey patch a different module now, for it to work
This is what I did
module Sprockets
module Helpers
module RailsHelper
def asset_path(source, options = {})
source = source.logical_path if source.respond_to?(:logical_path)
path = asset_paths.compute_public_path(source, asset_prefix, options.merge(:body => true))
path = options[:body] ? "#{path}?body=1" : path
if !asset_paths.send(:has_request?)
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path if ENV['RAILS_RELATIVE_URL_ROOT']
end
path
end
end
end
end
And in my deploy.rb I have:
desc "precompile the assets"
namespace :assets do
task :precompile_assets do
run "cd #{release_path} && rm -rf public/assets/* && RAILS_ENV=production bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT='/my_sub_uri'"
end
end
before "deploy:symlink", "assets:precompile_assets"
I'm using Rails 3.1.3 and deploying to a sub-URI successfully.
I have NOT monkey-patched anything.
The key problems with this setup have been better discussed here. As you can see, the solution was applied to Rails 3.2 and never backPorted to 3.1.4.
But, I have came to a solution using Rails 3.1.3 that works for my setup.
Try this: (I'm no expert, just trying to contribute to solve a problem that hassled me for hours...)
environment.rb:
#at top:
ENV['RAILS_RELATIVE_URL_ROOT'] = '/rais'
production.rb:
config.assets.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] ? ENV['RAILS_RELATIVE_URL_ROOT'] + '/assets' : '/assets'
routes.rb:
Rais::Application.routes.draw do
scope ENV['RAILS_RELATIVE_URL_ROOT'] || '/' do #see config/environment.rb
<<resources here>>
end
end
As you can see, I've put assets.prefix inside production.rb, not in application.rb
After that you do:
rake assets:clear
rake assets:precompile
and than, test with the console:
RAILS_ENV=production rails console
Results:
foo = ActionView::Base.new
foo.stylesheet_link_tag 'application'
=> "<link href=\"/rais/assets/layout.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/rais/assets/application.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />"
foo.image_tag('arrow-up.png')
=> "<img alt=\"Arrow-up\" src=\"/rais/assets/arrow-up-ca314ad9b991768ad2b9dcbeeb8760de.png\" />"
After a bit of digging around, I have found the issue. The issue is in Rails, specifically Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path. Sprockets::Helpers::RailsHelper::AssetPaths inherits from ActionView::AssetPaths and overrides a number of methods. When compute_public_path is called through the Sass::Rails::Resolver#public_path method is sass-rails, the rails sprocket helper picks up the task of resolving the asset. Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path defers to super which is ActionView::AssetPaths#compute_public_path. In this method there is a condition of has_request? on rewrite_relative_url_root as seen below:
def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
...
source = rewrite_relative_url_root(source, relative_url_root) if has_request?
...
end
def relative_url_root
config = controller.config if controller.respond_to?(:config)
config ||= config.action_controller if config.action_controller.present?
config ||= config
config.relative_url_root
end
If you look at the internals of rewrite_relative_url_root it relies on a request to be present and the ability to derive it from the controller variable in order to resolve the relative url root. The issue is that when sprockets resolves these assets for sass it does not have a controller present and therefore no request.
The solution above didn't work in development mode for me. Here is the solution that I am using to make it work for now:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
resolver = options[:custom][:resolver]
asset_paths = resolver.context.asset_paths
path = resolver.public_path(asset, kind.pluralize)
if !asset_paths.send(:has_request?) && ENV['RAILS_RELATIVE_URL_ROOT']
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path
end
path
end
end
end
end

How do I change the aws-ruby log location?

I've found the method set_log in the documentation, I just can't figure out the syntax to call it. Here's what I tried:
require 'ruby-aws'
Amazon::Util::Logging.set_log('my.log')
NoMethodError: undefined method `set_log' for Amazon::Util::Logging:Module
You can see that Amazon::Util::Logging is a module and set_log is a 'Public Instance method'. So you need
class NewClass
include Amazon::Util::Logging
def foo
set_log('file.txt')
log 'debug_message'
end
end
I ran into this problem when trying to deploy a Ruby-on-Rails site that uses 'aws-ruby' to heroku (I got the "Permission denied - ruby-aws.log" error).
To change the log file location from 'ruby-aws.log' to 'log/ruby-aws.log', I added the following to an initializer. Make sure this is called before you use any of the aws-ruby library. Notice the change on the "set_log..." line.
module Amazon
module Util
module Logging
def log( str )
set_log 'log/ruby-aws.log' if ##AmazonLogger.nil?
##AmazonLogger.debug str
end
end
end
end
A simpler way would be to add this line:
set_log("/dev/null")

Resources