I'm trying to execute Ruby functions in separate processes on my Windows system. On Mac, I used the Fork method. But that doesn't work on Windows. I also tried the spawn method. But that doesn't seem to work either.
def test_1
puts "Hello"
end
def test_2
puts " World"
end
On Mac (Works)
pid_1 = Fork.do
test_1
end
pid_2 = Fork.do
test_2
end
Process.waitall
On Windows (Doesn't work)
pid_1 = Process.spawn(test_1)
pid_2 = Process.spawn(test_2)
Process.waitall
Exception: NoMethodError - undefined method `spawn' for Process:Module
Ruby version: 2.0
Can someone help me in understanding what I'm missing.
Edit: Found the issue. The Ruby version was old (1.8.7) which doesn't implement this method.
Related
I wrote a basic ruby program with TextMate in Mac OS:
def hello
puts " This works!"
end
name it Check-it.rb
I open a Terminal session, cd to the directory where the program is stored.
Then I type
ruby Check-it.rb
And nothing appears.
ruby -v
shows me the version, so it's there.
But with this and every other Ruby program, nothing appears.
As others already pointed out. The code in your file
def hello
puts " This works!"
end
defines a method called hello that outputs a string. But that method is never called. To actually call that method and run it change your code in the file to
def hello # this block defines the `hello` method
puts " This works!"
end
hello # this line calls the method `hello`
I think you are not calling this method at all. Call this method and then run your code, it will work.
Consider the following code:
module M
def original ; puts __callee__ ; end
alias_method :aliased, :original
end
class A
include M
end
A.new.original
#⇒ original
A.new.aliased
#⇒ aliased
The above code runs perfectly fine in Ruby 2.1 and returns the actual method name, as it is supposed to be done by Kernel#__callee__.
Surprisingly enough, the code above does not work as expected in Ruby 2.3.1:
A.new.original
#⇒ original
A.new.aliased
#⇒ original
Is this a desired behaviour I failed to find in release notes, or is it a bug in MRI for 2.3? The same happens for alias.
PS I have created an issue https://bugs.ruby-lang.org/issues/12761
This applies also to attr_writer and attr_accessor.
I've been playing with some simple Ruby code recently and the following snippet does not work in all environments I've run it:
class Human
attr_reader :name
def initialize(name)
#name = name
end
end
hank = Human.new("Hank")
hank.name
This should output "Hank", which it does in my command line irb. In Textmate2 and Aptana Studio 3, nothing outputs when I run this code. All three work as expected if I explicitly define the reader:
def name
puts #name
end
When I play in the Aptana terminal and my usual terminal and type:
$ ruby -v
They both appear to use the same version: ruby 2.0.0p451. What's going on?
attr_reader just doesn't do what you think it does.
try
puts hank.name
rather than
hank.name
and you'll see the output. irb is a special case, it shows you the return value of the last statement executed. ruby on its own won't do that, it only prints things you explicitly tell it to print.
I'm trying to run some windows command line calls in the same system
process using a Ruby Rake task. I need to find the way to do the calls
correctly and this calls can't be dependent on each other.
I know that the 'fork' function can be a solution, but it doesn't work
in Windows. I tried with other functions, like IO.POPEN and
Process.spawn and I didn't find a real solution.
I'm working with Ruby 1.9.3 in windows XP.
task :CmdTest,:value do |t, args|
value=args.value.to_s
begin
$cmd<<("set MYVAR=#{value}")
$cmd<<("set MYVAR")
$cmd<<("exit")
rescue Exception => e
puts e.message
end
end
task :CmdTest3 do
IO.popen("cmd", "r+") do |io|
th = Thread.new(io) do |chan|
chan.each {|line| puts line}
end
$cmd.each do |f|
io.puts f
end
io.close_write
th.join
end
end
Take a look at win32utils, is that what you are after?
I have the following code
def start_sunspot_server
unless #server
pid = fork do
STDERR.reopen("/dev/null")
STDOUT.reopen("/dev/null")
server.run
end
at_exit { Process.kill("TERM", pid) }
wait_until_solr_starts
end
end
How would I effectively go about testing it using rspec?
I thought something along
Kernel.should_receive(:fork)
STDERR.should_receive(:reopen).with("/dev/null")
STDOUT.should_receive(:reopen).with("/dev/null")
server.should_receive(:run)
etc
I'm confused by the #server instance variable and server method in your example, but here is an example that should help you get where you're trying to go:
class Runner
def run
fork do
STDERR.reopen("/dev/null")
end
end
end
describe "runner" do
it "#run reopens STDERR at /dev/null" do
runner = Runner.new
runner.should_receive(:fork) do |&block|
STDERR.should_receive(:reopen).with("/dev/null")
block.call
end
runner.run
end
end
The key is that the fork message is sent to the Runner object itself, even though its implementation is in the Kernel module.
HTH,
David
David's solution didn't work for us. Maybe it's because we're not using RSpec 2?
Here's what did work.
def run
fork do
blah
end
end
describe '#run' do
it 'should create a fork which calls #blah' do
subject.should_receive(:fork).and_yield do |block_context|
block_context.should_receive(:blah)
end
subject.run_job
end
end
I'm not sure how this would apply when calling a constant, such as STDERR, but this was the only way we were able to accomplish fork testing.