DRY-ing up some rspec I have an rspec spec test that has two sets of the same tests (from 24 Pull Requests). I thought I'd refactor the spec whilst I fixed something else.

Normally I just do a basic each ... do array to DRY things up:

require 'spec_helper'

describe ReminderMailer, type: :mailer do

  # Half the code yay! :D
  ['daily','weekly'].each do |time_format|
    describe time_format do
      let(:time_format) { time_format }
      let(:user) do
        mock_model(User, nickname:           'David',
                         email:              'david@example.com',
                         languages:          ['Ruby'],
                         skills:             [],
                         pull_requests:      double(:pull_request, year: []),
                         suggested_projects: [])
      end

      # How do I do this bit better?  
      let(:mail) {
        if time_format == 'daily'
          ReminderMailer.daily(user)
        else
          ReminderMailer.weekly(user)
        end
      }

end


I couldn't figure out how to use the time_format with the send command, so I could do something like:

let(:mail) { ReminderMailer.send(timeformat(user) }


How could I do this?
The snippet you asked to re-write:

let(:mail) { ReminderMailer.send(time_format, user) }


Now, IMO using each to write specs is a bad practice. Why? Because rspec already provides idiomatic infrastructure to keep specs DRYed: use before and shared_examples. I'd write:

describe ReminderMailer, type: :mailer do
  let(:user) { ... }

  shared_examples "a reminder mailer" do |subject:, body:|
    it 'renders the subject' do
      expect(mail.subject).to eq(subject)
    end

    it 'renders the receiver email' do
      expect(mail.to).to eq([user.email])
    end

    it 'renders the sender email' do
      expect(mail['From'].to_s).to eq('24 Pull Requests &lt;info@24pullrequests.com&gt;')
    end

    it 'uses nickname' do
      expect(mail.body.encoded).to match(user.nickname)
    end

    it 'contains periodicity in body' do
      expect(mail.body.encoded).to match(body)
    end
  end

  describe 'daily' do
    let(:mail) { ReminderMailer.daily(user) }

    it_behaves_like "a reminder mailer", 
      subject: '[24 Pull Requests] Daily Reminder',
      body: 'today'
  end

  describe 'weekly' do
    let(:mail) { ReminderMailer.weekly(user) }

    it_behaves_like "a reminder mailer", 
      subject: '[24 Pull Requests] Weekly Reminder',
      body: 'week'
  end
end