“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it. Currently working for InPay...”

Rob Lacey
Senior Software Engineer, UK

Adding helpers for RSpec memoization

I thought initially it would be incredibly easy to add a wrapper method alongside existing let, let!, subject memoized helper methods in RSpec.

def current_user(&block)
    u = yield
    allow(User).to receive(:current_user).and_return(u)
  end

  describe 'stuff' do
    let(:artist) { Fabricate(:artist) }
    current_user { artist.user }
  end

But I kept getting. `artist` is not available on an example group when the current user block was yielded. I had to dig into RSpec::Core to find how let is defined and came up with and ensure that artist and current_user were in the same scope when calling one another.

module CurrentUserHelpers
  extend ActiveSupport::Concern

  module ClassMethods
    def current_user(&block)
      raise "#current_usercalled without a block" if block.nil?
      RSpec::Core::MemoizedHelpers.module_for(self).__send__(:define_method, :current_user, &block)

      # Apply the memoization. The method has been defined in an ancestor
      # module so we can use `super` here to get the value.
      define_method(:current_user) do
        u = __memoized.fetch_or_store(:current_user) do
          block.arity == 1 ? super(RSpec.current_example, &nil) : super(&nil)
        end
        allow(User).to receive(:current_user).and_return(u)
        u
      end
    end

    def current_user!(&block)
      current_user(&block)
      before { current_user }
    end
  end
end
GPK of the Day Charred CHAD