Is There Some Kind of Unseen Array Termination in Ruby

Is there some kind of unseen Array termination in Ruby?

The out-of range range selection is a special case, and works as per the docs:

http://www.ruby-doc.org/core/classes/Array.html#M002183

Though I'd agree that it's not exactly obvious.

ary[start, length]. out of boundary number giving [ ] output?

The semantics of [] are the same as for slice when two integers are provided. As explained in http://ruby-doc.org/core-2.0/Array.html#method-i-slice, when the first integer points to the end of the array, the empty array will be returned.

Ruby list an objects instance methods without it's getters and/or setters

The Ruby language has no notion of getters and setters for properties. attr_accessor :a_var is merely a convenient shorthand for creating the methods :a_var that returns the value, and :a_var= that set the value of the instance variable @a_var. The methods :a_var, and :a_var= are no different than any other method defined in the containing class.

So you have a need for a partial list of instance methods, that excludes those ending in =, and those that have an instance variable of the same name.

I think you have a reasonable method for implementing that behavior, though I don't think this should be implemented on Object.

Why does NSArray arrayWithObjects require a terminating nil?

It all has to do with the C calling ABI.

Consider these methods:

- (id)initWithFormat:(NSString *)format, ...;
+ (id)arrayWithObjects:(id)firstObj, ...;
+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;

The ... tells the compiler that a variable number of arguments of any type may be present. There is no way for the compiler to know what those types are required to be (the real definitions have markers that help with that).

Now, consider the three methods. All three have vastly different requirements for what might be present in the variable argument list. An array must be a bunch of objects followed by a nil. The dictionary requires a bunch of pairs of objects followed by a nil. Finally, the string method requires a bunch of arguments that match the types in the format string.

All of these behaviors are directly tied to the method being invoked and, if the author of an API decided to go for "hard to use", the behavior of decoding the variable arguments could be modified at runtime, just to make life difficult.

Bottom line: The C ABI doesn't have a syntax that allows for specifying that a method or function takes a variable number of arguments with any kind of set of constraints on the arguments or their termination.

Objective-C could change the rules just for method declarations & invocations, but that wouldn't help with C functions or C++, both of which Objective-C must remain compatible with.

What is recursion and how does it work?

A recursive function/method calls itself. For a recursive algorithm to terminate you need a base case (e.g. a condition where the function does not call itself recursively) and you also need to make sure that you get closer to that base case in each recursive call. Let's look at a very simple example:

def countdown(n)
return if n.zero? # base case
puts n
countdown(n-1) # getting closer to base case
end

countdown(5)
5
4
3
2
1

Some problems can be very elegantly expressed with recursion, e.g a lot of mathematical functions are described in a recursive way.

Cancel current/active query in Ruby on Rails

Try using pg_cancel_backend.

From the docs:

Cancel a backend's current query. You can execute this against another backend that has exactly the same role as the user calling the function. In all other cases, you must be a superuser.

ArgumentError: string contains null byte when writing Marshalled data into a file

The order of the file name and content argument is reversed. The first argument must be the name and the second one the content. The argument error is raised because file names shouldn't contain null bytes.

And since you're dealing with binary data, you should use IO.binwrite:

File.binwrite "users.txt", Marshal.dump(users)

Is this Ruby code using threads, thread pools, and concurrency correctly

Let us look at the problems you have described and try to solve these one at a time:

You have two pieces of code, SslClient and the script which uses this ssl client. From my understanding of the threadpool, the way you have used the threadpool needs to be changed a bit.

From:

pool = Concurrent::CachedThreadPool.new
pool.post do
[LARGE LIST OF URLS TO PING].each do |struct|
ssl_client = SslClient.new(struct.domain.gsub("*.", "www."), struct.scan_port)
cert_info = ssl_client.ping_for_certificate_info
struct.x509_cert = cert_info[:certificate]
struct.verify_result = cert_info[:verify_result]
end
end

pool.shutdown
pool.wait_for_termination

to:

pool = Concurrent::FixedThreadPool.new(10) 

[LARGE LIST OF URLS TO PING].each do | struct |
pool.post do
ssl_client = SslClient.new(struct.domain.gsub("*.", "www."), struct.scan_port)
cert_info = ssl_client.ping_for_certificate_info
struct.x509_cert = cert_info[:certificate]
struct.verify_result = cert_info[:verify_result]
end
end

pool.shutdown
pool.wait_form

In the initial version, there is only one unit of work that is posted to the pool. In the second version, we are posting as many units of work to the pool as there are items in LARGE LIST OF URLS TO PING.

To add a bit more about Concurrency vs Parallelism in Ruby, it is true that Ruby doesn't support true parallelism due to GIL (Global Interpreter Lock), but this only applies when we are actually doing any amount of work on the CPU. In case of a network request, CPU bound work duration is very negligible compared to the IO bound work, which means that your usecase is a very good candidate for using threads.

Also by using a threadpool, we can minimize the overhead of thread creation incurred by the CPU. When we use a threadpool, like in the case of Concurrent::FixedThreadPool.new(10), we are literally restricting the number of threads that are available in the pool, for an unbound threadpool, new threads are created for everytime when a unit of work is present, but rest of thre threads in the pool are busy.

In the first article, there was a need to collect the result returned by each individual workers and also to act meaningfully in case of an exception (I am the author). You should be able to use the class given in that blog without any change.

Lets try rewriting your code using Concurrent::Future since in your case too, we need the results.


thread_pool = Concurrent::FixedThreadPool.new(20)

executors = [LARGE LIST OF URLS TO PING].map do | struct |
Concurrent::Future.execute({ executor: thread_pool }) do
ssl_client = SslClient.new(struct.domain.gsub("*.", "www."), struct.scan_port)
cert_info = ssl_client.ping_for_certificate_info
struct.x509_cert = cert_info[:certificate]
struct.verify_result = cert_info[:verify_result]
struct
end
end

executors.map(&:value)

I hope this helps. In case of questions, please ask in comments, I shall modify this write up to answer those.

Dynamic RSpec spec generation

This doesn't work, because ... RSpec doesn't ... 'see' any specs at
compile-time ...

I was wondering why, and did some research. If you examine the following code and the output, you can draw some conclusions :

  • there is no compile time in Ruby
  • the body of a class/module is immediately evaluated and executed
  • so is the describe method
  • the body of a describe block is immediately processed by RSpec
  • RSpec stores before blocks and it blocks for later execution
  • when the parsing of a file is terminated, RSpec starts reporting the
    describe strings and executing the stored before/it example blocks

The following code demonstrates this.

module SO
puts '>>>>> Ruby sees module SO and executes/evaluates its body'
cases = [1,2,3]

describe "SO Cases" do
puts "in module SO, RSpec sees describe Cases self=#{self}"
before(:each) do
puts ' in before(:all)'
end

cases.each do |case_|
puts " in each loop with case_=#{case_}"
it "Case #{case_}" do
puts " check spec for case #{case_}"
end
end
end
end

module M # to avoid "warning: class variable access from toplevel"
puts '>>>>> Ruby sees module M and executes/evaluates its body'
describe "M Cases" do
puts "in module M, RSpec sees describe Cases self=#{self}, ancestors :"
ancestors.each {|a| puts " #{a}"}
print 'self.methods.grep(/^it/) : '; p self.methods.grep(/^it/).sort
before(:all) do
puts " in before(:all) self=#{self}"
@@cases = [1,2,3]
puts " ... now cases=#{@@cases}"
File.open('generated_cases.rb', 'w') do |fgen|
fgen.puts 'puts "\n*** inside generated_cases.rb ***"'
fgen.puts 'module GenSpecs'
fgen.puts "puts '>>>>> Ruby sees module GenSpecs and executes/evaluates its body'"
fgen.puts ' describe "GenSpecs Cases" do'
fgen.puts ' puts "in module GenSpecs, RSpec sees describe Cases"'
@@cases.each do |case_|
puts " in each loop with case_=#{case_}"
fgen.puts <<-IT_SPECS
it "Case #{case_}" do
puts " some spec for case_=#{case_}"
end
IT_SPECS
end
fgen.puts ' end'
fgen.puts 'end # module GenSpecs'
fgen.puts "puts '>>>>> end of ruby file generated_cases.rb <<<<<'"
end
puts 'file generated_cases.rb has been closed'
require_relative 'generated_cases'
end

it 'has loaded Cases' do
@@cases.should_not be_empty
end
end
end
puts '>>>>> end of ruby file t2_spec.rb <<<<<'

Execution :

$ ruby -v
ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-darwin12.2.0]
$ rspec --version
2.12.2
$ rspec --format nested t2_spec.rb
>>>>> Ruby sees module SO and executes/evaluates its body
in module SO, RSpec sees describe Cases self=#<Class:0x007fcaf49a6e80>
in each loop with case_=1
in each loop with case_=2
in each loop with case_=3
>>>>> Ruby sees module M and executes/evaluates its body
in module M, RSpec sees describe Cases self=#<Class:0x007fcaf2852e28>, ancestors :
#<Class:0x007fcaf2852e28>
RSpec::Core::ExampleGroup
...
self.methods.grep(/^it/) : [:it, :it_behaves_like, :it_should_behave_like, :its]
>>>>> end of ruby file t2_spec.rb <<<<<

SO Cases
in before(:all)
check spec for case 1
Case 1
in before(:all)
check spec for case 2
Case 2
in before(:all)
check spec for case 3
Case 3

M Cases
in before(:all) self=#<RSpec::Core::ExampleGroup::Nested_2:0x007fcaf2836ca0>
... now cases=[1, 2, 3]
in each loop with case_=1
in each loop with case_=2
in each loop with case_=3
file generated_cases.rb has been closed

*** inside generated_cases.rb ***
>>>>> Ruby sees module GenSpecs and executes/evaluates its body
in module GenSpecs, RSpec sees describe Cases
>>>>> end of ruby file generated_cases.rb <<<<<
has loaded Cases

GenSpecs Cases
some spec for case_=1
Case 1
some spec for case_=2
Case 2
some spec for case_=3
Case 3

Finished in 0.01699 seconds
7 examples, 0 failures

Creating a file and requiring it this way is for the demonstration and may not work in your case. I would recommend doing it in two phases : in the first you read the spreadsheet and create a file.rb with a describe and several it examples. In the second phase you launch Ruby to process the generated file.



Related Topics



Leave a reply



Submit