Ruby Shoes - Problem with edit list and if-statement - ruby

I want to run a program which changes the background depending on which gender you choose in a edit list.
Shoes.app do
para "your gender"
list_box :items => ["female", "male"],
width => 120, :choose => "weiblich" do |list|
#gender.text = list.text
end
#gender = para "#{#gender}"
button "change colours" do
if #gender ="female"
background (deeppink)
else #gender ="male"
background (dodgerblue)
end
end
end
The problem is - whatever I do, if I use the if-statement, suddenly always "female" is in the variable and my background is pink, altough when I pick "male". If I just do
...
button "change colours" do
para #gender
end
....
the right gender is in the variable #gender. Does anybody know what the problem is?

You need if #gender == "female" and if #gender == "male" - note the two = symbols.
You're performing an assignment, not testing equality.

Related

How to stub/mock multiple options depending on user input with Rspec 3.4

I am completely new to Rspec, and it's my first time trying to test outside of the rails framework. I am simply trying to understand how I can possibly mock behavior of my app when the implementation is pretty complex.
I want to be able to mimic the behavior of calling customize_gender inputting a choice and checking that when 1 is entered the result is 'Male', when 2 is entered the result is 'Female', etc.
I also want to be able to check if the instance variable of #gender was correctly set, which is why I added the attr_reader :gender in the first place. I have been trying a few things, but I guess I do not understand how mocks in general work to be able to find a solution. I have looked at similar questions but they do not seem to work for my scenario. Any insight is greatly appreciated!
Main file (person.rb)
class Person
attr_reader :gender
GENDER = { male: 'Male', female: 'Female', other: 'Other'}
def initialize
puts customize_gender
end
def customize_gender
display_hash_option GENDER, 'What is your gender? '
choice = gets.chomp.to_i
#gender =
case choice
when 1
GENDER[:male]
when 2
GENDER[:female]
when 3
print 'Enter your preferred gender: '
gets.chomp.downcase
else
puts 'Error: Person -> customize_gender()'
end
end
private
def display_hash_option(hash, saying = '')
print saying
hash.each_with_index { |(key, _value), index| print "#{index.next}) #{key} " }
end
end
Rspec File (spec/person_spec.rb)
require_relative "../person"
describe Person do
let(:person) { Person.new }
allow(Person).to receive(:gets).and_return(1,2,3)
person.customize_gender
expect(person.gender).to eq 'Male'
# allow(person).to receive(:customize_gender).and_return('Male')
# expect(Person).to receive(:puts).with('What is your gender?')
# allow(Person).to receive(:gets) { 1 }
# expect(person.gender).to eq 'Male'
end
Here's how you could do it, the only thing mocked here is that gets is set to '1' (remember it's a string in this case as gets input is always a string)
RSpec.describe Person do
subject { Person.new }
it 'returns male as gender when male is chosen' do
allow(subject).to receive(:gets).and_return('1')
subject.customize_gender
expect(subject.gender).to eq('Male')
end
end
For when 3 you could use the following.
RSpec.describe Person do
subject { Person.new }
it 'returns other as gender when other has been entered' do
allow(subject).to receive(:gets).and_return('3', 'other')
subject.customize_gender
expect(subject.gender).to eq('other')
end
end

Ruby + Prawn: How do I make text stick to bottom of page?

I have footer text that needs to stay at the bottom of the page: "If you have any questions regarding your order, you may contact us". How would I position it absolutely?
Here's one way from the docs:
file = "lazy_bounding_boxes.pdf"
Prawn::Document.generate(file, :skip_page_creation => true) do
point = [bounds.right-50, bounds.bottom + 25]
page_counter = lazy_bounding_box(point, :width => 50) do
text "Page: #{page_count}"
end
10.times do
start_new_page
text "Some text"
page_counter.draw
end
end

How can I display the output of an array in Ruby Shoes?

I've got this as my code
openAll = File.open('N:\Josh\Blondie\db.txt')
allNumbers = Array.new
allNumbers=[]
openAll.each_line {|line|
allNumbers.push line
}
puts allNumbers
and I'd like to be able to display the output of this code in a new window with Ruby Shoes, I can't seem to get it to display anything though. The contents of the file are names and phone numbers.
Any ideas?
Here's an example of outputting text to a shoes window. Using a puts statement just outputs to the shell, not to the Shoes app.
Shoes.app :title => "GUI RAW file converter, for the CLI challenged",
:resizable => true do
background white
stack do
flow {
background gray, :height => 30
caption "Caption", :margin => 8, :stroke => white
stack {
para 'This is a fancy line I just printed to the window'
####### Here's an example line you could use to put out the array...
allNumbers.each do |number|
para "#{number}"
end
}
}
end
end
I guess you should use the method Kernel#alert instead of Kernel#puts.
http://shoesrb.com/manual/Built-in.html

How to make an element take up all-the-width-that-is-left?

Shoes.app do
flow do
file = "something with variable length"
para "Loading #{file}: "
progress :width => -300
end
end
As you can see from the code I am trying to display a progress bar that goes from the end of the text until the right edge of the application window.
When the text has a fixed length this solution works but it doesn't once the text changes length in the above fragment: there will be either too little or too much space for the progress bar.
Is there a solution to this problem?
I tried asking the para element it's width but it is 0???
As I mentioned before, you have to get the width of the textblock after it is calculated. Try this:
Shoes.app do
flow do
file = "something with variable length"
#p = para "Loading #{file}: "
#prog = progress
start do
#prog.width = #prog.parent.width - #p.width
end
end
button 'Change text!' do
text = #p.text
#p.text = text + '1'
#prog.width = #prog.parent.width - #p.width
end
end

How can I create a hidden button in Shoes?

In Shoes, I'd like to create a button that is initially hidden. I've tried passing :hidden => true as part of the button style, as well as calling #button.hide() after creating it, but it remains obstinately visible.
I've been able to work around this by not creating the button until I want it shown, but that requires checking to see if it already exists, rather than just using it.
Not at present. Buttons are still fairly unreliable in Shoes, especially on Windows. You can work around the issue by putting the button in a slot and hiding or showing the slot, but you may discover that the button won't hide again once it has been clicked once:
Shoes.app do
para 'This is some text.'
#flow = flow :width => 50, :hidden => true do
button 'a' do |btn|
alert 'Hello, World!'
end
end
button 'toggle' do
#flow.toggle
end
para 'Blah blah blah'
end
Luckily, there is a way out: slots. Slots can be given a click event, which makes them behave much as a button does. In fact, you can make fairly decent buttons out of slots.
Here's something I cobbled together. It lets you use the pesto_button method to generate buttons built on flows. You can modify it to fit your needs, including such things as using an image as the background, modifiable text (with auto-expanding width?), ability to change styles on the fly, etc:
class PestoButton < Widget
def initialize (text, opts = {})
#border_color = opts[:border_color] || gray
#border_width = opts[:border_width] || 3
#color = opts[:up_color] || gainsboro
#click_color = opts[:down_color] || #border_color
#width = opts[:width] || 80
#click = block_given? ? Proc.new { yield } : nil
#text = text
#visible = true
#flow = flow :width => #width do
background #color
border #border_color, :strokewidth => #border_width
para #text, :align => 'center'
end
#flow.click do
#flow.clear
#flow.append do
background #click_color
border #border_color, :strokewidth => #border_width
para #text, :align => 'center'
end
end
#flow.release do
#flow.clear
#flow.append do
background #color
border #border_color, :strokewidth => #border_width
para #text, :align => 'center'
#click.call if #click
end
end
end
def click
#click = block_given? ? Proc.new { yield } : nil
end
def show
#flow.show
end
def toggle
#flow.toggle
end
def hide
#flow.hide
end
end
Shoes.app do
para 'This is some text.'
#btn = pesto_button 'Click me!' do
alert 'Hello, World!'
end
button 'toggle' do
#btn.toggle
end
button 'new block' do
#btn.click do
alert 'Goodbye, World!'
end
end
button 'no block' do
#btn.click #Clears the click method
end
para 'Blah blah blah'
end

Resources