diff --git a/app/models/user.rb b/app/models/user.rb index 509f92a..a7eaa26 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -4,7 +4,7 @@ class User < ActiveRecord::Base # :token_authenticatable, :confirmable, # :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :first_name, :last_name, :email, :password, :password_confirmation, :remember_me, :card_token, :customer_id @@ -17,54 +17,19 @@ def name end def check_recurly - customer = Recurly::Account.find(customer_id) unless customer_id.nil? - rescue Recurly::Resource::NotFound => e - logger.error e.message - errors.add :base, "Unable to create your subscription. #{e.message}" - false + recurly_account_checker.customer_exists? end def update_plan(role) - self.role_ids = [] - self.add_role(role.name) - customer = Recurly::Account.find(customer_id) unless customer_id.nil? - unless customer.nil? - subscription = customer.subscriptions.first - subscription.update_attributes! :timeframe => 'now', :plan_code => role.name - end - true - rescue Recurly::Resource::Invalid => e - logger.error e.message - errors.add :base, "Unable to update your subscription. #{e.message}" - false + recurly_account_checker.update_subscriber(role) end def update_recurly - customer = Recurly::Account.find(customer_id) unless customer_id.nil? - unless customer.nil? - customer.email = email - customer.first_name = first_name - customer.last_name = last_name - customer.save! - end - rescue Recurly::Resource::NotFound => e - logger.error e.message - errors.add :base, "Unable to update your subscription. #{e.message}" - false + recurly_account_checker.update_customer end def cancel_subscription - unless customer_id.nil? - customer = Recurly::Account.find(customer_id) - subscription = customer.subscriptions.first unless customer.nil? - if (!subscription.nil?) && (subscription.state == 'active') - subscription.cancel - end - end - rescue Recurly::Resource::NotFound => e - logger.error e.message - errors.add :base, "Unable to cancel your subscription. #{e.message}" - false + recurly_account_checker.cancel_subscription end def expire @@ -72,4 +37,9 @@ def expire destroy end + private + def recurly_account_checker + RecurlyAccountChecker.new(self) + end + end diff --git a/app/services/recurly_account_checker.rb b/app/services/recurly_account_checker.rb new file mode 100644 index 0000000..2a04f42 --- /dev/null +++ b/app/services/recurly_account_checker.rb @@ -0,0 +1,71 @@ +class RecurlyAccountChecker + attr_reader :user + + def initialize(user) + @user = user + end + + def customer_exists? + !customer.nil? + end + + def cancel_subscription + handle_recurly_exception do + if customer_exists? + subscription.cancel if !subscription.nil? && subscription.state == 'active' + end + end + end + + def update_customer + handle_recurly_exception do + if customer_exists? + customer.email = user.email + customer.first_name = user.first_name + customer.last_name = user.last_name + customer.save! + end + end + end + + def update_subscriber(role) + handle_recurly_exception do + user.role_ids = [] + user.add_role role.name + subscription.update_attributes! :timeframe => 'now', :plan_code => role.name if customer_exists? + end + end + + + def customer + @customer ||= retrieve_customer + end + + private + def customer_id + user.customer_id + end + + def subscription + @subscription ||= customer.subscriptions.first + end + + def user_customer_id_exists? + !user.customer_id.nil? + end + + def retrieve_customer + handle_recurly_exception do + Recurly::Account.find(customer_id) if user_customer_id_exists? + end + end + + def handle_recurly_exception(&block) + yield + rescue Recurly::Resource::NotFound => e + user.logger.error e.message + user.errors.add :base, "Unable to create your subscription. #{e.message}" + false + end + +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5ff5164..e7b95ec 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe User do + let(:account_checker) { stub } before(:each) do @attr = { @@ -10,10 +11,14 @@ :password => "changeme", :password_confirmation => "changeme" } + account_checker.stub(:customer_exists?) { true } end it "should create a new instance given a valid attribute" do - User.create!(@attr) + u = User.new(@attr) + u.stub(:recurly_account_checker) { account_checker } + + u.should be_valid end it "should require an email address" do @@ -38,14 +43,18 @@ end it "should reject duplicate email addresses" do - User.create!(@attr) + u = User.new(@attr) + u.stub(:recurly_account_checker) { account_checker } + u.save user_with_duplicate_email = User.new(@attr) user_with_duplicate_email.should_not be_valid end it "should reject email addresses identical up to case" do upcased_email = @attr[:email].upcase - User.create!(@attr.merge(:email => upcased_email)) + u = User.new(@attr.merge(:email => upcased_email)) + u.stub(:recurly_account_checker) { account_checker } + u.save user_with_duplicate_email = User.new(@attr) user_with_duplicate_email.should_not be_valid end @@ -88,7 +97,7 @@ describe "password encryption" do before(:each) do - @user = User.create!(@attr) + @user = User.new(@attr) end it "should have an encrypted password attribute" do @@ -104,7 +113,7 @@ describe "expire" do before(:each) do - @user = User.create!(@attr) + @user = User.new(@attr) end it "sends an email to user" do @@ -116,9 +125,9 @@ describe "#update_plan" do before do - @user = FactoryGirl.create(:user, email: "test@example.com") - @role1 = FactoryGirl.create(:role, name: "silver") - @role2 = FactoryGirl.create(:role, name: "gold") + @user = FactoryGirl.build(:user, email: "test@example.com") + @role1 = FactoryGirl.build(:role, name: "silver") + @role2 = FactoryGirl.build(:role, name: "gold") @user.add_role(@role1.name) end @@ -130,6 +139,7 @@ it "wont remove original role from database" do @user.update_plan(@role2) + @user.stub(:recurly_account_checker) { account_checker } Role.all.count.should == 2 end end diff --git a/spec/services/recurly_customer_checker_spec.rb b/spec/services/recurly_customer_checker_spec.rb new file mode 100644 index 0000000..d819de6 --- /dev/null +++ b/spec/services/recurly_customer_checker_spec.rb @@ -0,0 +1,60 @@ +require_relative '../../app/services/recurly_account_checker' +require 'recurly' +describe RecurlyAccountChecker do + let(:user) { stub } + let(:customer) { stub } + let(:customer_id) { -1 } + before do + user.stub(:customer_id) { customer_id } + Recurly::Account.stub(:find) { customer } + end + + context "#customer_exists?" do + subject { described_class.new(user).customer_exists? } + + it { should be_true } + end + + context "#update_subscriber" do + let(:role) { stub } + let(:subscription) { stub } + subject { described_class.new(user).update_subscriber(role) } + before do + user.stub(:role_ids=) + user.stub(:add_role) + role.stub(:name) { 'role' } + subscription.stub(:update_attributes!) { true } + customer.stub_chain(:subscriptions, :first) { subscription } + end + + it { should be_true } + end + + context "#update_customer" do + subject { described_class.new(user).update_customer } + before do + user.stub(:email) { 'email@example.com' } + user.stub(:first_name) { 'first_name' } + user.stub(:last_name) { 'last_name' } + customer.stub(:email=).with(user.email) + customer.stub(:first_name=).with(user.first_name) + customer.stub(:last_name=).with(user.last_name) + customer.stub(:save!) { true } + end + + it { should be_true } + end + + context "#cancel_subscription" do + subject { described_class.new(user).cancel_subscription } + let(:subscription) { stub } + before do + customer.stub_chain(:subscription, :first) { subscription } + subscription.stub(:state) { 'active' } + subscription.stub(:cancel) { true } + end + + it { should be_true } + end + +end