how to write rspec for method - ruby

I have following code in programmability folder
module Programmability
module Parameter
class Input < Parameter::Base
attr_reader :args
def initialize(name, type, **args)
super(name, type)
#args = args
end
def value=(val)
if val
val = convert_true_false(val)
--- some code ----
end
#value = val
end
def convert_true_false(val)
return val unless #args[:limit] == 1
if [:char].include?(#type) && val == 'true'
'Y'
elsif [:char].include?(#type) && val == 'false'
'N'
elsif [:bit].include?(#type) && val == 'true'
1
elsif [:bit].include?(#type) && val == 'false'
0
end
end
end
end
end
I am trying to write rspec for method convert_true_false. I am new to rspec. any help is appreciated.
I tried doing this
context 'returns Y if passed true'
input = Programmability::Parameter::Input.new(name, type, limit)
it 'returns Y' do
name = 'unregister_series'
type = ':char'
limit = 1
expect(input.value = 'true' ).to eq('Y')
end
end
but its not picking up limit value. when it reaches convert_true_false method it comes out of it since #args[:limit] is nil
Thanks

The issue is that setters always return the value passed:
class Test
def foo=(foo)
#foo = foo + 100
return 42
end
end
puts (Test.new.foo = 69) # 69
To resolve it, simply check the value after you assigned it:
# instead of
expect(input.value = 'true').to eq 'Y'
# do
input.value = 'true'
expect(input.value).to eq 'Y'

Related

return values for Ruby setter

I read that attr_writer :age is short hand for this:
def age=(value)
#age = value
end
So I created a class with a function like this:
def age=(value)
if #age == -1
#age = value
return true
end
return false
end
Then I wanted to call it like this in another place:
rv = Foo.age(1)
# do stuff with rv
But I get an error:
ArgumentError:
wrong number of arguments (given 1, expected 0)
Anyway, I can do something like Foo.age = 1 but that doesn't give me control over the return value. What is the proper idiomatic Ruby here?
how about a wrapper method that do 2 steps: first it'll try to set value age= then validate that age == new_value and return, so that you could know that the setter is success or not.
class Foo
def age=(val)
# do a bunch of complicated networking that was non-deterministic
# return true/false
end
def set_age(val)
self.age = val
#age == val
end
end
foo = Foo.new
result = foo.set_age(1)
you could also replace true/false by raising an error, then you could wrap setter into a begin-end block
class Foo
def age=(val)
# do a bunch of complicated networking that was non-deterministic
raise RuntimeError
end
end
result = begin
foo.age = 1
true
rescue => e
false
end

Ruby: Create a filter for methods

I have multiple methods which are very repetitive:
def method1 specific, options = {}
scopes = options[:scope] || [:favorites]
if scopes.size > 1
# do a
else
# do b
end
end
def method2 options = {}
scopes = options[:scope] || [:favorites]
if scopes.size > 1
# do c
else
# do d
end
end
def method3 options = {}
scopes = options[:scope] || [:favorites]
if scopes.size > 1
# do e
else
# do f
end
end
Is there a way to just use something similar to a filter to vaildate the option scope and do a or b in the method that was called originally?
Here is how I am doing it right now, although it is not very simplistic:
def method1 specific, options = {}
options[:parameter] = specific
if options.has_key?(:multiple_scopes) == false
results = validate_scopes __method__, options
elsif options.has_key?(:multiple_scopes) && options[:multiple_scopes] == true
results = {}
options[:scope].each do |scope|
results[scope] = # do a (scope, specific accessible)
end
else
results = # do a (options[:scope], specific accessible)
end
results
end
# method2
# method3
private
def validate_scopes method, options = {}
options[:scope] = [:favorites] unless options.has_key? :scope
if options[:scope].size > 1
options[:multiple_scopes] = true
else
options[:multiple_scopes] = false
options[:scope] = options[:scope][0]
end
if options.has_key? :parameter
parameter = options[:parameter]
options.delete :parameter
send(method, parameter, options)
else
send(method, options)
end
end

attr_accessor - Accessing an objects attributes from another class

I want to access the ogre's object's swings attribute from the Human's class. However, all I am getting is:
NameError: undefined local variable or method ogre for
**<Human:0x007fdb452fb4f8 #encounters=3, #saw_ogre=true>
Most likely a simple solution, and my brain is just not operating this morning. I am running tests with minitest. The test and classes are below:
ogre_test.rb
def test_it_swings_the_club_when_the_human_notices_it
ogre = Ogre.new('Brak')
human = Human.new
ogre.encounter(human)
assert_equal 0, ogre.swings
refute human.notices_ogre?
ogre.encounter(human)
ogre.encounter(human)
assert_equal 1, ogre.swings
assert human.notices_ogre?
end
ogre.rb
class Ogre
attr_accessor :swings
def initialize(name, home='Swamp')
#name = name
#home = home
#encounters = 0
#swings = 0
end
def name
#name
end
def home
#home
end
def encounter(human)
human.encounters
end
def encounter_counter
#encounters
end
def swing_at(human)
#swings += 1
end
def swings
#swings
end
end
class Human
def initialize(encounters=0)
#encounters = encounters
#saw_ogre = false
end
def name
"Jane"
end
def encounters
#encounters += 1
if #encounters % 3 == 0 and #encounters != 0
#saw_ogre = true
else
#saw_ogre = false
end
if #saw_ogre == true
ogre.swings += 1 # <----issue
end
end
def encounter_counter
#encounters
end
def notices_ogre?
#saw_ogre
end
end
The easy fix would be to pass the ogre object as an argument to encounters - assuming encounters isn't used anywhere else without the argument.
class Ogre
...
def encounter(human)
human.encounters(self)
end
...
end
class Human
...
def encounters(ogre)
#encounters += 1
if #encounters % 3 == 0 and #encounters != 0
#saw_ogre = true
else
#saw_ogre = false
end
if #saw_ogre == true
ogre.swings += 1 # <----issue
end
end
...
end

Minitest not working

I have simple ruby app that parses a string and counts the number of Xs and Os, and returns true if there is an equal number, otherwise false.
I want to know why my test isn't working.
When I run the test, the app gets called, and the test runs, but there are 0 runs, 0 assertion...etc. Why?
The app:
class Calc
def xo(str)
ex = 0
oh = 0
for i in (0...str.length)
if str[i] == "x" || str[i] == "X"
ex += 1
elsif str[i] == "o" || str[i] == "O"
oh += 1
else
end
end
if ex == oh
puts "equal"
return true
else
puts "not equal"
return false
end
end
end
Calc.new.xo("xoxoo")
The test:
require_relative "task"
require "minitest/autorun"
class Test < MiniTest::Test
def zeetest
#calc = Calc.new
assert_equal( true, #calc.xo("xoxo"))
end
end
Try this:
require_relative "task"
require "minitest/autorun"
class TestCalc < MiniTest::Test
def setup
#calc = Calc.new
end
def test_xo
assert_equal( true, #calc.xo("xoxo"))
end
end

Linked List ruby, the Node and LInkedlist class doesnt work properly

I have some issues with this code, so, I'm trying to make a linked list but with the first variable I get the next issue:
nodo.rb:34 in 'initialize': wrong number of arguments(1 for 0)
So, the Node class have the actual node and the link, and LinkedList the size and the header.
The problem comes when I try to add a new value but I receive the issue. So I dont know how to fix this problem. I will receive any help you could give me.
class Node
def intialize(data,ref = nil)
#data = data
#refe = refe
end
def get_data
return #data
end
def set_data(newdata)
#dato = newdata
end
def get_ref
return #ref
end
def set_ref(newref)
#ref = newref
end
end
class Linkedlist
def initialize
#size = 0
#header = nil
end
def add_var(value)
#aize = #size + 1
if #header == nil
#header = Node.new(value) #the issue comes here, in the moment when I try to make a new class of Node
else
nodeActual = #header
while nodeActual.get_ref != nil
nodeActual = nodeActual.get_ref
end
nodeActual.set_ref(Node.new(value))
end
end
#def print_list
#end
def get_size
return #size
end
end
list = Linkedlist.new
stop = nil
while stop != -1
a = gets.chomp
if a.to_i == -1
stop = -1
else
list.add_var(a)
end
end
#list.print_list
you have a typo in Node class, rename intialize to initialize (missing i)

Resources