RailsApps / rails-stripe-membership-saas

An example Rails 4.2 app with Stripe and the Payola gem for a membership or subscription site.
http://railsapps.github.io/rails-stripe-membership-saas
1.14k stars 232 forks source link

Best way to update plan/reassign credit card in devise edit? #172

Open RailsCod3rFuture opened 5 years ago

RailsCod3rFuture commented 5 years ago

The user plan and credit card are failing to update when I submit the changes to the form. Its crashing with a 500 error. Btw, I'm using SubscriptionPlan instead of Plan, to avoid namespace issues on my platform

registrations_controller.rb

  def user_change_plan
    plan = SubscriptionPlan.find_by!(id: params[:user][:subscription_plan_id].to_i)
    unless plan == current_user.subscription_plan
      role = User.roles[subscription_plan.stripe_id]
      if current_user.update_attributes!(subscription_plan: plan, role: role)
        subscription = Payola::Subscription.find_by!(owner_id: current_user.id)
        Payola::ChangeSubscriptionPlan.call(subscription, plan)
        redirect_to edit_user_registration_path, :notice => "Plan changed."
      else
        flash[:alert] = 'Unable to change plan.'
        build_resource
        render :edit
      end
    end
  end

users\registrations\edit.html.erb

<div class="update-subscription">
      <%= simple_form_for(resource, as: resource_name, url: user_change_plan_path, :html => {:method => :put, :role => 'form'}) do |f| %>
        <div class="form-group credit-card-label">
          <div class="col-md-4 field card">
            <label>Credit Card Number</label>
            <input id="card_number" type="text" data-stripe="number" class="form-control card-number" maxlength="19" placeholder="Enter your 19 Digit Credit Card Number"/>
            <span class="card_icon" style="margin-top: 0.05em"></span> <br>
            <p class="status"><span class="status_icon"></span><span class="status_message"></span></p>
          </div>
        </div>
        <div class="form-group row">
          <div class="col-md-2">
            <label>Card Expire Date</label>
            <input type="text" data-stripe="exp-month" placeholder="Month" class="form-control">
            <input type="text" data-stripe="exp-year" placeholder="Year" class="form-control">
          </div>
        </div>
        <div class="form-group">
          <div class="col-2">
            <label>Card Security Code</label>
            <input id="card_code" placeholder="cvc" type="text" data-stripe="number" class="form-control"/>
          </div>
        </div>
        <div class="form-group">
          <button class="btn btn-primary-outline" type="submit">Change Subscription Plan</button>
        </div>
        </div>
        <input type="hidden" value="<%= form_authenticity_token() %>" name="authenticity_token"/>
      <% end %>

routes.rb

 devise_scope :user do
    put 'user_change_plan', :to => 'users/registrations#user_change_plan'
    authenticated do
      root to: 'user_dashboard#index', as: 'authenticated_user_root'
    end
    unauthenticated do
      root to: 'home#index', as: 'unauthenticated_user_root'
    end
  end

Stack trace

Started PUT "/user_change_plan" for 127.0.0.1 at 2018-11-24 13:01:58 -0500
Processing by Users::RegistrationsController#user_change_plan as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"UTVhe2CIwzvpppGt+QS3K9Qh+OwGbYzlXVkHL5Yn8Pvd6cZ2VhtWV09Rfk3T4bCLRWl1CvEnvImwiMSoNHUnfw==", "user"=>{"subscription_plan_id"=>"4"}, "commit"=>"Change Plan"}
  SubscriptionPlan Load (0.0ms)  SELECT  "subscription_plans".* FROM "subscription_plans" WHERE "subscription_plans"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
  User Load (1.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
  SubscriptionPlan Load (1.0ms)  SELECT  "subscription_plans".* FROM "subscription_plans" WHERE "subscription_plans"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
   (0.0ms)  BEGIN
  SubscriptionPlan Exists (1.0ms)  SELECT  1 AS one FROM "subscription_plans" WHERE "subscription_plans"."stripe_id" = $1 AND "subscription_plans"."id" != $2 LIMIT $3  [["stripe_id", "silver"], ["id", 4], ["LIMIT", 1]]
  User Exists (1.0ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."id" != $2 LIMIT $3  [["email", "cooler@hotmail.com"], ["id", 2], ["LIMIT", 1]]
  User Exists (0.0ms)  SELECT  1 AS one FROM "users" WHERE "users"."username" = $1 AND "users"."id" != $2 LIMIT $3  [["username", "cooler"], ["id", 2], ["LIMIT", 1]]
   (0.0ms)  ROLLBACK
Completed 422 Unprocessable Entity in 872ms (ActiveRecord: 4.0ms)

ActiveRecord::RecordInvalid (Validation failed: Password can't be blank, Password is too weak):

app/controllers/users/registrations_controller.rb:44:in `user_change_plan'

Attempting to change only the subscription plan fails also.

<div class="authform">
      <h3>Subscription Plan</h3>
      <%= simple_form_for(resource, as: resource_name, url: user_change_plan_path, :html => {:method => :put, :role => 'form'}) do |f| %>
        <div class="form-group">
          <div class="col-md-3">
            <%= f.label 'Change Monthly Subscription Plan' %>
            <%= f.association :subscription_plan, collection: SubscriptionPlan.user_plan.map {|c| [c.name, c.id]}, label: false, prompt: 'Choose a plan' %>
          </div>
          <%= f.submit 'Change Plan', :class => 'btn btn-primary-outline btn-md' %>
        </div>
      <% end %>
    </div>
RailsCod3rFuture commented 5 years ago

One other note: I'm using Rails 5.2 and ruby 2.4.4