Hacker News new | ask | show | jobs
by radiospiel 1094 days ago
more correct would probably be

  threads = []
  3.times.map do 
    Thread.new do 
      service.call
    end 
  end
  threads.each(&:join)
But whether or not multithreading is really available within the test setup, and also whether or not the database adapter runs via different connections is something that one wanted to validate.
4 comments

Or this one?

  3.times.map do
   Thread.new do
     service.call
   end
  end.each(&:join)
I'm not really a fan of those & shortcuts.
> I'm not really a fan of those & shortcuts.

One of my favorite parts of ruby!

`collect.each(&:operation)` vs `collection.each { |thing| thing.operation }`

> &:operation

If one is unfamiliar, this syntax will implicitly call `Symbol#to_proc` on `:operation` and pass that as a block to the method (it will work with any object which responds to `#to_proc` and returns an object which responds to `#call`). These lines are all equivalent:

  my_array.map(&:operation)
  my_array.map { |my_element| my_element.operation }
  my_array.map { |my_element| :operation.to_proc.call(my_element) }
Given that, I adore the terseness in the first line, though I can understand a certain annoyance that the shorthand can cause if one doesn't know how this works.
I find it's best to just blindly accept it in Ruby, because you can really go down the rabbit hole otherwise. For example, the first example has even more syntactic fun going on because it looks like `map` accepts an argument but it doesn't:

    irb(main)> [1,2,3].map(1)
    (irb): in `map': wrong number of arguments (given 1, expected 0)
So you get clever and think.. well, it accepts a Proc, clearly, in the shape of &:operation. Let's use a Proc:

    irb(main)> [1,2,3].map(Proc.new { })
    (irb):in `map': wrong number of arguments (given 1, expected 0)
In the context of blocks, & is doing a little more than merely providing a Proc, but it's a handy way to think about it.
That's still a no-op because `threads` is empty

  threads = 3.times.map do 
    Thread.new do 
      service.call
    end 
  end
  threads.each(&:join)
That still wouldn't join any of the created threads though :)
In the case of rails, using multiple threads will checkout extra database connections.

Database connections are often a limited resource though, so it is not without peril.

Well yes. That's how a connection pool works. You're not really supposed to be creating extra threads inside a request. Things can get wonky unless you know what you're doing. Best to use ActiveJob, which will have its own context even if it uses threads underneath.