Ruby undefined constant NameError - ruby

I have the following code: http://scrp.at/FB
# Error:
# bin/rpg:5:in `<main>': uninitialized constant RubyPasswordGenerator::Korben (NameError)
In file "bin/rpg"
#!/usr/bin/env ruby
require_relative "../lib/ruby_password_generator"
puts RubyPasswordGenerator::Korben.new
In "lib/ruby_password_generator.rb"
require_relative "ruby_password_generator/ruby_password_generator"
require_relative "ruby_password_generator/password_generator"
require_relative "ruby_password_generator/version"
# DEBUG
require "pp"
module RubyPasswordGenerator
end
require_relative "ruby_password_generator/algo/korben"
In "algo/korben.rb"
module RubyPasswordGenrator
class Korben
M_LOWERCAS_LETTERS = ("a".."z").to_a
M_UPPERCASE_LETTERS = ("A".."Z").to_a
M_NUMBERS = (0..9).to_a
M_SPECCIAL_CHARACTERS = "!##()_-+=[]{}".split("")
def initialize(length = 42)
raise ArgumentError unless length.is_a?(Integer)
raise ArgumentError unless length >= 3 && length <= 255
#length = length
end
def generate
password = ""
(0...#length).each do
char = (M_LOWERCAS_LETTERS + M_UPPERCASE_LETTERS + M_NUMBERS + M_SPECCIAL_CHARACTERS).shuffle.sample
password << char
end
password
end
end
end
The file structure looks like:
# .
# ├── Gemfile
# ├── Gemfile.lock
# ├── LICENSE.markdown
# ├── NERD_tree_3
# ├── README.markdown
# ├── Rakefile
# ├── bin
# │   └── rpg
# ├── lib
# │   ├── ruby_password_generator
# │   │   ├── algo
# │   │   │   ├── korben.rb
# │   │   │   └── marvin.rb
# │   │   ├── helpers
# │   │   ├── password_generator.rb
# │   │   ├── ruby_password_generator.rb
# │   │   └── version.rb
# │   └── ruby_password_generator.rb
# ├── ruby_password_generator.gemspec
# └── spec
# ├── algo
# │   ├── korben_spec.rb
# │   └── marvin_spec.rb
# ├── password_generator_spec.rb
# ├── ruby_password_generator_spec.rb
# └── spec_helper.rb
#
# 7 directories, 19 files
I really don't know why I am getting an uninitialized constant "NameError" error. I included the file properly using require_relative. I also tried autoload and require, but that didn't solve anything. I am using ruby 1.9.2-p180.
If anybody knows what's going on please explain me.

module RubyPasswordGenrator
class Korben
You're missing an e in the module name. Thus the Korben class exists in the RubyPasswordGenrator module not the RubyPasswordGenerator module and RubyPasswordGenerator::Korben does indeed not exist.

Related

Wrong number of arguments Ruby while instantiating a Subclass

I have 3 classes that hare related through inheritance (it's a course exercise)
I have a Brand < Product < DBHandler classes
They are in a subfolder of the project, and all of them use require to access each other:
├── class
│   ├── Brand.rb
│   ├── Category.rb
│   ├── DBHandler.rb
│   └── Product.rb
├── db
│   ├── catalogo_categorias.txt
│   ├── catalogo_marca.txt
│   ├── catalogo_producto.txt
│   └── inventario_final.txt
├── init.rb
└── README.md
Clases
The Product file has in it:
require "#{Dir.pwd}/class/DBHandler"
class Product < DBHandler
attr_reader :key, :final_price, :db
attr_accessor :name, :unit, :brand, :category, :price
def initialize(name, unit, brand, category, price)
#name = name
#unit = unit
#brand = brand
#category = category
#price = price
#final_price = set_final_price
#db = DBHandler.new
#key = set_key
end
def set_key
#key = "#{#db.how_many+1}#{self.name[0..2].upcase}3BS"
end
def set_final_price
#final_price = self.price * 1.19
end
def search_product(search_expresion)
#db.db_search(search_expresion)
end
def alta_product
#db.write(
"#{key},#{name},#{unit},#{brand},#{category},#{price},#{final_price}\n"
)
end
end
and the Brand file has:
require "#{Dir.pwd}/class/Product"
class Brand < Product
attr_reader :brand_key, :a_brands, :q_brands
attr_accessor :brand
def initialize(brand)
# use super to use parent's attributes
super(brand)
#brand_key = set_brand_key
#a_brands = get_file.read
.split("\n")
.map { |abrand| abrand.split(',') }
#q_brands = #a_brands.count
end
def set_brand_key
"#{#q_brands}#{self.brand[0..2].upcase}3BS"
end
def get_file
File.open("#{Dir.pwd}/db/catalogo_marca.txt")
end
def alta_brand
get_file.write("#{#brand_key},#{#brand}", mode: 'a')
end
end
Init file
All the files are called from the init.rb file in order to call some instance methods.
this is my Init.rb file first lines.
require './class/Product'
require './class/Brand'
require './class/DBHandler'
require './class/Category'
The problem
when I want to create a new instance of Brand class, I have tried:
brand = Brand.new(name, unit, brand, category, price) and it returns wrong number of arguments (given 5, expected 1) (ArgumentError)
brand = Brand.new(brand) and it returns wrong number of arguments (given 1, expected 5) (ArgumentError)
I don't know what may I doing wrong.
I need to create a Brand instance with only brand argument
Your problem is here
super(brand)
This is saying "call the parent constructor with brand as the only argument". The parent constructor is Product#initialize, which takes five arguments. So no matter how you call Brand#initialize, it's going to fail since it calls Product#initialize with the wrong number of arguments. You need to call super with all five.
But I challenge the frame. Subclassing is a very tight coupling, an "is-a" relationship. What you're claiming is that every brand is a product, and I fail to see how that's true. So rather than fixing the super call, you might reconsider your design and ask yourself if you really meant to make a subclass.

steep check returns RBS::UnknownTypeName on DateTime

I am implementing a .rbs file for the ruby code and everything works but the DateTime. This is what I have:
ruby file:
class foo
# other attributes
attr_reader :bar
def initialize(bar)
#bar = bar
end
end
this is the rbs file:
class Foo
# other attributes
attr_reader bar: DateTime
def initialize: (DateTime bar) -> void
end
but when I run steep check I get the following error:
path/foo.rbs:14:26: [error] Cannot find type `DateTime`
│ Diagnostic ID: RBS::UnknownTypeName
│
└ attr_reader bar: DateTime
Why is DateTime not being found? should it be a different declaration?
the rest of the types works fine, either if they are created by me or if they are basic ones like Integer or String.
Thanks.
You need to explicitly add the date standard library types to your Steepfile
target :lib do
signature "sig"
check "lib"
library "date" # add standard libraries here
end
I didn't find any good documentation for this, the I pieced it together by reading steep's Steepfile.
This is how I guess it works:
Types that are automatically loaded by ruby are available by rbs/steep out of the box. Those signatures are in rbs/core).
The standard library that is not loaded automatically, e.g.
DateTime, is not available by rbs/steep unless you explicitly declare them in the Steepfile as library. Those signatures are in rbs/stdlib.

Ruby PageObject, visiting webpages outside of step defintions

I am trying to call page object methods outside of my step definitions for visiting pages so I can avoid duplication within my steps. I believe the issue now is with how I am creating my browser session, and the object I created in my hooks is not accessible by anything outside of other hooks / steps definitions.
Directory structure:
├── features/
│ ├── Gemfile
│ ├── feature_files
│ │ ├── example1.feature
│ │ ├── example2.feature
│ ├── hooks
│ │ ├── web_hooks.rb
│ ├── step_definitions
│ │ ├── web_steps.rb
│ ├── Support
│ │ ├── example1.feature
| | | |──pages
| | | | |──test.rb
| | | |──controller
| | | | |──controller.rb
My Web hooks are nothing more than the basic new watir session + logging:
#browser = Watir::Browser.new(:chrome)
So when I am visiting my pages within my step definitions that all works as expected, but when I change my step to call a method outside of the step definitions I get back.
Unable to pick a platform for the provided browser or element: nil.
nil was passed to the PageObject constructor instead of a valid browser or element object.
My controller class looks like this:
class TestController
class << self
include PageObject
include PageObject::PageFactory
def test_visit(url)
visit TestPage, :using_params => {:id => url} do |page|
page.populate
embed(#browser.screenshot.base64, 'image/png', "STUB Setup for #{code}")
end
end
end
end
I have several variations of the above controller including turning it into a module and extending pageobject functionality, trying to pass #browser into the method from the step definition etc but they all result in the following. I have also tried requiring everything under my support structure prior to running my cucumber tests.
The visit method assumes that #browser is defined and available. You will need to define it within the test_visit method.
Passing browser instance
The most straightforward solution may be to pass in the Watir::Browser object:
def test_visit(url, browser)
#browser = browser
visit TestPage, :using_params => {:id => url} do |page|
page.populate
embed(#browser.screenshot.base64, 'image/png', "STUB Setup for #{code}")
end
end
With the step definitions presumably looking like:
TestController.test_visit('some_url', #browser)
If you are making a lot of calls to the TestController and always using the same browser instance, you could setup a #browser in the class. This would save you from having to always pass in the browser instance.
class TestController
class << self
include PageObject
include PageObject::PageFactory
def browser=(browser)
#browser = browser
end
def test_visit(url)
visit TestPage, :using_params => {:id => url} do |page|
page.populate
embed(#browser.screenshot.base64, 'image/png', "STUB Setup for #{code}")
end
end
end
end
In your web hooks, where you start the browser, you could configure the TestController to have the browser instance:
#browser = Watir::Browser.new(:chrome)
TestController.browser = #browser
Then your step definitions do not need to pass in the #browser:
TestController.test_visit('some_url')
Make methods available to step definitions
Another option is to make the shared methods directly available to step definitions. As the methods will be in the scope of the step, #browser and embed will be available.
First, define your methods in a module:
module TestController
def test_visit(url)
visit TestPage, :using_params => {:id => url} do |page|
page.populate
embed(#browser.screenshot.base64, 'image/png', "STUB Setup for #{code}")
end
end
end
In your env.rb (or similar), make the module methods available to the step definitions by using World:
World(TestController)
Your step definitions can then simply call the methods directly:
test_visit('some_url')

java.lang.NoClassDefFoundError CRFClassifier in a Rails app

I'm trying to run the CRFClassifier on a string to extract entities from the string. I'm using the Ruby bindings for the Stanford NLP entity recognizer from here: https://github.com/tiendung/ruby-nlp
It works perfectly fine on its own class say (nlp.rb). When I run ruby nlp.rb it works fine. However, I've tried to create an object of this class inside one of my controllers in my rails app and for some reason I'm getting the following error:
java.lang.NoClassDefFoundError: edu/stanford/nlp/ie/crf/CRFClassifier
Here is the code that works fine on its own but not inside a controller.
def initialize
Rjb::load('stanford-postagger.jar:stanford-ner.jar', ['-Xmx200m'])
crfclassifier = Rjb::import('edu.stanford.nlp.ie.crf.CRFClassifier')
maxentTagger = Rjb::import('edu.stanford.nlp.tagger.maxent.MaxentTagger')
maxentTagger.init("left3words-wsj-0-18.tagger")
sentence = Rjb::import('edu.stanford.nlp.ling.Sentence')
#classifier = crfclassifier.getClassifierNoExceptions("ner-eng-ie.crf-4-conll.ser.gz")
end
def get_entities(sentence)
sent = sentence
#classifier.testStringInlineXML( sent )
end
It's the same exact code in both cases. Anyone has any idea of what's happening here!?
Thanks in advance!
I think you need this:
Rjb::load('/path/to/jar/stanford-postagger.jar:/path/to/jar/stanford-ner.jar', ['-Xmx200m'])
I just tried this and it works. Create a dir in lib called nlp. Put the jars there and then create a class which loads the jars using the full path:
So you end up with:
├── lib
│   ├── nlp
│   │   ├── stanford-ner.jar
│   │   └── stanford-postagger.jar
│   └── nlp.rb
require 'rjb'
class NLP
def initialize
pos_tagger = File.expand_path('../nlp/stanford-postagger.jar', __FILE__)
ner = File.expand_path('../nlp/stanford-ner.jar', __FILE__)
Rjb::load("#{pos_tagger}:#{ner}", ['-Xmx200m'])
crfclassifier = Rjb::import('edu.stanford.nlp.ie.crf.CRFClassifier')
maxentTagger = Rjb::import('edu.stanford.nlp.tagger.maxent.MaxentTagger')
maxentTagger.init("left3words-wsj-0-18.tagger")
sentence = Rjb::import('edu.stanford.nlp.ling.Sentence')
#classifier = crfclassifier.getClassifierNoExceptions("ner-eng-ie.crf-4-conll.ser.gz")
end
def get_entities(sentence)
sent = sentence
#classifier.testStringInlineXML( sent )
end
end
Little test class:
require_relative 'lib/nlp'
n = NLP.new
n.get_entities("Good afternoon Rajat Raina, how are you today?")
output:
ruby t.rb
Loading classifier from /Users/brendan/code/ruby/ruby-nlp/ner-eng-ie.crf-4-conll.ser.gz ... done [1.2 sec].
Getting data from Good afternoon Rajat Raina, how are you today? (default encoding)
Good afternoon <PERSON>Rajat Raina</PERSON>, how are you today?

How to get object instance by filename in ruby

There is a class in a ruby file test.rb
#test.rb
class AAA<TestCase
def setUp()
puts "setup"
end
def run()
puts "run"
end
def tearDown()
end
end
In another file test2.rb, i want to get the instance of AAA by file name "test.rb".
In python, i can do this by below:
casename = __import__ ("test")
for testcase in [getattr(casename, x) for x in dir(casename)]:
if type(testcase) is type and issubclass(testcase, TestCase):
#do something with testcase()
How can i implement the same function in ruby now.
Thanks
Just require the filename without the .rb extension like so:
require './test'
Suppose you have this directory structure:
+-- project/
| |
| +-- folder1/
| | |
| | +-- file1.rb
| |
| +-- folder2/
| |
| +-- file2.rb
|
+-- file3.rb
in this case you may want to add specific directories to the load path like so:
# in file3.rb
$LOAD_PATH.unshift './folder1'
this way you can require files by their name without specifying the folder every time:
require 'file1'
Now for the second part, getting an instance. You could just do AAA.new but i suppose you want to dynamically create instances of classes that are subclasses of TestCase. First you have to find all subclasses of TestCase:
class Class
def subclasses
constants.map do |c|
const_get(c)
end.select do |c|
c.is_a? Class
end
end
end
this will enable you to get a list of subclasses like so:
TestCase.subclasses
#=> [TestCase::AAA]
from which you can construct your objects
TestCase.subclasses.map{|klass| klass.new }
#=> [#<TestCase::AAA:0x007fc8296b07f8>]
or even shorter if you do not need to pass arguments to new
TestCase.subclasses.map(&:new)
#=> [#<TestCase::AAA:0x007fc8296b07d0>]
So far, so good. But if i get this right you are trying to build a test runner. Don't. There are plenty of testing libraries and great test runners out there. Ruby has the built-in Minitest and this blog post explains very well how you can best run your tests.

Resources