首页 > 解决方案 > Rails PUT/POST 请求在第一次尝试时失败,在下一次尝试

问题描述

我有一个带有 Ruby On Rails API 后端的 VueJS 前端应用程序。我需要更改有关数据库中用户的信息。

我有一个删除信用卡信息的 PUT/POST 请求。基本的rails代码如下。我遇到的问题是我得到了一个非常流行的错误:

NoMethodError (undefined method []' for nil:NilClass):

但问题是它只发生在第一次尝试时。随后的尝试都成功了。有人可以在这里指出我正确的方向吗?如果您需要更多信息,请随时询问。

class AccountsController < ApplicationController
   before_action :load_account, only: [:show, :update, :destroy, :formats, :charges, :destroy_card]
   
   def destroy_card
     @account.card_last_4 = nil
     @account.card_type = nil
     @account.card_exp_month = nil
     @account.card_exp_year = nil
     @account.plan_id = 1
     @account.save!

     render json: { account: @account }, status: 200
   end

   private

   def load_account
     if @current_user.admin?
       @account =  Account.find(params[:id])
     else
       @account = @current_user.accounts.find_by_id(params[:id]) unless @account.present?
     end
   end
 end

错误:


Started PUT "//accounts/20/destroy_card" for ::1 at 2020-08-17 20:24:47 -0400
Processing by AccountsController#destroy_card as */*
  Parameters: {"id"=>20, "account_id"=>"20"}
  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 10 LIMIT 1
  ↳ app/controllers/application_controller.rb:18:in `load_user'
  AccountUser Load (0.2ms)  SELECT `account_users`.* FROM `account_users` WHERE `account_users`.`user_id` = 10 AND `account_users`.`account_id` = 20 LIMIT 1
  ↳ app/controllers/application_controller.rb:28:in `load_user'
  Account Load (0.1ms)  SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`id` = 20 LIMIT 1
  ↳ app/controllers/application_controller.rb:30:in `load_user'
  CACHE Account Load (0.0ms)  SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`id` = 20 LIMIT 1  [["id", 20], ["LIMIT", 1]]
  ↳ app/controllers/accounts_controller.rb:97:in `load_account'
   (0.1ms)  BEGIN
  ↳ app/models/account.rb:148:in `assign_plan'
  Plan Load (0.1ms)  SELECT `plans`.* FROM `plans` WHERE `plans`.`id` = 1 LIMIT 1
  ↳ app/models/account.rb:148:in `assign_plan'
  Account Update (0.2ms)  UPDATE `accounts` SET `accounts`.`card_last_4` = NULL, `accounts`.`card_type` = NULL, `accounts`.`card_exp_month` = NULL, `accounts`.`card_exp_year` = NULL, `accounts`.`plan_id` = 1, `accounts`.`updated_at` = '2020-08-18 00:24:47' WHERE `accounts`.`id` = 20
  ↳ app/controllers/accounts_controller.rb:82:in `destroy_card'
  Account Update (0.3ms)  UPDATE `accounts` SET `accounts`.`plan_updated_at` = '2020-08-18 00:24:47' WHERE `accounts`.`id` = 20
  ↳ app/models/account.rb:60:in `stripe_subscribe'
   (9.1ms)  ROLLBACK
  ↳ app/controllers/accounts_controller.rb:82:in `destroy_card'
Completed 500 Internal Server Error in 1150ms (ActiveRecord: 10.4ms | Allocations: 22601)



NoMethodError (undefined method `[]' for nil:NilClass):

app/models/account.rb:71:in `stripe_subscribe'
app/controllers/accounts_controller.rb:82:in `destroy_card'

代码来自account.rb

 def stripe_subscribe
    s = stripe_customer.subscriptions.first

    self.plan_updated_at = Time.now
    save!

    if coupon.present? && plan.id != coupon.plan_id
      self.coupon = nil
      save!
    end

    if plan.price == 0
      # Downgrading from a paid tier
      if s.present?
        meta = s.delete
        self.changed_plan = Plan.find(previous_changes[:plan_id][0])
        self.changed_plan_date = Time.at(meta['current_period_end']).to_datetime
        save!
      end
    else
      s.delete({ prorate: true, invoice_now: true }) if s.present?
      params = { items: [{ plan: plan.short_name }] }
      if coupon.present?
        params[:coupon] = coupon.token
      end
      stripe_customer.subscriptions.create(params)
      if Rails.env == 'production'
        client = Slack::Web::Client.new
        client.chat_postMessage(channel: '#somechannel', text: "some random message", as_user: true)
      end
    end
  end

标签: ruby-on-rails

解决方案


推荐阅读