JRuby String Class Methods Not Available - ruby

I can't seem to call any of Java's string methods from within JRuby. The same style of syntax work for the Math class though. What am I doing wrong?
#! /usr/bin/env jruby
require 'rubygems'
require 'java'
puts java.lang.Math::max(1000,200)
puts java.lang.Math::PI
# this doesn't work
puts java.lang.String::toUpperCase("we, the people")
# this doesn't work either
JString = java.lang.String
puts JString.toUpperCase('We, the people')
#toUpperCase exists though, see below
puts java.lang.String.java_class.declarSed_instance_methods

I think this is what you are trying to do:
java.lang.String.new("we, the people").toUpperCase
As mentioned by #Jesper, toUpperCase is an instance method with the String class. Using it as a static method will not work.
Also note, the class returned is of native Ruby type.

Related

Require statement usage in ruby

Is there any difference between these two sample Ruby programs? It seems the same. require just includes the Ruby program on memory.
require_sample1.rb
class Klass
require "./effective_module"
include Mod
end
require_sample2.rb
require "./effective_module"
class Klass
include Mod
end
effective_module.rb
module Mod
end
With the sample code you've given, the behavior is effectively the same. However, it won't always be the same. For example, take the following code:
effective_module.rb
module Foo; end
require_sample.rb
require "./effective_module"
class Foo
end
When you run ruby require_sample.rb you'll get the following error:
require_sample.rb:2:in `<main>': Foo is not a class (TypeError)
This demonstrates to us that on line 2, when class Foo is reached, Foo has already been defined (by effective_module.rb) as a module, and Ruby won't let you redefine a module as a class.
Now suppose we make the following change:
require_sample.rb
class Foo
require "./effective_module"
end
Now when you run ruby require_sample.rb, you get a different error:
.../effective_module.rb:1:in `<top (required)>': Foo is not a module (TypeError)
This time Foo is already defined as a class when the require is reached. Ruby won't let you redefine a module as a class.
Obviously this isn't the kind of code you'd write in the real world, but hopefully it helps demonstrate that where you put your requires does matter.

How do I turn a hash to a string in Puppet DSL?

I have a hash of hashes that I need to embed in an exec resource command. My thought was to serialize the hash to a string and interpolate it into the exec call. The exec call will be executing ruby code via ruby -e 'ruby code here'.
Using irb, I know that hash.to_s creates a single line parse-able version of the hash. Or I could use json. I doubt you can call to_s in puppet, but am not sure.
The stdlib for Puppet has parseyaml and parsejson to deserialize, but is there a way to serialize to a parse-able string? I can write a custom puppet function to do it, but prefer an already built in solution if there is one.
Update
I am considering defining a puppet function. I have never written one before, so am not sure of the syntax. Here is my first attempt:
Puppet::Parser::Functions.newfunction(
:serialize_hash,
:arity => 2,
:doc => "Serialize a hash to any depth and optionally escape the double quotes.",
:type => :rvalue) do |args|
hash = args[0]
escape_quotes = args[1]
serialized = hash.to_s
if (escape_quotes)
serialized.sub!(/"/, "\\\"")
end
serialized
end
You can always execute ruby code inline with your puppet module:
$my_string = inline_template('<%= #my_hash.to_s %>')
Obviously it is important to not overuse this, but it is particularly useful when a very simple ruby function can achieve what you need.

Why does Date exist in Ruby before it is required?

In Ruby, I'd expect that a class which has not been required would raise an "uninitialized constant" error. This is the case with CSV, for instance.
However, Date behaves strangely: it is available, but apparently does not work, until it is required.
~: irb
>> Date.new(2012,7,24)
ArgumentError: wrong number of arguments(3 for 0)
>> require 'date'
=> true
>> Date.new(2012,7,24)
=> #<Date: 2012-07-24 ((2456133j,0s,0n),+0s,2299161j)>
What explains this behavior?
I believe that date doesn't come from irb, but from rubygems, specifically the file where Gem::Specification is defined:
class Date; end # for ruby_code if date.rb wasn't required
I believe they needed any Date class defined so that the interpreter doesn't complain further down in the Specification class.
Similar to this question. irb loads a Date class by default, but Ruby itself doesn't (try e.g. puts Date.new in a file).
It seems that the Date class that irb loads is different to the distribution class, as you have pointed out. Furthermore this only seems to be the case in Ruby 1.9 -- if I try it in 1.8, I get the same class methods before and after the require.
Partial answer: it seems that the incomplete Date class comes from irb, not from ruby.

Call ruby function from command-line

How can I directly call a ruby function from the command-line?
Imagine, I would have this script test.rb:
class TestClass
def self.test_function(some_var)
puts "I got the following variable: #{some_var}"
end
end
If this script is run from the command-line (ruby test.rb), nothing happens (as intended).
Is there something like ruby test.rb TestClass.test_function('someTextString')?
I want to get the following output: I got the following variable: someTextString.
First the name of the class needs to start with a capital letter, and since you really want to use a static method, the function name definition needs to start with self..
class TestClass
def self.test_function(someVar)
puts "I got the following variable: " + someVar
end
end
Then to invoke that from the command line you can do:
ruby -r "./test.rb" -e "TestClass.test_function 'hi'"
If you instead had test_function as an instance method, you'd have:
class TestClass
def test_function(someVar)
puts "I got the following variable: " + someVar
end
end
then you'd invoke it with:
ruby -r "./test.rb" -e "TestClass.new.test_function 'hi'"
Here's another variation, if you find that typing ruby syntax at the command line is awkward and you really just want to pass args to ruby. Here's test.rb:
#!/usr/bin/env ruby
class TestClass
def self.test_function(some_var)
puts "I got the following variable: #{some_var}"
end
end
TestClass.test_function(ARGV[0])
Make test.rb executable and run it like this:
./test.rb "Some Value"
Or run it like this:
ruby test.rb "Some Value"
This works because ruby automatically sets the ARGV array to the arguments passed to the script. You could use ARGV[0] or ARGV.first to get the first argument, or you could combine the args into a single string, separated by spaces, using ARGV.join(' ').
If you're doing lots of command-line stuff, you may eventually have a use for Shellwords, which is in the standard ruby lib.
If you have multiple arguments to call in a example like this:
class TestClass
def self.test_function(some_var1, some_var2)
puts "I got the following variables: #{some_var1}, #{some_var2}"
end
end
run it like this (the arguments need to be comma separated in this case)
ruby -r "./test.rb" -e "TestClass.new.test_function 'hi','Mike'"
#!/usr/bin/env ruby
class A
def run
p :Hello_world
end
self
end.new.run
The usual way to script Ruby is to just use the top level execution environment called main. You can just start defining methods and code you write outside of a class, and these will be executed directly. (BTW, code inside a class but outside any method will run "by itself" also.)
Anyway, I'm with you ... I like writing all code in a named class and instantiating that class, so you can combine the techniques .. have the class return its own object .. and then use just a little of that top level code to allocate, initialize, and then dot into the class.
With this, you can just type $ ruby test.rb and it will do what you want. Or you can chmod +x test.rb; ./test.rb since we did add a shebang.
If you are working on a command line interface, then I would suggest to have a look at thor.
Thor directly maps your commands to methods within the defined class, see the thor wiki for an example.
Just an extension to Ingenu's answer for the case that the function does not print something out, but does return something.
We would have the following test.rb
class TestClass
def self.test_function(some_var)
return "I got the following variable: " + some_var
end
end
Then to invoke that from the command line and get the return value:
ruby -r "./test.rb" -e "puts TestClass.test_function('hi')"
If you know that how to call an rb file from commandline
ruby yourfile.rb
This can do the whole trick for you.
What you have done is, just defined your methods in the class. Now you can call it below the definition. If you still want to read, wide open your eyes
class TestClass
def self.test_function(some_var)
puts "I got the following variable: #{some_var}"
end
test_function(var)
end

Does Ruby 1.8 have an equivalent to 1.9's __callee__?

I need to grab the name of the lexically enclosing method in Ruby 1.8; e.g.
def foo
this_method = __callee__ # => 'foo'
end
The above code is valid in Ruby 1.9, but fails in 1.8, since __callee__ was introduced in 1.9.
Any suggestions for doing this in 1.8? Kernel#caller looked promising, but seems to give me the call stack starting with the caller of the method, not the method itself.
I guess I could throw an exception, catch it, and grab the first element in the Exception#backtrace array, but my gut tells me that will be slow.
On Ruby 1.8.7 there is the __method__, not sure about 1.8.6.
Anyway, You can monkey patch the Kernel module:
module Kernel
# Defined in ruby 1.9
unless defined?(__callee__)
def __callee__
caller[0] =~ /`([^']*)'/ and $1
end
end
end
Have you checked whether the "backports" gem has it?

Resources