MacRuby xcode label not working - ruby

class HelloApp
attr_accessor :label, :text_field, :button
def clickedButton(sender)
# implementation
your_name = self.text_field.stringValue
self.label.stringValue = "Hello, #{your_name}"
end
end
The above code is in HelloApp.rb
The problem is when I type something into the textbox, and click the button, the label just says "Hello, " and not "Hello, namegoeshere"
I am using MacRuby .4 by the way.

Your code works for me in MacRuby .5
Does this log the user input to the console?
your_name = self.text_field.stringValue
puts "Your name is #{your_name}"
If not, you may not have the text_field hooked up to the NSTextField in Interface Builder.

Related

Ruby Class Output

I am trying my hands at Ruby, below is the code that I am writing in 2 different ways to understand Ruby Classes. In first block I am using accessor method (combination of accessor read & write) and I want to print final line as "lord of the rings is written by Tolkien and has 400 pages". How can I make that happen? I understand that adding string and integer will throw an error. I can get them to print on separate lines, its just that I can't get them in a sentence.
class Book
attr_accessor :title, :author, :pages
end
book1 = Book.new()
book1.title = 'lord of the rings'
book1.author = 'Tolkien'
book1.pages = 400
puts book1.title
puts book1.author
puts book1.pages
#puts book1.title + " is written by " + book1.author + " and has " + book1.pages + " pages" <<<this errors out for known reason>>>
Second piece of code doing the same thing but I am using instance variable and have figured out how to get desired output. However, please advise if there's a better way of doing this?
class Novel
def initialize(title, author, pages)
#title = title
#author = author
#pages = pages
end
def inspect
"#{#title} is written by #{#author} and has #{#pages} pages"
end
end
novel1 = Novel.new('harry potter', 'JK Rowling', 300)
puts novel1.inspect
In your first example you are providing access the info you want and leaving it up to the client to format the output. For example you could have gotten what you wanted by adding this line in place of your commented line.
puts "#{book1.title} is written by #{book1.author} and has #{book1.pages} pages"
In your second example you are "pushing" that code down into the Novel class and proving a method to produce the output you want. BTW, don't use inspect as a method name, inspect is already a defined method
For example the following will print the same info twice.
class Novel
attr_accessor :title, :author, :pages
def initialize(title, author, pages)
#title = title
#author = author
#pages = pages
end
def info
"#{#title} is written by #{#author} and has #{#pages} pages"
end
end
novel = Novel.new('harry potter', 'JK Rowling', 300)
puts novel.info
puts "#{novel.title} is written by #{novel.author} and has #{novel.pages} pages"

Connect function to a QPushButton press

I want to execute a user defined function after a button was pressed. I don't know how to use the connect function correctly to achieve the behavior specified in the code snippet.
#!/usr/bin/env ruby
require 'Qt4'
def do_sth
print "did something"
end
app = Qt::Application.new(ARGV)
btn = Qt::PushButton.new('Button')
btn.resize(75, 30)
btn.setFont(Qt::Font.new('Times', 18, Qt::Font::Bold))
# A button click will close the application.
#Qt::Object.connect(btn, SIGNAL('clicked()'),app, SLOT('quit()'))
#
# FIXME How to execute the function do_sth if the button was pressed?
Qt::Object.connect(btn, SIGNAL('clicked()'),app, SLOT('do_sth()'))
btn.show()
app.exec()
Thanks for your hint, it worked the way you suggested.
#!/usr/bin/env ruby
require 'Qt4'
class Qo < Qt::Object
slots 'do_sth()'
slots 'bla()'
def do_sth
puts "did something"
end
def bla
puts "blabla"
end
end
qobj = Qo.new
app = Qt::Application.new(ARGV)
btn = Qt::PushButton.new('Button')
btn.resize(75, 30)
btn.setFont(Qt::Font.new('Times', 18, Qt::Font::Bold))
Qt::Object.connect(btn, SIGNAL('clicked()'),qobj, SLOT('do_sth()'))
Qt::Object.connect(btn, SIGNAL('pressed()'),qobj, SLOT('bla()'))
btn.show()
app.exec()

RSpec: simulating user input (via gets) without the test prompting for it

I'm coding a game by taking a TDD first approach, and have gotten stuck because the test keeps stopping for user input (repo is here).
I want the test to simulate user input rather than prompting for it, as I've set up some let keywords and have tried to account for user input that comes in via gets.chomp.
Here is where the game prompts for user input:
game.rb
module ConnectFour
class Game
def start_game
puts 'Welcome to Connect Four.'
puts "Enter name of player 1 (red)"
player1name = gets.chomp
player1 = Player.new(player1name)
end
end
end
And here is the test code:
game_spec.rb
require 'spec_helper'
module ConnectFour
describe Game do
let(:game) { Game.new }
let(:player1name) { 'Bob' }
let(:player1) { Player.new(player1name) }
describe 'Instantiate game play objects' do
describe 'Create player 1' do
it 'Provide player 1 name' do
allow_any_instance_of(Kernel)
.to receive(:gets)
.and_return(player1name)
end
it 'Instantiate player 1' do
expect(player1.name).to eq player1name
end
end
end # describe 'Instantiate game play objects'
end # Describe 'Game'
end
So far I've tried encapsulating the gets.chomp in its own method as recommended here but this has no effect. I've also tried prefixing $stdin to gets.chomp statements in the Ruby code but yeah, that was pretty useless. I had asked a similar question here recently and thought I had understood how to simulate user input but obviously not... any help would be appreciated.
use allow_any_instance_of(Object) instead of Kernel. The module Kernel is included into Object. Kernel is not ever actually instantiated because it's a module.
kind of a small point, but it'd be more accurate if you stubbed gets to return a strinng ending in \n, otherwise you could remove the chomp from the tested functionn and the test will still pass
reproducable example
require 'rspec'
require 'rspec/expectations'
test_case = RSpec.describe "" do
it "" do
allow_any_instance_of(Object).to receive(:gets).and_return "something\n"
puts gets.chomp
end
end
test_case.run

Shoes 4 ,Cannot call objects outside main app

Im developing a really simple application in Ruby and decided to use Shoes Gui, im trying to use the new fourth version but i cannot call shoes objects outside the app, for example in the Shoes Manual http://shoesrb.com/manual/Rules.html this code doesn't work:
class Messenger
def initialize(stack)
#stack = stack
end
def add(msg)
#stack.append do
para msg
end
end
end
when i pass the stack object from the app nothing happens, thanks for your help
I think you just missed out reading the manual completely. The manual very clearly says that this could apparently should work but it doesn't since the App object isn't around any more. Fortunately, each shoes object has a app method, so:
You should replace your code with:
class Messenger
def initialize(stack)
#stack = stack
end
def add(msg)
#stack.app do
#stack.append do
para msg
end
end
end
end
Hope it helps :)
I had the same issue described here, but with the right piece of code from the manual. I have found something, so I'm posting it here, hoping it'll help someone (or that someone will explain me what I've not found).
Here is what I had first (it doesn't work, no matter where you put your class instantiation).
class Messenger
def initialize(stack)
#stack = stack
end
def add(msg)
#stack.app do
#stack.append do
para msg
end
end
end
end
Shoes.app do
stack margin: 20, width: 20 do
subtitle "Shoes box"
para "Maaamaaaaa"
button "Mama ?" do
s = Messenger.new(#box)
s.add("Yeah, mama !")
end
end
#box = stack
end
First thing : if you got these two pieces of code in the same file, you could do that :
class Messenger
...
#stack.app do
#box.append do
para msg
end
...
end
It works.
It doesn't work if you remove the #stack.app do block or if you move this class in another file though. If you put your class instantiation somewhere else, it doesn't work either.
More interesting, now, and working even if you put your Messenger class somewhere else, you can do that :
class Messenger
...
def add(msg)
#stack.app do
para msg
end
...
Shoes.app do
...
button "Mama ?" do
#box.append do
s = Messenger.new(#box)
s.add("Yeah, mama !")
end
end
...
end
Now you also can move your class instantiation anywhere in your app block... but it still has to be BEFORE the box you're trying to append to, and that same box has to be declared BEFORE the button which is trying to add to it. Making the thing a bit tricky. Otherwise, you can let your class instantiation here. It means you will create a new object every time you're trying to append something to your box. And it is ugly. But it works.
Edit : just saw that, you can replace the #stack.append do by self.append do in the Messenger class. Though it doesn't really append anything, since it's adding the msg at the begining of your window.
First of all, change class Messenger to class Messenger < Shoes. This is essential for any and all classes in Shoes. Then, put the Shoes.app statement after the end statement of the class, but don't add the do. Your code should look like this:
class Messenger < Shoes
# Your code goes here...
end
Shoes.app [styling goes here]
NOTE: Put the Shoes.app only once, at the end, after all classes have been defined.

Running a Ruby program during development

I'm writing a program in Ruby for the first time (I'm using RubyMine as my IDE), having previously coded mostly in Java.
When programming in Java, I used to regularly 'run' my code after each bit of functionality I had added to it, just to check that it worked properly.
I'm trying to do that with Ruby, but I'm having a little bit of difficulty.
I have the following class, which I will be using as the menu for my program, so it is where I want the user to start off when they run the program:
class Application
# To change this template use File | Settings | File Templates.
def initialize
mainMenu
end
def navigateTo(what)
what.new.display
mainMenu
end
def mainMenu
puts "What would you like to do?
1: Add module to a scheme
2: Remove module from a scheme
3: Query modules
4: Modify module
5: Register a student on a scheme
6: Remove a student from a scheme
7: Register a student on a module
8: Remove a student from a module"
case gets.strip
when "1"
navigateTo Module
addModule
when "2"
navigateTo Module
when "3"
navigateTo Module
when "4"
navigateTo Module
when "5"
navigateTo Student
when "6"
navigateTo Student
when "7"
navigateTo Student
end
end
end
However, when I run the class, the console displays a line stating that it's running it, but then the next line is "Process finished with exit code 0"
I can't work out why this is? In Java, there was a main method, which was where the program would always go for instruction on what to do when it was run... but as far as I can tell with Ruby, there's no need for a main method? If this is the case, how can I run what I've written so far to check that I've written it correctly?
*UPDATED**
Ok, I've added in the line
Application.new
as suggested, and that's brilliant- the menu now prints out. I selected option 1 from the menu, and this line was printed out in the console:
#<Module:0x1bd2c90>What would you like to do?
followed by a printout of the menu again.
Option 1 should navigate to my Module class, which looks like this:
class Module
# To change this template use File | Settings | File Templates.
##moduleScheme = nil
##moduleYear = nil
##moduleTitle = ""
def self.moduleYear
##moduleYear
end
def initialize(v)
#val = v
end
# Set and get the #val object value
def set (v)
#val = v
end
def get
return #val
end
def addModule
moduleName = Module.new(30)
moduleRefNo = Random(100)
#moduleTitle = #moduleTitle
moduleYear(4)
print "What is the name of the module you would like to add?"
moduleName = gets
moduleRefNo
printf "Which year does the module belong to?"
##moduleYear = gets
puts "#{moduleName}, belonging to #{##moduleYear} has been added to the system, with reference number #{moduleRefNo}."
navigateTo Application
end
def addModuleToScheme
moduleName.moduleScheme = schemeName
end
def removeModuleFromScheme
moduleName.moduleScheme = nil
end
def queryModule
end
end
Once the the user has selected option 1 from the main menu, and the program has navigated to the Module class, I expected it to run that class fully, i.e. display the prompts to the user, and read in whatever they type on the keyboard, then navigate back to the menu, as indicated by the line
navigateTo Application
at the end of my 'addModule' function. However, for some reason, it seems to either not be navigating to the Module class, or just skipping straight to the end of it. Can anyone point out what I'm doing wrong here?
When you run a ruby file, it will run the file from beginning to end. In your file, you are just defining a class, so it will create that class in ruby, then do nothing, since you are not telling it to instantiate a instance of that class. At the end of your file, add Application.new, which will create an instance of that class, and, looking at your code, will print and receive input
Your code might look like this:
class Application
def run
puts "What would you like to do?
1: Add module to a scheme
...."
end
...
end
Application.new.run
# here the user will interact with you application

Resources