this is my first post and I'm quite new to programming/this site, so I apologise in advance if I'm doing something wrong/annoying.
I wanted to find a way to define objects without having to do so for each object. I came up with this
class Number
def initialize(name)
#name = name
end
def description
puts "I'm #{#name} "
end
end
a = ["zero", "one","two", "three", "four"]
for i in (0..5) do
a[i] = Number.new(a[i])
end
a[3].description
I'm hoping someone can tell me what kind of Frankensteins monster I've created?
It seems to work, a[3].description returns "I'm three" but does that mean three/a[3] exists as its own object and not an element of an array?
Furthermore if I try to do:
puts a[3]
I get:
<Context::Number:0x000000009b7fd0 #name="three">, #
To clarify I just want to know whether I have actually managed to create objects here, and why on earth when I try and access elements of my array I get that weird feedback (kind of seems like its accessing memory or something, but that is a little beyond me)
My thanks in advance for anyone who replies to this.
All objects stand on their own, regardless of whether they are contained by/in other objects such as Array instances.
Regarding this:
<Context::Number:0x000000009b7fd0 #name="three">, #
...did you mean you get that when you puts a[3] and not puts a?
Every instance of Object and its subclasses has a to_s method that returns a string representation of the object. Since you did not override that in your Number class, it used the default implementation defined in class Object. It is showing you:
1) the class name (I presume you defined Number in side a class or module named Context)
2) the object id (a unique id in the Ruby runtime)
3) the string representation of its instance variable(s)
Also, regarding this:
a = ["zero", "one","two", "three", "four"]
This is equivalent and easier to type (I use 2 spaces for better readability):
%w(zero one two three four)
Also, as Ilya pointed out, map will simplify your code. I'll go a little further and recommend this to do the array initialization:
a = %w(zero one two three four).map { |s| Number.new(s) }
Yes, you have created objects. It's just how Ruby represents a class as a string.
class MyClass
attr_accessor :one, :two
def initialize(one, two)
#one, #two = one, two
end
end
my_class = MyClass.new(1, 2)
my_class.to_s # #<MyClass:0x007fcacb8c7c68>
my_class.inspect # #<MyClass:0x007fcacb8c7c68 #one=1, #two=2>
I have many methods like these two:
def create_machine(name, os_type_id, settings_file='', groups=[], flags={})
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{__method__}".to_sym
args = method(__method__).parameters.map { |arg| arg[1] }
soap_message = Hash[args.map { |arg| [arg, eval(arg.to_s)] }]
VirtualBoxAPI.send_request(#cl.conn, soap_method, #this.merge(soap_message))
end
def register_machine(machine)
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{__method__}".to_sym
args = method(__method__).parameters.map { |arg| arg[1] }
soap_message = Hash[args.map { |arg| [arg, eval(arg.to_s)] }]
VirtualBoxAPI.send_request(#cl.conn, soap_method, #this.merge(soap_message))
end
They have the same implementation but different number of different arguments. There will be tens of such methods in each of tens of classes. So I thought I'd use some meta-programming to minimize the code repetition.
I was trying to do this via define_method and wanted to end up in something like this:
vb_method :create_machine, :args => [:name, :os_type_id], :optional_args => [:settings_file, :groups, :flags]
But I can't find a way to pass arbitrary number of named (non-splat) arguments to define_method (I thought splat argument will make documenting the methods hard to impossible also will make the resulting API inconvenient).
What would be the best way to deal with this (using Ruby 2.0)?
UPD
Another way to do this is defining a method vb_method:
def vb_method(*vb_meths)
vb_meths.each do |meth|
define_method(meth) do |message={}|
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{meth}".to_sym
VirtualBoxAPI.send_request(#cl.conn, soap_method, #this.merge(message))
end
end
end
And then the class would have a call like this:
vb_method :create_machine, :register_machine
But is this case I will need to always call the methods with hash as an argument:
machine = vb.create_machine(name: 'my_vm', os_type_id: 'Windows95')
And that's exactly what I'm trying to avoid because I think in this case the resulting API can't be documented and is not convenient to use.
Stop trying to avoid option hashes. That's the "Ruby way" of doing things. They aren't impossible to document and several mainstream Ruby libraries use them this way (the first that come to mind are ActiveRecord and Mysql2).
Note that you can provide a default argument to the option hash, which serves as documentation and allows you to reduce code repetition.
Also, think about how your code would work if you could (somehow) pass an arbitrary number of named arguments to define_method. How would users remember which arguments are which? They would need to memorize the order and meaning of all the different positional arguments to all the different methods defined this way. When you have many similar methods with arguments of varying meanings, it's very difficult to keep everything straight. Keyword arguments (which is essentially what Ruby's option hashes are) were specifically created to avoid this situation.
If you're worried about error checking, define a helper method that checks the option hash for missing/unrecognized keys and raises an informative exception:
def validate_options(known, opts)
opts.each_key { |opt| raise "Unknown option: #{opt}" unless known.include?(opt) }
known.each { |opt, required| raise "Missing required option: #{opt}" if required and not opts.include?(opt) }
end
I was just reading a blog article and noticed that the author used tap in a snippet something like:
user = User.new.tap do |u|
u.username = "foobar"
u.save!
end
My question is what exactly is the benefit or advantage of using tap? Couldn't I just do:
user = User.new
user.username = "foobar"
user.save!
or better yet:
user = User.create! username: "foobar"
When readers encounter:
user = User.new
user.username = "foobar"
user.save!
they would have to follow all the three lines and then recognize that it is just creating an instance named user.
If it were:
user = User.new.tap do |u|
u.username = "foobar"
u.save!
end
then that would be immediately clear. A reader would not have to read what is inside the block to know that an instance user is created.
Another case to use tap is to make manipulation on object before returning it.
So instead of this:
def some_method
...
some_object.serialize
some_object
end
we can save extra line:
def some_method
...
some_object.tap{ |o| o.serialize }
end
In some situation this technique can save more then one line and make code more compact.
This can be useful with debugging a series of ActiveRecord chained scopes.
User
.active .tap { |users| puts "Users so far: #{users.size}" }
.non_admin .tap { |users| puts "Users so far: #{users.size}" }
.at_least_years_old(25) .tap { |users| puts "Users so far: #{users.size}" }
.residing_in('USA')
This makes it super easy to debug at any point in the chain without having to store anything in in a local variable nor requiring much altering of the original code.
And lastly, use it as a quick and unobtrusive way to debug without disrupting normal code execution:
def rockwell_retro_encabulate
provide_inverse_reactive_current
synchronize_cardinal_graham_meters
#result.tap(&method(:puts))
# Will debug `#result` just before returning it.
end
Using tap, as the blogger did, is simply a convenience method. It may have been overkill in your example, but in cases where you'd want to do a bunch of things with the user, tap can arguably provide a cleaner looking interface. So, perhaps it may be better in an example as follows:
user = User.new.tap do |u|
u.build_profile
u.process_credit_card
u.ship_out_item
u.send_email_confirmation
u.blahblahyougetmypoint
end
Using the above makes it easy to quickly see that all those methods are grouped together in that they all refer to the same object (the user in this example). The alternative would be:
user = User.new
user.build_profile
user.process_credit_card
user.ship_out_item
user.send_email_confirmation
user.blahblahyougetmypoint
Again, this is debatable - but the case can be made that the second version looks a little messier, and takes a little more human parsing to see that all the methods are being called on the same object.
If you wanted to return the user after setting the username you'd need to do
user = User.new
user.username = 'foobar'
user
With tap you could save that awkward return
User.new.tap do |user|
user.username = 'foobar'
end
It results in less-cluttered code as the scope of variable is limited only to the part where it is really needed. Also, the indentation within the block makes the code more readable by keeping relevant code together.
Description of tap says:
Yields self to the block, and then returns self. The primary purpose
of this method is to “tap into” a method chain, in order to perform
operations on intermediate results within the chain.
If we search rails source code for tap usage, we can find some interesting usages. Below are few items (not exhaustive list) that will give us few ideas on how to use them:
Append an element to an array based on certain conditions
%w(
annotations
...
routes
tmp
).tap { |arr|
arr << 'statistics' if Rake.application.current_scope.empty?
}.each do |task|
...
end
Initializing an array and returning it
[].tap do |msg|
msg << "EXPLAIN for: #{sql}"
...
msg << connection.explain(sql, bind)
end.join("\n")
As syntactic sugar to make code more readable - One can say, in below example, use of variables hash and server makes the intent of code clearer.
def select(*args, &block)
dup.tap { |hash| hash.select!(*args, &block) }
end
Initialize/invoke methods on newly created objects.
Rails::Server.new.tap do |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
end
Below is an example from test file
#pirate = Pirate.new.tap do |pirate|
pirate.catchphrase = "Don't call me!"
pirate.birds_attributes = [{:name => 'Bird1'},{:name => 'Bird2'}]
pirate.save!
end
To act on the result of a yield call without having to use a temporary variable.
yield.tap do |rendered_partial|
collection_cache.write(key, rendered_partial, cache_options)
end
Visualize your example within a function
def make_user(name)
user = User.new
user.username = name
user.save!
end
There is a big maintenance risk with that approach, basically the implicit return value.
In that code you do depend on save! returning the saved user. But if you use a different duck (or your current one evolves) you might get other stuff like a completion status report. Therefore changes to the duck might break the code, something that would not happen if you ensure the return value with a plain user or use tap.
I have seen accidents like this quite often, specially with functions where the return value is normally not used except for one dark buggy corner.
The implicit return value tends to be one of those things where newbies tend to break things adding new code after the last line without noticing the effect. They do not see what the above code really means:
def make_user(name)
user = User.new
user.username = name
return user.save! # notice something different now?
end
A variation on #sawa's answer:
As already noted, using tap helps figuring out the intent of your code (while not necessarily making it more compact).
The following two functions are equally long, but in the first one you have to read through the end to figure out why I initialized an empty Hash at the beginning.
def tapping1
# setting up a hash
h = {}
# working on it
h[:one] = 1
h[:two] = 2
# returning the hash
h
end
Here, on the other hand, you know right from the start that the hash being initialized will be the block's output (and, in this case, the function's return value).
def tapping2
# a hash will be returned at the end of this block;
# all work will occur inside
Hash.new.tap do |h|
h[:one] = 1
h[:two] = 2
end
end
It’s a helper for call chaining. It passes its object into the given block and, after the block finishes, returns the object:
an_object.tap do |o|
# do stuff with an_object, which is in o #
end ===> an_object
The benefit is that tap always returns the object it’s called on, even if the block returns some other result. Thus you can insert a tap block into the middle of an existing method pipeline without breaking the flow.
I would say that there is no advantage to using tap. The only potential benefit, as #sawa points out is, and I quote: "A reader would not have to read what is inside the block to know that an instance user is created." However, at that point the argument can be made that if you're doing non-simplistic record creation logic, your intent would be better communicated by extracting that logic into its own method.
I hold to the opinion that tap is an unnecessary burden on the readability of the code, and could be done without, or substituted with a better technique, like Extract Method.
While tap is a convenience method, it's also personal preference. Give tap a try. Then write some code without using tap, see if you like one way over another.
There is a tool called flog that measures how difficult it is to read a method. "The higher the score, the more pain the code is in."
def with_tap
user = User.new.tap do |u|
u.username = "foobar"
u.save!
end
end
def without_tap
user = User.new
user.username = "foobar"
user.save!
end
def using_create
user = User.create! username: "foobar"
end
and according on flog's result the method with tap is the most difficult to read (and I agree with it)
4.5: main#with_tap temp.rb:1-4
2.4: assignment
1.3: save!
1.3: new
1.1: branch
1.1: tap
3.1: main#without_tap temp.rb:8-11
2.2: assignment
1.1: new
1.1: save!
1.6: main#using_create temp.rb:14-16
1.1: assignment
1.1: create!
There could be number of uses and places where we may be able to use tap. So far I have only found following 2 uses of tap.
1) The primary purpose of this method is to tap into a method chain, in order to perform operations on intermediate results within the chain. i.e
(1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
tap { |x| puts "array: #{x.inspect}" }.
select { |x| x%2 == 0 }.
tap { |x| puts "evens: #{x.inspect}" }.
map { |x| x*x }.
tap { |x| puts "squares: #{x.inspect}" }
2) Did you ever find yourself calling a method on some object, and the return value not being what you wanted it to? Maybe you wanted to add an arbitrary value to a set of parameters stored in a hash. You update it with Hash.[], but you get back bar instead of the params hash, so you have to return it explicitly. i.e
def update_params(params)
params[:foo] = 'bar'
params
end
In order to overcome this situation here, tap method comes into play. Just call it on the object, then pass tap a block with the code that you wanted to run. The object will be yielded to the block, then be returned. i.e
def update_params(params)
params.tap {|p| p[:foo] = 'bar' }
end
There are dozens of other use cases, try finding them yourself :)
Source:
1) API Dock Object tap
2) five-ruby-methods-you-should-be-using
You're right: the use of tap in your example is kind of pointless and probably less clean than your alternatives.
As Rebitzele notes, tap is just a convenience method, often used to create a shorter reference to the current object.
One good use case for tap is for debugging: you can modify the object, print the current state, then continue modifying the object in the same block. See here for example: http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions.
I occasionally like to use tap inside methods to conditionally return early while returning the current object otherwise.
You can make your codes more modular using tap, and can achieve a better management of local variables. For example, in the following code, you don't need to assign a local variable to the newly created object, in the scope of the method. Note that the block variable, u, is scoped within the block. It is actually one of the beauties of ruby code.
def a_method
...
name = "foobar"
...
return User.new.tap do |u|
u.username = name
u.save!
end
end
In rails we can use tap to whitelist parameters explicitly:
def client_params
params.require(:client).permit(:name).tap do |whitelist|
whitelist[:name] = params[:client][:name]
end
end
I will give another example which I have used. I have a method user_params which returns the params needed to save for the user (this is a Rails project)
def user_params
params.require(:user).permit(
:first_name,
:last_name,
:email,
:address_attributes
)
end
You can see I dont return anything but ruby return the output of the last line.
Then, after sometime, I needed to add a new attribute conditionally. So, I changed it to something like this:
def user_params
u_params = params.require(:user).permit(
:first_name,
:last_name,
:email,
:address_attributes
)
u_params[:time_zone] = address_timezone if u_params[:address_attributes]
u_params
end
Here we can use tap to remove the local variable and remove the return:
def user_params
params.require(:user).permit(
:first_name,
:last_name,
:email,
:address_attributes
).tap do |u_params|
u_params[:time_zone] = address_timezone if u_params[:address_attributes]
end
end
In the world where functional programming pattern is becoming a best practice (https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming), you can see tap, as a map on a single value, indeed, to modify your data on a transformation chain.
transformed_array = array.map(&:first_transformation).map(&:second_transformation)
transformed_value = item.tap(&:first_transformation).tap(&:second_transformation)
No need to declare item multiple times here.
What is the difference?
The difference in terms of code readability is purely stylistic.
Code Walk through:
user = User.new.tap do |u|
u.username = "foobar"
u.save!
end
Key points:
Notice how the u variable is now used as block parameter?
After the block is done, the user variable should now point to a User ( with a username: ‘foobar’, and who is also saved).
It's just pleasant and easier to read.
API Documentation
Here’s an easy to read version of the source code:
class Object
def tap
yield self
self
end
end
For more info, see these links:
https://apidock.com/ruby/Object/tap
http://ruby-doc.org/core-2.2.3/Object.html#method-i-tap
Apart from the above answers, I have used tap in stubbing and mocking while writing RSpecs.
Scenario: When I have a complex query to stub and mock with multiple arguments which shouldn't go missed. The alternative here is to use receive_message_chain (but it lacks the details).
# Query
Product
.joins(:bill)
.where("products.availability = ?", 1)
.where("bills.status = ?", "paid")
.select("products.id", "bills.amount")
.first
# RSpecs
product_double = double('product')
expect(Product).to receive(:joins).with(:bill).and_return(product_double.tap do |product_scope|
expect(product_scope).to receive(:where).with("products.availability = ?", 1).and_return(product_scope)
expect(product_scope).to receive(:where).with("bills.status = ?", "paid").and_return(product_scope)
expect(product_scope).to receive(:select).with("products.id", "bills.amount").and_return(product_scope)
expect(product_scope).to receive(:first).and_return({ id: 1, amount: 100 })
end)
# Alternative way by using `receive_message_chain`
expect(Product).to receive_message_chain(:joins, :where, :where, :select).and_return({ id: 1, amount: 100 })
I was learning ruby, and i learnt that ruby constants must start with a Upper case letter (e.g. Myconstant). This will make it a constant, but its value is changeable!
If a constant's value is changeable then why do we need constant, what is the difference between variable then?
Constants have lexical scoping, whereas methods have dynamic scoping:
class Super
Constant = "Super::Constant"
def method
'Super#method'
end
def get_constant
Constant
end
def get_method
method
end
end
class Sub < Super
Constant = 'Sub::Constant'
def method
'Sub#method'
end
end
Super.new.get_constant # => "Super::Constant"
Sub.new.get_constant # => "Super::Constant"
Super.new.get_method # => "Super#method"
Sub.new.get_method # => "Sub#method"
And as far as variables, they are inaccessible from the outside. How would you intend to access these?
class Object
Constant = 'constant'
local_var = 'local var'
#instance_var = 'instance var'
##class_var = 'class var' # btw, never use these
end
Also, there's a lot of things you can do in Ruby, but for your own sanity, be wary. I'd recommend against changing constants around, it will likely frustrate your team.
Ruby lets you shoot yourself in the foot (if you really want to). But, at least in this case, it warns you about it.
ONE = 'one'
ONE = 'two' # !> already initialized constant ONE
Some reasons:
1) Convention. It's easy to see just from the name of an identifier that it's not supposed to change.
2) Technical. It (probably; someone more knowledgeable than I will probably answer) makes the interpreter simpler.
3) Dynamism is sometimes helpful; in testing, for example, it's possible to redefine things for testing purposes rather than having to stub/proxy everything…
I use this feature sometimes to test out code without otherwise necessary parameters, eg when i run the script from my editor where it is difficult to provide a parameter.
#ARGV[0] = "c:/test.txt" #in case of testing i remove the first remark sign
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