Turning an argument into a receiver - ruby

I created the following extension
class String
def is_a_number? s # check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
end
How can I make it work as a chained method?
is_a_number?("10") # returns true
"10".is_a_number? # returns an error (missing arguments)
Update
Thanks sawa, mikej and Ramon for their answers. As suggested, I changed the class to Object and got rid of the argument (s):
class Object
def is_a_number? # check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) != nil
end
end
It now works perfectly fine:
23.23.is_a_number? # > true
Thanks guys...

When you write "10".is_a_number?, you already have the object "10" you want to check for, which is the receiver of is_a_number?, so your method doesn't need to take any parameters.
Because match is an instance method on String, you don't need to specify a receiver for it. It will just operate on the same object on which is_a_number? was called. Because you know you already have a String object, the to_s isn't needed either.
Just write it as:
class String
# check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
def is_a_number?
match(/\A[+-]?\d+?(\.\d+)?\Z/) != nil
end
end
Ramon's suggestion that you may want to put your extension on Object rather than on String is a good point if you don't know if the object you're testing is going to be a string.
Also, what you're describing isn't really what is meant by method chaining; it's just calling a method on an object. Method chaining is where the return types of methods are set up so that several methods can be called in sequence e.g in Rails, something like
User.where(:name => 'Mike').limit(3) # find the first 3 Mikes
is an example of method chaining.

It seems like you want to patch Object instead of String (since you are calling to_s):
class Object
def is_a_number?
to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/).nil?
end
end
You could also look at replacing with it with validates numericality: true on your model.

Related

Ruby calling hash values returns nil

I have a code
def pitch_class(note)
note_hash = {:C=>0, :D=>2, :E=>4, :F=>5, :G=>7, :A=>9, :B=>11}
note_hash[:note]
end
but whenever I try to call the value inside it returns nil.
pitch_class("C")
#=> nil
How can I call the values using the key as the argument?
Thanks!
"C" != :C. Therefore, pitch_class(:C) will work.
You can also use String#to_sym to force the argument inside the function, if you want to be able to accept a string argument. Or you can create the hash with string keys in the first place.
EDIT: Also, :note is not note.
EDIT2: As a performance tweak, I'd rather have note_hash declared outside the method, rather than instantiating it each time the method is called. Stuffing it into a class constant (NOTE_HASH) would be the best way to handle it.
You hardcoded :note symbol instead of reading parameter passed to your method:
def pitch_class(note)
note_hash = {:C=>0, :D=>2, :E=>4, :F=>5, :G=>7, :A=>9, :B=>11}
note_hash[note.to_sym]
end

Ruby: Retrieving values from method parameters

I'm trying to figure out how I can create a method in Ruby where I can retrieve values from the method's parameters such as strings/integers.
For example, if this were a function coded in C, it might be done similar to this:
main()
{
int value;
GetAnIntegerValue(value);
printf("The value is %d", value);
}
// The "value" integer variable is passed to it, and updated accordingly because of the use of the ampersand prior to the parameter
GetAnIntegerValue(&int value)
{
value = 5;
}
// The output would be "The value is 5"
I think the term for this is pass by value but I'm not sure. My mind is a little vague on this area and I couldn't find many decent results.
Here's my example Ruby function, the array that the parameters are being assigned to is only local to the class which is the reason for this usage:
def getRandomWordAndHint(&RandomWord, &RandomHint)
randIndex = rand(7)
RandomWord = EnglishLevel1Word[randIndex]
RandomHint = EnglishLevel1Hint[randIndex]
end
Cheers!i
Ruby is pass-by-value. Always. No exceptions. You cannot do pass-by-reference in Ruby.
What you can do, is put the object you want to change into some sort of mutable container:
class MutableCell
attr_accessor :val
def initialize(val)
self.val = val
end
end
def change_the_value(cell)
cell.val = 5
end
value = MutableCell.new(42)
change_the_value(value)
value.val
# => 5
Of course, you can just use an Array instead of writing your own MutableCell class, this is just for demonstration.
However, mutable state is a bad idea in general, and mutating arguments passed to methods is a really bad idea especially. Methods know about their own object (i.e. self) and thus can safely modify it, but for other objects, that's generally a no-go.

How to make a Ruby method to pass output parameters (change the value of referenced arguments)?

I'm trying to make a method with output arguments in ruby.
I read differents posts here and here about the discussion of wether ruby pass its arguments by-value or by-reference and
I undersand that on a strict sens, Ruby always pass-by-value, but the value passed is actually a reference. Reason why there is so much debate on this.
I find out that there are several ways to change the value of the referenced variable.
For instance with the replace method when its an Array, a Hash or a String, or merge! when it's a hash.
I found out that with integer, I can change and pass the value outside my method without any special method use.
My question is about other objects.
For instance I want to retrieve the 'id' attribute of an object, and the object reference itself :
class RestaurantController < ApplicationController
def pizza_to_deliver(pizza_name, id_of_the_order, pizza)
# pizza to eat
pizza = Pizza.where(:name => pizza_name).first
# unknown pizza
return false if pizza.nil?
# first customer order about this pizza
id_of_the_order = Orders.where(:pizza_id => pizza.id).first
true
end
end
my_pizza_name = 'margerita'
My_order_id = nil
my_pizza = nil
my_restaurant = RestaurantController.new
if my_restauant.pizza_to_deliver(my_pizza_name, My_order_id, my_pizza) then
puts "Pizza to deliver : #{my_order_id}"
rex_dog.eat(my_pizza)
end
How to make this works ? (order_id and my_pizza remains with nil)
Ruby has only pass by value, just like Python and Java. Also like Python and Java, objects are not values directly, and are manipulated through references.
It seems you already understand how it works -- assigning to a local variable never has any effect on a caller scope. And to "share" information with the caller scope other than returning, you must use some method on the object to "mutate" the object (if such a method exists; i.e. if the object is mutable) that is pointed to by the passed reference. However, this simply modifies the same object rather than giving a reference to a new object, which you want.
If you are not willing to return the value, you can pass a mutable container (like an array of one element) that the called function can then mutate and put whatever in there and have it be seen in the caller scope.
Another option is to have the function take a block. The function would give the block the new value of pizza, and the block (which is given by the caller) can then decide what to do with it. The caller can pass a block that simply sets the pizza in its own scope.
For the most part, out parameters are a workaround for languages that don't have multiple-value return. In Ruby, I'd just return an Array containing all the output values of the function. Or make the mutable values instance variables in an object and the function a method on that object.
Thanks for both answers.
It seems I came out with an equivalent solution at last : the mutable container.
I created a new class 'OutputParameter' that contains (as attr_accessors) the parameters that I want to output from my method. Then I passed an instance of this class to my method.
class OutputParameters
attr_accessor :order_id, pizza
end
class RestaurantController < ApplicationController
def pizza_to_deliver(pizza_name, output_parameters)
# pizza to eat
pizza = Pizza.where(:name => pizza_name).first
# unknown pizza
return false if pizza.nil?
# first customer order about this pizza
id_of_the_order = Orders.where(:pizza_id => pizza.id).first
# Output values returned
output_parameters.pizza = pizza
output_parameters.order_id = id_of_the_order
true
end
end
my_pizza_name = 'margerita'
my_output = OutputParameters.new
my_restaurant = RestaurantController.new
if my_restaurant.pizza_to_deliver(my_pizza_name, my_output) then
puts "Pizza to deliver : #{my_output.order_id}"
rex_dog.eat(my_output.pizza)
end
The hash or array you suggested seems even a better idea as it is more adaptative : I wouldn't have to declare a class.
I would just use the merge! method
class RestaurantController < ApplicationController
def pizza_to_deliver(pizza_name, output_hash)
# pizza to eat
pizza = Pizza.where(:name => pizza_name).first
# unknown pizza
return false if pizza.nil?
# first customer order about this pizza
id_of_the_order = Orders.where(:pizza_id => pizza.id).first
# Output values returned
output_hash.merge!({:pizza => pizza})
output_hash.merge!({:id_of_the_order => id_of_the_order})
true
end
end
my_pizza_name = 'margerita'
my_output_hash = {}
my_restaurant = RestaurantController.new
if my_restaurant.pizza_to_deliver(my_pizza_name, my_output_hash) then
puts "Pizza to deliver : #{my_output_hash[:id_of_the_order]}"
rex_dog.eat(my_output_hash[:pizza])
end
You could use multiple return values like this:
def maybe_get_something
...
return nil, "sorry" if bad_condition
...
something, nil
end
...
something, err = maybe_get_something
if !err.nil?
handle(err)
return
end
do_something_with(something)
Very similar to what people do when using Go:
f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
// do something with the open *File f

How can I make a custom Ruby type behave like a string?

If I have a custom Ruby class representing some string type, as in
class MyString
end
Which functions should I implement in order to make the following use cases possible:
Passing a Ruby string whenever a MyString is expected
Passing a MyString whenever a Ruby string is expected
Comparing a Ruby string with a MyString value (it shouldn't matter whether I use s == t or t == s).
I saw various interesting functions like to_s, cmp, == and eq already, but it's not clear to me when each of them is called.
My concrete use case is that I'm writing a Ruby extension using the C API which exposes functions taking (and returning) values of a custom string type (QString, to be precise) which my extension also registers. However, I'd like to make those custom strings behave as intuitive as possible. Unfortunately I can't just return Ruby strings from my C code since it should be possible to call Qt methods on the strings.
There are at least three approaches:
class MyString < String; ...; end
Define #to_s
Define #to_str
Doing both #2 and #3 will make the object act very much like a real String even if it isn't a subclass.
#to_s is an explicit converter, meaning it must appear in Ruby code to work.
#to_str is an implicit converter, meaning the Ruby interpreter will attempt to call it when it wants a String but is given something else.
Update:
Here is an example of some fun you can have with to_str:
begin
open 1, 'r'
rescue TypeError => e
p e
end
class Fixnum
def to_str; to_s; end
end
open 1, 'r'
When run, the first open fails with TypeError but the second proceeds to looking for 1.
#<TypeError: can't convert Fixnum into String>
fun.rb:9:in `initialize': No such file or directory - 1 (Errno::ENOENT)
from fun.rb:9:in `open'
Although it's tempting to sub-class String to give it a new initialize method that will import these QString-type strings, you may just want to tack on an extension to String that helps with the conversion so you don't have to re-implement a version of String itself.
For instance, with two methods you could pretty much have this done:
class String
def self.from_qstring(qstring)
new(...)
end
def to_qstring
# ...
end
end
Having multiple storage types for String is not going to be a problem until you start comparing them, but given that Ruby's String is quite robust, writing a work-alike is difficult.
It's not generally a good idea to subclass classes that were built by someone else in Ruby, because too many things can go wrong. (You might, for example, override an internal method without knowing it.)
1) define Mystring.to_s to get automatic conversion from a Mystring to a String.
2) Not sure what you mean by this. If you want a String method that returns a Mystring, you will have to monkey-patch String:
Class String
def to_mystring
return Mystring.new(self)
end
end
3) to get t == s (assuming s is an instance of String and t an instance of Mystring) define <=>. To get s == t you will have to monkey patch String again, though.
Since I was looking for something similar, but none of the other answers worked for me, I'll post what did work for me.
Found in this blog post which discourage the use of inheriting String and instead use simple delegator.
Inheriting from SimpleDelegator create an object which delegate everything to a string of your choice but on which you add behavior as you see fit.
class ChunkyBacon < SimpleDelegator
def initialize(content)
#content = content
super #content
end
def chunky_bacon?
#content == 'chunky_bacon'
end
end
test = ChunkyBacon.new('choco pizza') # => 'choco pizza'
test.chunky_bacon? # => false

Stepping into Ruby Meta-Programming: Generating proxy methods for multiple internal methods

I've multiply heard Ruby touted for its super spectacular meta-programming capabilities, and I was wondering if anyone could help me get started with this problem.
I have a class that works as an "archive" of sorts, with internal methods that process and output data based on an input. However, the items in the archive in the class itself are represented and processed with integers, for performance purposes. The actual items outside of the archive are known by their string representation, which is simply number_representation.to_s(36).
Because of this, I have hooked up each internal method with a "proxy method" that converts the input into the integer form that the archive recognizes, runs the internal method, and converts the output (either a single other item, or a collection of them) back into strings.
The naming convention is this: internal methods are represented by _method_name; their corresponding proxy method is represented by method_name, with no leading underscore.
For example:
class Archive
## PROXY METHODS ##
## input: string representation of id's
## output: string representation of id's
def do_something_with id
result = _do_something_with id.to_i(36)
return nil if result == nil
return result.to_s(36)
end
def do_something_with_pair id_1,id_2
result = _do_something_with_pair id_1.to_i(36), id_2.to_i(36)
return nil if result == nil
return result.to_s(36)
end
def do_something_with_these ids
result = _do_something_with_these ids.map { |n| n.to_i(36) }
return nil if result == nil
return result.to_s(36)
end
def get_many_from id
result = _get_many_from id
return nil if result == nil # no sparse arrays returned
return result.map { |n| n.to_s(36) }
end
## INTERNAL METHODS ##
## input: integer representation of id's
## output: integer representation of id's
private
def _do_something_with id
# does something with one integer-represented id,
# returning an id represented as an integer
end
def do_something_with_pair id_1,id_2
# does something with two integer-represented id's,
# returning an id represented as an integer
end
def _do_something_with_these ids
# does something with multiple integer ids,
# returning an id represented as an integer
end
def _get_many_from id
# does something with one integer-represented id,
# returns a collection of id's represented as integers
end
end
There are a couple of reasons why I can't just convert them if id.class == String at the beginning of the internal methods:
These internal methods are somewhat computationally-intensive recursive functions, and I don't want the overhead of checking multiple times at every step
There is no way, without adding an extra parameter, to tell whether or not to re-convert at the end
I want to think of this as an exercise in understanding ruby meta-programming
Does anyone have any ideas?
edit
The solution I'd like would preferably be able to take an array of method names
##PROXY_METHODS = [:do_something_with, :do_something_with_pair,
:do_something_with_these, :get_many_from]
iterate through them, and in each iteration, put out the proxy method. I'm not sure what would be done with the arguments, but is there a way to test for arguments of a method? If not, then simple duck typing/analogous concept would do as well.
I've come up with my own solution, using #class_eval
##PROXY_METHODS.each do |proxy|
class_eval %{ def #{proxy} *args
args.map! do |a|
if a.class == String
a.to_i(36)
else
a.map { |id| id.to_i(36) }
end
end
result = _#{proxy}(*args)
result and if result.respond_to?(:each)
result.map { |r| r.to_s(36) }
else
result.to_s(36)
end
end
}
end
However, #class_eval seems a bit...messy? or inelegant compared to what it "should" be.
class Archive
# define a new method-creating method for Archive by opening the
# singleton class for Archive
class << Archive
private # (make it private so no one can call Archive.def_api_method)
def def_api_method name, &defn
define_method(name) do |*args|
# map the arguments to their integer equivalents,
# and pass them to the method definition
res = defn[ *args.map { |a| a.to_i(36) } ]
# if we got back a non-nil response,
res and if res.respond_to?(:each)
# map all of the results if many returned
res.map { |r| r.to_s(36) }
else
# map the only result if only one returned
res.to_s(36)
end
end
end
end
def_api_method("do_something_with"){ |id| _do_something_with(id) }
def_api_method("do_something_with_pair"){ |id_1, id_2| _do_something_with_pair id_1.to_i(36), id_2.to_i(36) }
#...
end
Instead of opening the singleton to define Archive.def_api_method, you could define it simply using
class Archive
def Archive.def_api_method
#...
But the reason I didn't do that is then anyone with access to the Archive class could invoke it using Archive.def_api_method. Opening up the singleton class allowed me to mark def_api_method as private, so it can only be invoked when self == Archive.
If you're always going to be calling an internal version with the same (or derivable) name, then you could just invoke it directly (rather than pass a definition block) using #send.
class Archive
# define a method-creating method that wraps an internal method for external use
class << Archive
private # (make it private so no one can call Archive.api_method)
def api_method private_name
public_name = private_name.to_s.sub(/^_/,'').to_sym
define_method(public_name) do |*args|
# map the arguments to their integer equivalents,
# and pass them to the private method
res = self.send(private_name, *args.map { |a| a.to_i(36) })
# if we got back a non-nil response,
res and if res.respond_to?(:each)
# map all of the results if many returned
res.map { |r| r.to_s(36) }
else
# map the only result if only one returned
res.to_s(36)
end end
# make sure the public method is publicly available
public public_name
end
end
api_method :_do_something_with
api_method :_do_something_with_pair
private
def _do_something_with
#...
end
def _do_something_with_pair
#...
end
end
This is more like what is done by other meta-methods like attr_reader and attr_writer.

Resources