blocks in silly blocks rspec testing - ruby-on-rails

I had the following tests given to me as an exercise:
require "silly_blocks"
describe "some silly block functions" do
describe "reverser" do
it "reverses the string returned by the default block" do
result = reverser do
"hello"
end
result.should == "olleh"
end
it "reverses each word in the string returned by the default block" do
result = reverser do
"hello dolly"
end
result.should == "olleh yllod"
end
end
describe "adder" do
it "adds one to the value returned by the default block" do
adder do
5
end.should == 6
end
it "adds 3 to the value returned by the default block" do
adder(3) do
5
end.should == 8
end
end
describe "repeater" do
it "executes the default block" do
block_was_executed = false
repeater do
block_was_executed = true
end
block_was_executed.should == true
end
it "executes the default block 3 times" do
n = 0
repeater(3) do
n += 1
end
n.should == 3
end
it "executes the default block 10 times" do
n = 0
repeater(10) do
n += 1
end
n.should == 10
end
end
end
I was able to solve them with the following code:
def reverser
k = []
x = yield.split(" ")
x.each do |y|
n = y.reverse
k.push(n)
end
m = k.join(" ")
m
end
def adder(num=1, &block)
block.call + num
end
def repeater(num=1, &block)
for i in (1..num) do
block.call
end
end
However I some of these concepts I do not understand all that well. For example:
What exactly does the & symbol in the &block parameter mean?
Similarly what is block.call and where is the actual block object I am assuming its calling?
Could I theoretically use another method on block if I wanted to achieve something else?
Also where can I learn a bit more about blocks
This exercise was a bit above my current knowledge.

It means "this is the block parameter". You are not bound to calling it &block, so there needs to be a way to separate it from the other arguments. The same notation is used to pass arguments to a function as block as opposed to normal arguments (see below)
block.call is exactly the same thing as yield. The difference is that you can use block to access the block itself without calling it immediately. For example, you could store the block for later execution. This is a common pattern known as lazy evaluation.
Yes, you can also pass different things than a do/end block as the &block parameter. See below for some examples.
#UriAgassi gave you an excellent link.
Here are some other things you can pass as block argument. First, just a simple method that takes a block for demonstration:
def reverser(&block)
block.call.reverse
end
You can now pass a standard block
reverser do
"hello"
end
#=> "olleh"
Or, in alternative block syntax, used for inline style
reverser { "hello" }
#=> olleh
You can also pass a lambda or proc, which is similar to a block.
By using the &block notation you can pass a variable as block argument:
my_block = lambda { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"
Or, in alternative lambda syntax
my_block = -> { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"
You can even take an existing method and pass it as block argument
here you can see the great advantage of blocks: They are evaluated
when block.call is executed, not when the code is loaded. Here this
means that the string will change every time accordingly.
def foobar
"foobar at #{Time.now}"
end
reverser(&method(:foobar))
#=> "0020+ 15:42:90 02-50-4102 ta raboof"
#=> "0020+ 31:52:90 02-50-4102 ta raboof"
You can do cool stuff with this, for example:
[1, 2, 3].each(&method(:puts))
1
2
3
#=> [1, 2, 3]
But remember not to overdo it, Ruby is all about expressive and readable code. Use these techniques when they enhance your code, but use simpler ways if possible.
Finally, here is also an example of lazy evaluation:
class LazyReverser
def initialize(&block)
#block = block
end
def reverse
#block.call.reverse
end
end
reverser = LazyReverser.new do
# some very expensive computation going on here,
# maybe we do not even need it, so lets use the
# lazy reverser!
"hello dolly"
end
# now go and do some other stuff
# it is not until later in the program, that we can decide
# whether or not we even need to call the block at all
if some_condition
reverser.reverse
#=> "yllod olleh"
else
# we did not need the result, so we saved ourselves
# the expensive computation in the block altogether!
end

Related

Ruby Yield in Rails Controllers variable

I am trying to understand the following method of a rails controller
def self.collect_with_max_id(collection=[], max_id=nil, &block)
response = yield(max_id)
collection += response
response.empty? ? collection.flatten : collect_with_max_id(collection, response.last.id - 1, &block)
end
When trying to debug the method with byebug I get values for all the objects collection and max_id:
I am stuck on this part
response = yield(max_id)
while there is a max_id of 552860227390144512, when calling the response variable I simply get an empty array [] and it seems to break the whole method.
Could someone explanin the yield function in this context. I only now it from rendering views and blocks in ror.
yield is a keyword in ruby and it is used to execute the block given to the method.
def foo
yield 'Hi 1'
yield 'Hi 2'
end
foo { |string| puts string }
# Hi 1
# Hi 2
In your case the block is also taken in a variable &block so you can do a recursion:
def bar(i = 1, &block)
return if i <= 0
yield(i) # or you can do block.call(i)
bar(i - 1, &block)
end
bar(3) { |i| puts "I am called with #{i}" }
The method stops the recursion because of the last line. You ask whether the response.empty? and if it is you'll return collection.flatten
The tl&dr is forget about rails for couple of months and learn the ruby language otherwise you'll be in a world of hurt.

yield to an anonymous block two functions up

there is probably a simple way to do this.
I'm trying to refactor something like the following
def foo(baz)
baz.update_first
if baz.has_condition?
yield baz.val if block_given?
baz.a
else
baz.b
end
end
called like
foo(baz) {|b| b.modify}
to something like
def foo(baz)
baz.update_first
bar(baz) {|i| yield i if block_given? }
end
def bar(baz)
if baz.has_condition?
yield baz.val if block_given?
baz.a
else
baz.b
end
end
Will that work? How?
I think it will, but I'd appreciate a clear explanation of how yielding inside a block works... reading through proc.c and vm.c and a relevant git commit in the ruby source code , I think when bar is called in foo it executes until it yields, and then you walk up the frame stack to the local environment pointer for block defined in foo, which is called, where the yield walks up to the block foo is called with, executes it, and then you are back in bar. Is that correct? Is there a better way to do this?
This feels a little weird to me, like inverting control, and it requires foo to know about baz more then I'd like, but I unfortunately can't simply pass a proc or lambda in this code.
I think maybe the concept of yield will be more clear if you look at an alternative syntax, which is converting the bloc to a proc argument.
For example, the following examples are the same
def my_each(arr)
arr.each { |x| yield x }
end
def my_each(arr, &blk)
arr.each { |x| blk.call(x) }
end
# Both are called the same way
my_each([1,2,3]) { |x| print x }
# => 123
When using yield, the variable is available in the method without declaring it in the parameters list. Prepending an & sign to a parameter converts it to a proc, so in the method it can be run with .call.
Here's an example of providing a block to one method then executing it two scopes in:
def method_a(number, &blk)
method_b do
method_c do
blk.call(number)
end
end
end
def method_b(&blk)
blk.call
end
def method_c(&blk)
blk.call
end
method_a(1) { |num| puts num + 1 }
# => 2
Note that blk is not a magic word - you can name the variable whatever you want.
Here's the same thing with yield:
def method_a(number)
method_b do
method_c do
yield number
end
end
end
def method_b
yield
end
def method_c
yield
end
method_a(1) { |num| puts num + 1 }
# => 2
I think using the &blk syntax is clearer because it assigns a variable to the proc. Just because a proc is used in the method doesn't mean you have to ever run Proc.new. The block is automatically converted to a proc.

How can you detect when "break" is called in the callers Proc?

I'm writing a library that iterates over a set and calls the caller's proc for every item in the set. Example:
def self.each(&block)
# ... load some data into results_array
results_array.each do |result|
status = block.call(result)
# how do I know to call break if the user calls break?
break if status == false
end
end
Currently, as you can see in my code, I inspect the "last expression evaluated" in order to break. This seems bug-prone as the end-user may have a perfectly valid reason for their last expression evaluating to false. The more appropriate thing would be to detect the caller using "break".
How do I know to call break if the user calls break?
If you use yield instead of block.call, you can use the difference in behavior between next and break. As an example:
def each(&block)
puts "before"
result = yield
puts "after"
result
end
each do
puts "hello"
next
end
# Result:
# before
# hello
# after
each do
puts "hello"
break
end
# Result:
# before
# hello
As you can see, when you use next inside a block, the control is given back to the function calling the block. If you use break however, the calling function will return immediately with nil as a return value. You could now exploit this behavior with some trick:
def each(&block)
# ...
results_array.each do |result|
block_result = yielder(result, &block) || {:status => :break, :value => nil}
if block_result[:status] == :break
# block has called break
#...
else
# block has called either next or the block has finished normally
#...
end
end
end
def yielder(*args, &block)
value = yield *args
{:status => :normal, :value => value}
end
This works because here, the yielder function returns either nil in case the block called break or a hash with a status and the return value of the block. You can thus differentiate between a valid result (which is always different from nil) and an exceptional result which is always nil.
This should work, unless I don't understand what you are trying to do:
def each(&block)
# ... load some data into results_array
results_array= [1, 2, 3]
results_array.each do |result|
block.call(result)
end
end
each do |result|
puts result
break
end

How to define a method some how like the 'yield' ( I mean, automatically catch the block)?

If I need to define a method called 'yields' which will call yiled 3 times:
def yields
3.times do
yield
end
end
And then I will use it in an other method:
def call_me_3_times
yields
end
In the console or irb:
>> call_me_3_times { puts 'me'} # => Cause error
=> LocalJumpError: no block given (yield)
from (irb):32:in `yields'
from (irb):35:in `call_me_3_times'
I hope you can read what I want;
And how to make the 'yields' autolly capture the block given?
I mean that when we use the 'yields',we don't need to pass it a '&block', just like the usage of 'yield'(we don't have to even mustn't pass the '&block' to 'yield', need we?).
Something like:
def call_me_3_times &block
yields &block
end
I tried to look at yield implementation to see if we could reproduce its behaviour, but I think it is a keyword, so there's no way to look at the implementation.
I tried with block_given, and looking at the implementation from the ruby core rdocs, I found that block_given? is implemented this way :
rb_f_block_given_p()
{
if (ruby_frame->prev && ruby_frame->prev->iter == ITER_CUR && ruby_block)
return Qtrue;
return Qfalse;
}
As you see, it's C, so it's too low-level implementation. We can't do the same.
If block_given? methods needs to rely on C implementation to just check that a block is given, I can't see how we could get that block and call it within ruby code.
So I think there's no way to do what you want.
You need given a block to you yields method or avoid yield if no block
no yield if no block :
def yields
3.times do
yield if block_given?
end
end
Pass a block to your yields methods
def call_me_3_times
yields { puts 'hello' }
end
A solution to this can be created using the techniques described in this blog post http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
def call_me_three_times
yields &(Proc.new) if block_given?
end
When you define a method as def some_method(&block) ruby will expect you to pass a block to the method. It will convert that block to a Proc and store it in the block variable.
If you prefix a Proc object with an & it will convert it to a block.
If you call Proc.new within a method and do not provide it with a block then it will create a Proc from the block passed to it.
Some test results are below
def yields
puts "Tripling"
3.times do
yield
end
end
def call_me_three_times
yields &(Proc.new) if block_given?
end
x="Foo"
call_me_three_times { puts x }
x="Bar"
call_me_three_times { puts x }
call_me_three_times
Output
Tripling
Foo
Foo
Foo
Tripling
Bar
Bar
Bar

Explain Iterator Syntax on Ruby on Rails

I started learning Ruby on Rails and found myself confounded by the syntax, so I had to read about somet of the Ruby syntax. I learned the syntax from http://www.cs.auckland.ac.nz/references/ruby/doc_bundle/Manual/man-1.4/syntax.html:
method_call do [`|' expr...`|'] expr...end
They call it an Iterator. I understand an iterator runs through a loop, but I don't understand how exactly I'm supposed to read this or what's going on in in this syntax. I see it all the time in RoR screencasts and the words make sense, but I actually have no idea what's going on. Could anyone explain this to me?
edit: example
respond_to do |format|
format.json
format.xml { render :xml => #posts }
end
Methods can take a construct called "Blocks". These are anonymous methods that get passed into the method.
Another syntax for this is:
method_call { |var| do_something(var) }
Basically, you are saying that for each item in an iteration, name it "var" and do something with that item. The method simply calls your block that you passed in as it "yields" items to it.
Does this help?
edit: In your example, you they are using the iterator pattern in a funny way... probably only passing one format object into your block, so you can then tell it which formats to handle, and what to do when you see it.
In other words, they are using the pattern to create a DSL of sorts that lets you configure what you respond to.
In the case of iterators, think of them like an interface in Java: you can do a for-loop in Ruby, but all the objects that you might want to iterate over (should) implement the 'each' method which takes a block (i.e. a closure, an anonymous function).
Blocks are used all over the place in Ruby. Imagine you have this array:
[1, 2, 3, 4, 5, 6].each do |i| puts i.to_s end
Here, you are creating the array and then you are calling the 'each' method on it. You pass the block to it. You could separate this out, like this:
arr = [1, 2, 3, 4, 5, 6]
string_printer = lambda do |i| puts i.to_s end
arr.each(&string_printer)
This kind of interface is implemented in other things: the Hash collection lets you iterate over the key-value pairs:
{:name => "Tom", :gender => :male}.each do |key, value| puts key end
The do..end can be replaced with braces, like this:
[1, 2, 3, 4, 5, 6].each {|i| puts i.to_s }
This kind of iteration is made possible because of the functional-programming that Ruby employs: if you are creating a class that needs to iterate over something, you can also implement the each method. Consider:
class AddressBook
attr_accessor :addresses
def each(&block)
#addresses.each {|i| yield i }
end
end
All sorts of classes implement interesting functionality through this block pattern: look at String's each_line and each_byte method, for instance.
method_call do [`|' expr...`|'] expr...end
Is not limited to iteration functions.
In ruby, any method can take a block as an argument. The block can then be called by the method. In the case of an iterator, the method looks something like this:
def iter
for i in [:x,:y,:z]
yield i
end
end
If you call iter with a block, it will loop over [:x, :y, :z] and yield each of them to the block, which can then do whatever you want. e.g. to print them out:
iter { |z| puts z }
You can also use this to hide init and cleanup steps, like opening and closing files. e.g. File.open. File.open, if it were implemented in pure ruby(it's in C for performance) would do something like this.
def File.open filename, opts
f = File.new filename, opts
yield f
f.close
end
Which is why you can use
File.open 'foobar', 'w' do |f|
f.write 'awesome'
end
respond_to is similar. It works something like this:( check out the real implementation here)
def respond_to
responder = Responder.new(self)
block.call(responder)
responder.respond
end
It creates a responder object that has methods like html that take a block and passes it to you. This turns out to be really handy, because it lets you do things like:
def action
#foo = Foo.new params[:foo]
respond_to do |format|
if #foo.save
format.html { redirect_to foo_path #foo }
format.xml { render :xml => #foo.to_xml }
else
flash[:error] = "Foo could not be saved!"
format.html { render :new }
format.xml { render :xml => {:errors => #foo.errors }.to_xml}
end
end
end
See how I change the behavior dependent on save inside the block? Doing this would be much more annoying without it.
<function> do |<temp variable>|
<code to operate on temp variable>
end
This creates a temporary anonymous function which accepts an item into a temporary variable, and then lets things operate on that item. The anonymous function is passed in to the original <function> specified to operate on the items yielded by that function.
What you see there is a block of code, the syntax is a bit awkward when you first see it.
So, basically, with iterators your have a "thing" that may be repeated, and it receives a block to know what to do.
For instance the Range class has a method called "each" which receives the block of code to execute on each element in the range.
Let's say you want to print it:
range = 1..10 #range literal
range.each {|i|
puts i
}
The code: {|i| puts i} is a block that says what to do when this range iterates over each one of its elements. The alternate syntax is the one you posted:
range.each do |i|
puts i
end
These blocks are used with iterators, but they are not limited to "iteration" code, you can use them in other scenarios, for instance:
class Person
def initialize( with_name )
#name = with_name
end
# executes a block
def greet
yield #name #passes private attribute name to the block
end
end
p = Person.new "Oscar"
p.greet { |n|
puts "Name length = #{n.length}"
puts "Hello, #{n}"
}
Prints:
Name length = 5
Hello, Oscar
So, instead of having a greet method with a fixed behavior, using block let the developer specify what to do, which is very helpful with iterators, but as you have just witness not the only place. In your case, that block is letting you specify what to do in the respond_to method.
The documentation you are reading is ancient -- practically prehistoric. If it were possible for web pages to gather dust, that one would have a thick layer.
Try the reference material at the ruby-lang website. Also, the Programming Ruby (pickaxe) book is an essential reference.
I think you could call it iterator, because often, the block function is called more than once. As in:
5.times do |i|
puts "#{i} "
end
"Behind the scenes", the following steps are made:
The method times of the object instance 5 is called, passing the code puts "#{i} " in a Proc object instance.
Inside the times method, this code is called inside a loop, passing the current index as a parameter. That's what times could look like (it's in C, actually):
class Fixnum
def times_2(&block) # Specifying &block as a parameter is optional
return self unless block_given?
i = 0
while(i < self) do
yield i # Here the proc instance "block" is called
i += 1
end
return self
end
end
Note that the scope (i.e. local variables etc.) is copied into the block function:
x = ' '
5.times do { |i| puts "#{i}" + x }

Resources