Skip to content

Commit bf1ba7d

Browse files
committed
Use inheritance to obey the Open/Closed Principle
* Uses a subclass to add unsubscribeable behavior * Demonstrates when subclasses are ugly
1 parent 69f3470 commit bf1ba7d

7 files changed

Lines changed: 66 additions & 25 deletions

File tree

example_app/app/models/invitation.rb

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,13 @@ def to_param
1515
end
1616

1717
def deliver
18-
unless unsubscribed?
19-
body = InvitationMessage.new(self).body
20-
Mailer.invitation_notification(self, body).deliver
21-
end
18+
body = InvitationMessage.new(self).body
19+
Mailer.invitation_notification(self, body).deliver
2220
end
2321

2422
private
2523

2624
def set_token
2725
self.token = SecureRandom.urlsafe_base64
2826
end
29-
30-
def unsubscribed?
31-
Unsubscribe.where(email: recipient_email).exists?
32-
end
3327
end

example_app/app/models/survey_inviter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def deliver_invitations
3131
def create_invitations
3232
Invitation.transaction do
3333
recipients.map do |recipient_email|
34-
Invitation.create!(
34+
UnsubscribeableInvitation.create!(
3535
survey: survey,
3636
sender: sender,
3737
recipient_email: recipient_email,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class UnsubscribeableInvitation < Invitation
2+
def deliver
3+
unless unsubscribed?
4+
super
5+
end
6+
end
7+
8+
private
9+
10+
def unsubscribed?
11+
Unsubscribe.where(email: recipient_email).exists?
12+
end
13+
end

example_app/spec/models/invitation_spec.rb

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,8 @@
2626
message.should have_body_text(survey_url(invitation.survey))
2727
end
2828

29-
it 'sends nothing to users that have unsubscribed' do
30-
unsubscribe = create(:unsubscribe)
31-
deliver_invitation(recipient_email: unsubscribe.email)
32-
33-
find_email(unsubscribe.email).should be_nil
34-
end
35-
3629
def deliver_invitation(overrides = {})
37-
attributes = {
38-
message: 'hello',
39-
survey: create(:survey)
40-
}.merge(overrides)
41-
42-
create(:invitation, attributes).tap do |invitation|
43-
invitation.deliver
44-
end
30+
InvitationDeliverer.new(Invitation).deliver_invitation(overrides)
4531
end
4632
end
4733

example_app/spec/models/survey_inviter_spec.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
it "doesn't send emails if any invitations fail to save" do
2424
invitation = stub('invitation', deliver: true)
2525
error = StandardError.new('failure')
26-
Invitation.stubs(:create!).returns(invitation).then.raises(error)
26+
UnsubscribeableInvitation.
27+
stubs(:create!).
28+
returns(invitation).
29+
then.
30+
raises(error)
2731
params = valid_params(recipients: 'one@example.com,two@example.com')
2832
inviter = SurveyInviter.new(params)
2933

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'spec_helper'
2+
3+
describe UnsubscribeableInvitation, '#deliver' do
4+
include Rails.application.routes.url_helpers
5+
self.default_url_options = ActionMailer::Base.default_url_options
6+
7+
it 'sends email notifications to new users' do
8+
invitation = deliver_invitation
9+
10+
find_email(invitation.recipient_email).
11+
should have_body_text(invitation.message)
12+
end
13+
14+
it 'sends nothing to users that have unsubscribed' do
15+
unsubscribe = create(:unsubscribe)
16+
deliver_invitation(recipient_email: unsubscribe.email)
17+
18+
find_email(unsubscribe.email).should be_nil
19+
end
20+
21+
def deliver_invitation(overrides = {})
22+
InvitationDeliverer.new(UnsubscribeableInvitation).
23+
deliver_invitation(overrides)
24+
end
25+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class InvitationDeliverer
2+
include FactoryGirl::Syntax::Methods
3+
4+
def initialize(factory)
5+
@factory = factory
6+
end
7+
8+
def deliver_invitation(overrides = {})
9+
attributes = {
10+
message: 'hello',
11+
survey: create(:survey)
12+
}.merge(overrides)
13+
invitation_attributes = create(:invitation, attributes).attributes
14+
15+
@factory.new(invitation_attributes).tap do |invitation|
16+
invitation.deliver
17+
end
18+
end
19+
end

0 commit comments

Comments
 (0)