Wrong number of arguments Ruby while instantiating a Subclass - ruby

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.

Related

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?

Access module Configuration constant from another class

I am trying to understand how the following code is able to do this:
attr_accessor *Configuration::VALID_CONFIG_KEYS
Without requiring the Configuration file. Here is part of the code:
require 'openamplify/analysis/context'
require 'openamplify/connection'
require 'openamplify/request'
module OpenAmplify
# Provides access to the OpenAmplify API http://portaltnx20.openamplify.com/AmplifyWeb_v20/
#
# Basic usage of the library is to call supported methods via the Client class.
#
# text = "After getting the MX1000 laser mouse and the Z-5500 speakers i fell in love with logitech"
# OpenAmplify::Client.new.amplify(text)
class Client
include OpenAmplify::Connection
include OpenAmplify::Request
attr_accessor *Configuration::VALID_CONFIG_KEYS
def initialize(options={})
merged_options = OpenAmplify.options.merge(options)
Configuration::VALID_CONFIG_KEYS.each do |key|
send("#{key}=", merged_options[key])
end
end
....
end
And this is the Configuration module:
require 'openamplify/version'
# TODO: output_format, analysis, scoring can be specied in the client and becomes the default unless overriden
module OpenAmplify
# Defines constants and methods for configuring a client
module Configuration
VALID_CONNECTION_KEYS = [:endpoint, :user_agent, :method, :adapter].freeze
VALID_OPTIONS_KEYS = [:api_key, :analysis, :output_format, :scoring].freeze
VALID_CONFIG_KEYS = VALID_CONNECTION_KEYS + VALID_OPTIONS_KEYS
DEFAULT_ENDPOINT = 'http://portaltnx20.openamplify.com/AmplifyWeb_v21/AmplifyThis'
DEFAULT_HTTP_METHOD = :get
DEFAULT_HTTP_ADAPTER = :net_http
DEFAULT_USER_AGENT = "OpenAmplify Ruby Gem #{OpenAmplify::VERSION}".freeze
DEFAULT_API_KEY = nil
DEFAULT_ANALYSIS = :all
DEFAULT_OUTPUT_FORMAT = :xml
DEFAULT_SCORING = :standard
DEFAULT_SOURCE_URL = nil
DEFAULT_INPUT_TEXT = nil
attr_accessor *VALID_CONFIG_KEYS
....
end
This is from this repository: OpenAmplify
First of all, in both configuration.rb and client.rb, they're using the same naming space, which is module OpenAmplify.
Even though configuration.rb is not required in client.rb, the convention of Ruby project usually requires all necessary files in one file (normally the same name as the name space, and placed in {ProjectName}/lib/, in this case the file is openamplify/lib/openamplify.rb).
So if you go to openamplify/lib/openamplify.rb, you'll notice it actually requires all those two files:
require 'openamplify/configuration'
require 'openamplify/client'
And since constants are already defined in configuration.rb:
module OpenAmplify
module Configuration
VALID_CONFIG_KEYS = ...
end
end
Then obviously constant VALID_CONFIG_KEYS is visible in the same module (re-opened by client.rb) by Configuration::VALID_CONFIG_KEYS (and the * in front just means exploding array, because VALID_CONFIG_KEYS is an array of symbols)
module OpenAmplify
class Client
attr_accessor *Configuration::VALID_CONFIG_KEYS
end
end

Ruby undefined constant NameError

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.

Resources