Iterator.each: why is this working - ruby

I was refactoring a bit of code in a project for work when I came across an odd bit of syntax. I confirmed it has been in the file since it was first created and the bit of code is being called.
worksheet.each 1 do |row|
Dashboard::LocalizedMessagingField.create({blah blah blah})
end
When I run something like the following in irb it complains about 1 for 0 parameters on each.
[1,2,3].each 1 do |i|
puts i
end
Why does it work in the RoR application? Anyone ever see something like this before?

I found the answer after a bit of digging. We have the Spreadsheet gem installed and it provides an each method that takes a parameter to skip the first n rows of a spreadsheet.
def each skip=dimensions[0], &block
skip.upto(dimensions[1] - 1) do |idx|
block.call row(idx)
end
end

Related

What is this Rspec syntax exactly asking for?

TL;DR I am going to a bootcamp next year and one their assessments to get in is learning ruby. I have a background in JS and am very new to ruby. I have this assessment in which case I am not familiar with what the test wants me to do. Below is the test case(Rspec) and right below that is my answer.
describe "some silly block functions" do
describe "reverser" do
it "reverses the string returned by the default block" do
result = reverser do
"hello"
end
expect(result).to eq("olleh")
end
it "reverses each word in the string returned by the default block" do
result = reverser do
"hello dolly"
end
expect(result).to eq("olleh yllod")
end
end
This is my answer code:
def reverser sentence
words = sentence.split(" ")
result = []
words.length.times do |i|
result.push(yield(words[i]))
end
result.join(" ")
end
reverser("hello dolly") {|n| n.reverse} #=> 'olleh yllod'
As I mentioned above I am new to ruby and the idea of yielding is like a callback function for JS. I am having a hard time figuring out what expected code the test case wants me to write. It says that 'it reverses each word in the string returned by the default block' from the statement I just created a block outside of the function where the words are being reversed. I appreciate the help and guidance from whoever can give advice.
This is really more about TDD than about Ruby. The approach would be much the same in any other language as well.
The point of TDD is to write the simplest test that could possibly fail, and then write the simplest code that could possibly change the error message. Step #1 is already provided to you in this example, so this is really about step #2: write the simplest code that could possibly change the message.
Let's run the tests! The message says:
NoMethodError:
undefined method `reverser' …
What's the simplest code that could possibly change a message that says a method doesn't exist? Well, make the method exist, of course!
def reverser; end
Now, the message is:
expected: "olleh"
got: nil
Okay, so it expected us to return the string 'olleh', but we actually returned nil. That's easy:
def reverser; 'olleh' end
Great! The first test passes. But the second still fails. It says:
expected: "olleh yllod"
got: "olleh"
Hmm … apparently, it is not enough to just return something statically. We have to return something different every time. The obvious source would be an argument, but our method doesn't have any parameters. Or does it? Yes! In Ruby, all methods have an implicit block parameter! You can evaluate it using the yield keyword, so let's try that:
def reverser; yield end
Damn! We're back to two errors! That was a step backwards. Or was it? Let's look at the first error message:
expected: "olleh"
got: "hello"
Do you notice something? The expected value is exactly the reverse of the value we are currently returning. So, all we need to do is reverse the return value:
def reverser; yield.reverse end
Hooray! We're back to 1 error:
expected: "olleh yllod"
got: "yllod olleh"
Again, can you spot what is happening? The order of the words is reversed! We need to separate the words and then reverse them, then put them back together:
def reverser; yield.reverse.split.reverse.join end
So close!
expected: "olleh yllod"
got: "ollehyllod"
We just need to put the space back in:
def reverser; yield.reverse.split.reverse.join(' ') end
Yippieh!
2 examples, 0 failures
The important thing is: at no point did we actually have to think. Every step of the way, the tests told us what to do, what to do next, and when we were done. That's what TDD is about: the tests drive the development.
I think the point of the question should be to explain about RSpec and TDD if you're going on a bootcamp. I think giving you the answer to the problem is only part of what you need to know in this case. So...
One of the principles of TDD is to write the least amount of code to get the tests to pass. If I go back to the start.
You have written a reverser method that takes sentence as an argument:
def reverser sentence
'olleh'
end
Run the test and the test should fail with an error: wrong number of arguments. Remove the argument and try that and run RSpec again:
def reverser
'olleh'
end
The first test should pass, but it will fail the second test as we've hard coded the return value of olleh. Clearly it's no good returning a hard coded value — it just helped the test to pass — so I need to figure out how to yield a return value.
def reverser
yield.reverse
end
And this perhaps will get the second test to pass...
This is the guiding principle of TDD, take small steps and get your code to pass. Once it's passing then go back and refactor and improve your code.
As you probably know already TDD is invaluable for writing good quality code - it makes writing code fun, it helps with refactoring.
I found a page with some resources and I would recommend codeschool but they've retired their course which is a pity but there is a PluralSight TDD course that might be useful and also there is a Udemy course on TDD that might be useful too in giving you a head start.
yield means "execute the code inside the block and give me the result". Your reverser method can be simply written like this:
def reverser
yield.split.map(&:reverse).join(' ') if block_given?
end
result = reverser do
'hello world'
end
puts result
# => olleh dlrow
Ruby automatically returns the last thing called as the return value, so the return value of the block given to reverser is hello world which is what will be assigned to yield.
You could check the documentation for block_given? here. Take a look at this answer for deeper explanation of blocks

basic undefined method for #<RSpec::ExampleGroups:::0x00000101906440>

I started and to code back in 2013 and took a break from it and decided to start from scratch. But for the life of me cannot get pass this error. I've done everything I can think of, but it's not requiring the methods from the lib file.
here is my folder structure
fizzbuzz
lib/
fizzbuzz.rb
spec/
fizzbuzz_spec.rb
spec_helper.rb
.rspec
fizzbuzz_spec.rb file
require "fizzbuzz"
describe "fizzbuzz" do
it "tells me that 3 is divisible by 3" do
expect(divisible_by_three?(3)).to_eq true
end
end
Heres the fizzbuzz.rb file
def fizzbuzz
def divisible_by_three? (number)
number % 3 ==0
end
end
Yes I understand it's not the most puzzling thing in the world. But my mind s a blank and I've troubledshoot this and searched online and followed tutorials to do it another way, but it never seems to call the method.
I've used
require "fizzbuzz"
require './lib/fizzbuzz'
require_relative '../lib/fizzbuzz'
Please help, please and thank yous.
Kind regards,
Grateful developer.
There are 2 problems here as I see it. In the lib/fizzbuzz.rb file, your method divisible_by_three? method is enclosed in another method. While this is technically allowed, it's not really advisable if it can be avoided. Instead, change def fizzbuzz to class Fizzbuzz.
class Fizzbuzz
def divisible_by_three? (number)
number % 3 ==0
end
end
In the spec file, require_relative '../lib/fizzbuzz' is fine. However, to use the method (at least as defined in the previous snippet), you'll need to use an instance of the class to have access to the method. See the snippet below.
require_relative '../lib/fizzbuzz'
describe "fizzbuzz" do
let(:instance) { Fizzbuzz.new }
it "tells me that 3 is divisible by 3" do
expect(instance.divisible_by_three?(3)).to eq true
end
end

Ruby - Running an iteration by calling require 'filename'

I had a thought and so far the thought has failed so I wanted to share it and have it corrected.
I have a series of Ruby scripts written to walk through a ecommerce site from adding to cart to checking out. The scripts are all referencing each other in order to keep the chain moving along. What I want to do is make a Ruby file called Run_CheckOut.rb but be able to run through several iterations of the checkout by invoking this file x amount of times.
Here was my first try:
i = 0
10.times do
i+= 1
puts "Iteration number: " + i.to_s
require 'Test_OrderService_SubmitCart'
end
When I do this it will only call the required file once but continues to count for i. How can I call the required file 10 times or am I completely off base with this?
am I completely off base with this?
Yes.
What I want to do is make a Ruby file called Run_CheckOut.rb but be able to run through several iterations of the checkout by invoking this file x amount of times.
The point of require is to make code available to your execution environment. require only pulls in the code once -- calling it again has no effect. load will run the included script each time, but that is a poor design choice.
What you want is to invoke something in the source code file. Perhaps you'd like to call a method, or create an object from a class. Define a method:
def do_something
# blah blah
end
require the file at the top of your script:
require 'Test_OrderService_SubmitCart'
and invoke the method in the loop:
i = 0
10.times do
i+= 1
puts "Iteration number: " + i.to_s
do_something
end
You are looking for load (note that you need to append .rb):
load 'Test_OrderService_SubmitCart.rb'
Contrary to load, require executes a source file only once. See the detailed description of what require does in the reference documentation.
Also there is a ruby convention for naming files and methods - lowercased and underscored.
Class and Module names are camel cased. These two conventions are never mixed.
Your final code should look something more like:
require 'order_service'
10.times do |n|
puts "iteration #{n}"
submit_cart
end
Notice the beauty.
Good luck!

Does IronRuby have an issue with each_for_index?

I'm working on some stuff in IronRuby, but I've run into a bit of a snag. This chunk of code:
def func
b = #b
b.each_with_index do |element, index|
<some stuff in here>
end
end
gives the following error:
./myfile.rb:<line number>:in 'func': wrong number of arguments (0 for 1) (ArgumentError)
from IronRuby.Libraries:0:in '<EachWithIndex>b__9'
from IronRuby.Libraries:0:in 'each'
from IronRuby.Libraries:0:in 'Each'
from ./myfile.rb:<line number>:in 'each_with_index'
from ./myfile.rb:<line number>:in 'func'
Am I doing anything wrong here? I'm using IronRuby 1.0 (the .NET 2.0 version). It's probably something ridiculously obvious, but I just haven't been able to find the answer.
As a note: I've thrown a bunch of puts statements in there, and b is definitely an Array, so it's not like I'm trying to do this on something it shouldn't work on.
Ah, I figured it out, IronRuby targets Ruby 1.8.6, and apparently each_for_index didn't return an enumerator in 1.8.6. I've changed it to:
require 'enumerator'
b.enum_for(:each_with_index) do |element, index|
and it seems to work fine.

Where does 'color_puts' come from?

I can't find where the color_puts would come from in the mod_passenger installer... any ideas?
Looked up myself just what you meant, since it's more fun than working.
Check the require statements at the top of the file - you'll see that there are only 3 possible sources, given that color_puts is not a Ruby standard.
Turns out, it's in abstract_installer.rb.
def color_print(text)
STDOUT.write(ConsoleTextTemplate.new(:text => text).result)
STDOUT.flush
end
def color_puts(text)
color_print("#{text}\n")
end

Resources