Skip to content

Commit

Permalink
Use inheritance to obey the Open/Closed Principle
Browse files Browse the repository at this point in the history
* Uses a subclass to add unsubscribeable behavior
* Demonstrates when subclasses are ugly
  • Loading branch information
jferris committed Apr 25, 2013
1 parent 69f3470 commit bf1ba7d
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 25 deletions.
10 changes: 2 additions & 8 deletions example_app/app/models/invitation.rb
Expand Up @@ -15,19 +15,13 @@ def to_param
end

def deliver
unless unsubscribed?
body = InvitationMessage.new(self).body
Mailer.invitation_notification(self, body).deliver
end
body = InvitationMessage.new(self).body
Mailer.invitation_notification(self, body).deliver
end

private

def set_token
self.token = SecureRandom.urlsafe_base64
end

def unsubscribed?
Unsubscribe.where(email: recipient_email).exists?
end
end
2 changes: 1 addition & 1 deletion example_app/app/models/survey_inviter.rb
Expand Up @@ -31,7 +31,7 @@ def deliver_invitations
def create_invitations
Invitation.transaction do
recipients.map do |recipient_email|
Invitation.create!(
UnsubscribeableInvitation.create!(
survey: survey,
sender: sender,
recipient_email: recipient_email,
Expand Down
13 changes: 13 additions & 0 deletions example_app/app/models/unsubscribeable_invitation.rb
@@ -0,0 +1,13 @@
class UnsubscribeableInvitation < Invitation
def deliver
unless unsubscribed?
super
end
end

private

def unsubscribed?
Unsubscribe.where(email: recipient_email).exists?
end
end
16 changes: 1 addition & 15 deletions example_app/spec/models/invitation_spec.rb
Expand Up @@ -26,22 +26,8 @@
message.should have_body_text(survey_url(invitation.survey))
end

it 'sends nothing to users that have unsubscribed' do
unsubscribe = create(:unsubscribe)
deliver_invitation(recipient_email: unsubscribe.email)

find_email(unsubscribe.email).should be_nil
end

def deliver_invitation(overrides = {})
attributes = {
message: 'hello',
survey: create(:survey)
}.merge(overrides)

create(:invitation, attributes).tap do |invitation|
invitation.deliver
end
InvitationDeliverer.new(Invitation).deliver_invitation(overrides)
end
end

Expand Down
6 changes: 5 additions & 1 deletion example_app/spec/models/survey_inviter_spec.rb
Expand Up @@ -23,7 +23,11 @@
it "doesn't send emails if any invitations fail to save" do
invitation = stub('invitation', deliver: true)
error = StandardError.new('failure')
Invitation.stubs(:create!).returns(invitation).then.raises(error)
UnsubscribeableInvitation.
stubs(:create!).
returns(invitation).
then.
raises(error)
params = valid_params(recipients: 'one@example.com,two@example.com')
inviter = SurveyInviter.new(params)

Expand Down
25 changes: 25 additions & 0 deletions example_app/spec/models/unsubscribeable_invitation_spec.rb
@@ -0,0 +1,25 @@
require 'spec_helper'

describe UnsubscribeableInvitation, '#deliver' do
include Rails.application.routes.url_helpers
self.default_url_options = ActionMailer::Base.default_url_options

it 'sends email notifications to new users' do
invitation = deliver_invitation

find_email(invitation.recipient_email).
should have_body_text(invitation.message)
end

it 'sends nothing to users that have unsubscribed' do
unsubscribe = create(:unsubscribe)
deliver_invitation(recipient_email: unsubscribe.email)

find_email(unsubscribe.email).should be_nil
end

def deliver_invitation(overrides = {})
InvitationDeliverer.new(UnsubscribeableInvitation).
deliver_invitation(overrides)
end
end
19 changes: 19 additions & 0 deletions example_app/spec/support/invitation_deliverer.rb
@@ -0,0 +1,19 @@
class InvitationDeliverer
include FactoryGirl::Syntax::Methods

def initialize(factory)
@factory = factory
end

def deliver_invitation(overrides = {})
attributes = {
message: 'hello',
survey: create(:survey)
}.merge(overrides)
invitation_attributes = create(:invitation, attributes).attributes

@factory.new(invitation_attributes).tap do |invitation|
invitation.deliver
end
end
end

0 comments on commit bf1ba7d

Please sign in to comment.