Updating column from being NULL after action is called

219 views Asked by At

Stripe is setup on my app and users can cancel or upgrade their subscription. It communicates perfectly to Stripe. I need help figuring out how I can make the changes communicate with my database.

If a user cancels their subscription it should be marked in the Subscriptions table under a cancelled column. With this in place the user will be restricted access to website if it shows in the database that their subscription was cancelled.

I am not sure how to add this to the cancel subscription action I have setup.

Help with this would be greatly appreciated!

Subscriptions controller:

  def new
    plan = Plan.find(params[:plan_id])
    @subscription = plan.subscriptions.build
    if params[:PayerID]
      @subscription.paypal_customer_token = params[:PayerID]
      @subscription.paypal_payment_token = params[:token]
      @subscription.email = @subscription.paypal.checkout_details.email
    end
  end

  def create
    @subscription = Subscription.new(params[:subscription])
    if @subscription.save_with_payment
      redirect_to @subscription, :notice => "Thank you for subscribing!"
    else
      render :new
    end
  end

  def show
    @subscription = Subscription.find(params[:id])
  end

    def updatesubscription
      @user = current_user
      @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)
      @customer.update_subscription(:plan => "1", :prorate => true)
     current_user.save!
      flash.alert = 'Your subscription has been updated!'
      redirect_to root_url
     end

     def cancelsubscription
       @user = current_user
         @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)
         @customer.cancel_subscription()
         current_user.save!
         flash.alert = 'Your subscription has been cancelled successfully!'
         redirect_to root_url
       end

       def showcard
         @user = current_user
         Stripe::Customer.retrieve(@user.subscription.stripe_customer_token).cards.all()
       end

       def changecard
           @user = current_user       
           @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)

             card = @customer.cards.create({
               :card => @user.subscription.stripe_customer_token
             })

             @customer.default_card = card
             @customer.save
           end
end

Subscription model:

  belongs_to :plan
  belongs_to :subscription
  belongs_to :user

  validates_presence_of :plan_id
  validates_presence_of :email

  attr_accessor :stripe_card_token, :paypal_payment_token

  def save_with_payment
    if valid?
      if paypal_payment_token.present?
        save_with_paypal_payment
      else
        save_with_stripe_payment
      end
    end
  end

  def paypal
    PaypalPayment.new(self)
  end

  def save_with_paypal_payment
    response = paypal.make_recurring
    self.paypal_recurring_profile_token = response.profile_id
    save!
  end

  def save_with_stripe_payment
    customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
    self.stripe_customer_token = customer.id
    save!
  rescue Stripe::InvalidRequestError => e
    logger.error "Stripe error while creating customer: #{e.message}"
    errors.add :base, "There was a problem with your credit card."
    false
  end

  def payment_provided?
    stripe_card_token.present? || paypal_payment_token.present?
  end

  def suspend_paypal
    paypal.suspend
    save
  end


  def reactivate_paypal
    paypal.reactivate
    save
  end
end
2

There are 2 answers

0
Cornelius Wilson On BEST ANSWER

The simplest way to do it would be to add extra lines to update the required column.

def cancelsubscription
  @user = current_user
  @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)
  @customer.cancel_subscription()
  current_user.subscription.update_attributes(:cancelled => 1)
  current_user.save!
  flash.alert = 'Your subscription has been cancelled successfully!'
  redirect_to root_url
end

However, ideally all this should happen within a model. From the controller you should just be telling the model to cancel the subscription.

So, this method could become something like:

#subscriptions_controller.rb
def cancelsubscription
  current_user.subscription.cancel_stripe_subscription
  flash.alert = 'Your subscription has been cancelled successfully!'
  redirect_to root_url
end

#subscription.rb model
def cancel_stripe_subscription
  customer = Stripe::Customer.retrieve(self.stripe_customer_token)
  customer.cancel_subscription()
  self.cancelled = 1
  self.save!
end
5
Oscar Valdez Esquea On

Cant you update the Subscription table via an active_record query? Like this:

updateQuery = ActiveRecord::Base.connection.execute("UPDATE Subscription SET cancelled = 'Cancelled' WHERE user_id = #{@user.id}")

That'd update your subscription table and change the targetted field value to "Cancelled". Its not clear if this is a boolean or not. If it is, then the value should be "TRUE" instead of the "Cancelled" string i put in there.

If subscription succesfully saves, then you execute the query. But you'd have to make sure you put the query between a condition so that it only executes it when the user has cancelled the subscription, not every time its updated.

respond_to do |format|
  if @subscription.save
    if (something to tell the controller you are cancelling the subscription)
       EXECUTE QUERY HERE
    end
  end
end