RubyMine: Unresolved Ruby Reference for global variable - ruby

Running RubyMine 2016.2.4. This project has a "global" singleton called $environment. All over the codebase this file is require_relative'd to get access to runtime dependencies. RubyMine is showing "Unresolved Ruby Reference" for every instance of $environment in classes which use this global.
Mock-up of how the environment.rb file looks:
require 'singleton'
class Environment
include Singleton
def log
...
end
end
$environment ||= Environment.instance
Example usage which RubyMine complains about:
require_relative '../environment'
class FancyWorker
def run
...
$environment.log.info 'Running!'
end
end
I've tried searching to no avail on how to resolve this inspection problem in RubyMine. I don't want to disable the inspection since it is useful for finding legitimate problems - but this is not a legitimate issue.
(Please keep commentary about globals being bad to yourself, I didn't make that design decision - I just want to help RubyMine understand the reference.)

I think you found a bug on RubyMine. Try changing:
$environment ||= Environment.instance
to:
$environment = $environment || Environment.instance
or just assign it if you're sure you won't be defining $environment anywhere else.

Related

Rails and MiniTest: How to write tests for something in app/lib/mymodule (Class not found)?

Rails 5.2 here.
I want to test a class defined in app/lib/legacy/export.rb:
# app/lib/legacy/export.rb
module Legacy
class Export
def initialize ; end
end
end
However, a test in test/services/legacy_export_test.rb
# test/services/legacy_export_test.rb
require 'test_helper'
class LegacyExportTest < ActiveSupport::TestCase
test 'can be initialized' do
Legacy::Export.new
end
end
will spit out NameError: uninitialized constant Legacy::Export.
It works well if I put the class definition in app/lib/export.rb (and remove the module definition).
I can also reference this class in Controllers and in the rails console (rails c).
Trying to reference the class starting with the top-level-"namespace" (::Legacy::Export) does not help either. I find answers to questions how to reference lib folders (and subdirectories) in the test/ folder, but this is not what I need.
require 'lib/legacy/export will tell me cannot load such file, as will require 'legacy/export'.
I assumed that the (Auto-)Load-stuff of Rails and MiniTest are the same, but obviously there is some additional configuration to be done.
What has to be done? Where would I find this information?
The problem is that your class namespace / class path doesn't match how Rails autoloading works out of the box.
When you use a class that wasn't previously declared, Rails by default will look on specific paths (defined on config.autoload_paths)
app/controllers
app/controllers/concerns
app/models
app/models/concerns
...
When you use User for the first time, as it's not defined (yet) it will loop over those paths and try to require app/controllers/user.rb, app/controllers/concerns/user.rb, app/models/user.rb, until it founds the User class
if your class is namespaced as Legacy::Export, then it will look for app/models/legacy/export.rb, app/models/concerns/legacy/export.rb, app/controllers/legacy/export.rb, etc.
That's why it can't find your class: Your file is located on app/lib, that's not within the paths Rails use to look for.
There are different solutions:
Option #1
Require the file explicitly. (The Ruby way)
require_relative '../../app/lib/legacy/export'
Option #2
Add app/lib to autoload_path (in config/application.rb)
(The Rails Way)
module YourApp
class Application < Rails::Application
# ...
config.autoload_paths << Rails.root.join("app/lib")
end
end
Option #3
Adapt namespace to match what autoloading expects (instead of changing the configuration)
Example: move you file to something like app/models/legacy/export.rb

Rubymine doesn't regonize shared context variables

I have specs that use variables from a shared context. The set up looks something like this:
shared_context.rb
RSpec.shared_context :handy_things do
let(:handy_object) { ... }
end
test_spec.rb:
require 'shared_context.rb'
describe 'Something happens' do
include_context :handy_things
before(:each) do
handy_object.option = true
end
...
The handy_object from the context is not recognized by Rubymine. I get an inspection message 'Cannot find...'.
This is not the end of the world but it annoys me.
Is there a way to let Rubymine know the variables of the shared context are accessible everywhere. Or as workaround to add my shared_context variables to some kind of dictionary so Rubymine doesn't flag it as unknown?
You might try two things:
Replacing your require with require_relative "shared_context" (with the relative path included if they're in different folders, no .rb extension necessary)
Specifying require "./shared_context"

Ruby Undefined method error - Using Beaker [duplicate]

I'm quite new to all of this. I am trying to test out a puppet module using Beaker. I keep getting this:
NoMethodError: undefined method `describe' for
#Beaker::TestCase:0x007fd6f95e6460
/Users/user1/beaker/Puppet/puppet-files/spec/classes/unit_spec.rb:3
/Users/user1/.rvm/gems/ruby-2.2.7/gems/beaker-3.24.0/bin/beaker:9
/Users/user1/.rvm/gems/ruby-2.2.7/bin/ruby_executable_hooks:15
/Users/user1/.rvm/gems/ruby-2.2.7/bin/ruby_executable_hooks:15.
This is the command that I'm running - "beaker --hosts myhost.yaml --pre-suite spec".
My unit_spec.rb contains this:
require 'puppetlabs_spec_helper/rake_tasks'
describe 'application' do
context 'applied to supported operating system' do
on_supported_os.each do |os, facts|
context "#{os}" do
let(:facts) do
facts
end
context "without any parameters" do
let(:params) {{ }}
it { is_expected.to compile.with_all_deps }
it { is_expected.to contain_class('files') }
end
end
end
end
context 'applied to unsupported operating system' do
describe 'ubuntu-14-x86_64' do
let(:facts) {{
:osfamily => 'Debian',
:operatingsystem => 'Ubuntu'
}}
it { is_expected.to raise_error(Puppet::Error, /Ubuntu not supported/) }
end
end
end
Any help would be much appreciated! Btw, I am using 'puppetlabs_spec_helper/rake_tasks' due to the fact that when I just used 'spec_helper' it gave me an error that it could not "load such file" even though it was there.
Also, I have tried doing
RSpec.Describe
That did not fix the issue either. I get the following error -
NameError: undefined local variable or method `on_supported_os' for #Class:0x007f92a61d5e58
I realise that this might be an RSpec Puppet issue, as this module was previously tested through puppet RSpec, however now I am trying to test using Beaker and not quite sure how to fully achieve that!
You're mixing up unit- and VM-based testing.
rspec-puppet (and rspec-puppet-facts' on_supported_os) are for catalog-based unit testing. They do not require a VM, and can give you quick feedback on syntax, and logic of your module.
beaker, and the recommended beaker-rspec add-on, provide full end-to-end testing capabilities, using actual VMs, and testing a complete stack deploy (as defined in you tests).
The main entry point for existing modules is usually rake. Take a look at the existing rake tasks in the module using rake -T. In a well-written module it should have tasks for both rspec-puppet (usually called spec), and beaker (often called beaker, or acceptance).
If it is your own module, you also might want to look into the new Puppet Development Kit to get the most important tools in a single installer.

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

How I include a module (this module has a module inside that) inside another module in Ruby

I have a module as following,
main.rb:
module Main
include Dad::Mam
end
and
in dad.rb:
module Dad
module Mam
puts "Mam is saying you are very lazy..."
end
end
How can I name this file? dad.rb is right?
but when running
$ ruby main.rb
I am getting an Error like,
main.rb:2:in <module:Main>': uninitialized constant Main::Dad
(NameError) from main.rb:1:in'
I need to show the sentance inside the puts under Mam module while running ruby main.rb,
I am confused about using ruby's modules, please anyone help me and guide me..
In this case, since you're just writing a simple script, use #require_relative
require_relative 'dad'
module Main
include Dad::Mam
end
For an actual app or library, you would want to manage the load path (a global variable holding an array that tells ruby where to look for files) and then use a normal require

Resources