Identify unique blocks - ruby

I have an array to which I keep adding blocks of code at different points of time. When a particular event occurs, an iterator iterates through this array and yields the blocks one after the other.
Many of these blocks are the same and I want to avoid executing duplicate blocks.
This is sample code:
#after_event_hooks = []
def add_after_event_hook(&block)
#after_event_hooks << block
end
Something like #after_event_hooks.uniq or #after_event_hooks |= block don't work.
Is there a way to compare blocks or check their uniqueness?

The blocks can not be checked for uniqueness since that will mean to check whether they represent the same functions, something that is not possible and has been researched in computer science for a long time.
You can probably use a function similar to the discussed in "Ruby block to string instead of executing", which is a function that takes a block and returns a string representation of the code in the block, and compare the output of the strings you receive.
I am not sure if this is fast enough to be worthy to compare them, instead of executing them multiple times. This also has the downside you need to be sure the code is exactly the same, even one variable with different name will break it.

As #hakcho has said, it is not trivial to compare blocks. A simple solution might be having the API request for named hooks, so you can compare the names:
#after_event_hooks = {}
def add_after_event_hook(name, &block)
#after_event_hooks[name] = block
end
def after_event_hooks
#after_event_hooks.values
end

Maybe use something like this:
class AfterEvents
attr_reader :hooks
def initialize
#hooks = {}
end
def method_missing(hook_sym, &block)
#hooks[hook_sym] = block
end
end
Here is a sample:
events = AfterEvents.new
events.foo { puts "Event Foo" }
events.bar { puts "Event Bar" }
# test
process = {:first => [:foo], :sec => [:bar], :all => [:foo, :bar]}
process.each { |event_sym, event_codes|
puts "Processing event #{event_sym}"
event_codes.each { |code| events.hooks[code].call }
}
# results:
# Processing event first
# Event Foo
# Processing event sec
# Event Bar
# Processing event all
# Event Foo
# Event Bar

Related

How to pass a block

For the sake of simplicity, I've tried to abstract the problem down to its core elements. I've included a small piece of functionality wherein I use Socket to show that I want to pass the block further down into a method which is a black box for all intents and purposes. I'm also passing a constant True for the sake of showing I want to pass arguments as well as a yield block.
With all that being said, if I small have a hierarchy of calls as such:
def foo(use_local_source)
if use_local_source
Socket.unix("/var/run/my.sock") &yield
else
Socket.tcp("my.remote.com",1234) &yield
end
end
foo(True) { |socket|
name = socket.read
puts "Hi #{name}, I'm from foo."
}
How can I pass the implicitly declared block right down through foo and into Socket as if I were calling Socket.tcp(...) { ... } directly.
I know I could set it as an argument, but it doesn't feel idiomatic to Ruby. Is this also untrue and I should pass it as an argument? I've tried combinations of & and *, and I get a range of exception.
def foo(use_local_source)
if use_local_source
yield Socket.unix("/var/run/my.sock")
else
yield Socket.tcp("my.remote.com",1234)
end
end
From the docs for yield:
Yields control back to the context that resumed the fiber, passing along any arguments that were passed to it.

How do I transform a Ruby block and apply it as an argument to another block?

I'm reducing the verbosity on a lot of related specs with a small shortcut method I wrote:
def association_spec_for(kind, field)
it { expect(subject).to send(kind, field) }
end
This gets used like this:
describe Student do
association_spec_for :have_many, :courses
association_spec_for :have_one, :transcript
end
Now I'd like to expand the way association_spec_for works, so that I can do this while still leaving the original use cases intact:
association_spec_for(:foo, :bar) do |a|
a.baz(:blerp).bloop(:bleep => :blarg)
end
and have it turn into this:
it { expect(subject).to send(:foo, :bar).baz(:blerp).bloop(:bleep => :blarg) }
# |----------------------------------|
# This part came from the block
# that was passed to a_s_f.
What's the best way to make that happen?
def association_spec_for(kind, field, &pr)
it{expect(subject).to pr ? pr.call(send(kind, field)) : send(kind, field)}
end

advantage of tap method in ruby

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 })

How would you express an idiom "with this object, if it exists, do this" in Ruby?

Very often in Ruby (and Rails specifically) you have to check if something exists and then perform an action on it, for example:
if #objects.any?
puts "We have these objects:"
#objects.each { |o| puts "hello: #{o}"
end
This is as short as it gets and all is good, but what if you have #objects.some_association.something.hit_database.process instead of #objects? I would have to repeat it second time inside the if expression and what if I don't know the implementation details and the method calls are expensive?
The obvious choice is to create a variable and then test it and then process it, but then you have to come up with a variable name (ugh) and it will also hang around in memory until the end of the scope.
Why not something like this:
#objects.some_association.something.hit_database.process.with :any? do |objects|
puts "We have these objects:"
objects.each { ... }
end
How would you do this?
Note that there's no reason to check that an array has at least one element with any? if you're only going to send each, because sending each to an empty array is a no-op.
To answer your question, perhaps you are looking for https://github.com/raganwald/andand?
Indeed, using a variable pollutes the namespace, but still, I think if (var = value).predicate is is a pretty common idiom and usually is perfectly ok:
if (objects = #objects.some_association.hit_database).present?
puts "We have these objects: #{objects}"
end
Option 2: if you like to create your own abstractions in a declarative fashion, that's also possible using a block:
#objects.some_association.hit_database.as(:if => :present?) do |objects|
puts "We have these objects: #{objects}"
end
Writing Object#as(options = {}) is pretty straigthforward.
What about tap?
#objects.some_association.something.hit_database.process.tap do |objects|
if objects.any?
puts "We have these objects:"
objects.each { ... }
end
end
Edit: If you're using Ruby 1.9, the Object#tap method provides the same functionality as the code listed below.
It sounds like you just want to be able to save a reference to an object without polluting the scope, correct? How about we open up the Object class and add a method do, which will just yield itself to the block:
class Object
def do
yield self if block_given?
return self # allow chaining
end
end
We can then call, for example:
[1,2,3].do { |a| puts a.length if a.any? }
=> 3
[].do { |a| puts a.length if a.any? }
=> nil

What are those pipe symbols for in Ruby?

What are the pipe symbols for in Ruby?
I'm learning Ruby and RoR, coming from a PHP and Java background, but I keep coming across code like this:
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
What is the |format| part doing? What's the equivalent syntax of these pipe symbols in PHP/Java?
They are the variables yielded to the block.
def this_method_takes_a_block
yield(5)
end
this_method_takes_a_block do |num|
puts num
end
Which outputs "5". A more arcane example:
def this_silly_method_too(num)
yield(num + 5)
end
this_silly_method_too(3) do |wtf|
puts wtf + 1
end
The output is "9".
This was very strange to me too at first, but I hope this explanation/walkthru helps you.
The documentation touches the subject, in a quite good way - if my answer doesn't help I am sure their guide will.
First, fire up the Interactive Ruby interpreter by typing irb in your shell and hitting Enter.
Type something like:
the_numbers = ['ett','tva','tre','fyra','fem'] # congratulations! You now know how to count to five in Swedish.
just so that we have an array to play with. Then we create the loop:
the_numbers.each do |linustorvalds|
puts linustorvalds
end
It will output all the numbers, separated by newlines.
In other languages you'd have to write something like:
for (i = 0; i < the_numbers.length; i++) {
linustorvalds = the_numbers[i]
print linustorvalds;
}
The important things to note are that the |thing_inside_the_pipes| can be anything, as long as you are using it consistently. And understand that it is loops we are talking about, that was a thing I didn't get until later on.
#names.each do |name|
puts "Hello #{name}!"
end
at http://www.ruby-lang.org/en/documentation/quickstart/4/ is accompanied by this explanation:
each is a method that accepts a block of code then runs that block of code for every element in a list, and the bit between do and end is just such a block. A block is like an anonymous function or lambda. The variable between pipe characters is the parameter for this block.
What happens here is that for every entry in a list, name is bound to that list element, and then the expression puts "Hello #{name}!" is run with that name.
The code from the do to the end defines a Ruby block. The word format is a parameter to the block. The block is passed along with the method call, and the called method can yield values to the block.
See any text on Ruby for details, this is a core feature of Ruby that you will see all the time.
The equivalent in Java would be something like
// Prior definitions
interface RespondToHandler
{
public void doFormatting(FormatThingummy format);
}
void respondTo(RespondToHandler)
{
// ...
}
// Equivalent of your quoted code
respondTo(new RespondToHandler(){
public void doFormatting(FormatThingummy format)
{
format.html();
format.xml();
}
});
Parameters for a block sit between the | symbols.
To make it even more clearer, if needed:
the pipe bars essentially make a new variable to hold the value generated from the method call prior. Something akin to:
Original definition of your method:
def example_method_a(argumentPassedIn)
yield(argumentPassedIn + 200)
end
How It's used:
example_method_a(100) do |newVariable|
puts newVariable;
end
It's almost the same as writing this:
newVariable = example_method_a(100)
puts newVariable
where, newVariable = 200 + 100 = 300 :D!

Resources