#<Stripe::Customer:0x00007f1ac4d0b548> 的未定义方法“订阅”/无法为 SubscriptionsController 找到操作 'index'
Undefined method `subscriptions' for #<Stripe::Customer:0x00007f1ac4d0b548> / The action 'index' could not be found for SubscriptionsController
在我使用 Stripe API 提交卡详细信息后,我将 运行 留在这两个错误中,然后该应用程序应创建一个新订阅者并将其重定向到图书馆,但我却得到了:
Undefined method `subscriptions' for #Stripe::Customer:0x00007f1ac4d0b548
和
The action 'index' could not be found for SubscriptionsController
而且我总是先遇到第一个错误,然后当我刷新页面时它会变成第二个错误。
这是我的 subscriptions_controller (/app/controllers/subscriptions_controller.rb):
class SubscriptionsController < ApplicationController
layout "subscribe"
before_action :authenticate_user!, except: [:new, :create]
def new
if user_signed_in? && current_user.subscribed?
redirect_to root_path, notice: "You are already a subscriber!"
end
end
def create
Stripe.api_key = Rails.application.credentials.stripe_api_key
plan_id = params[:plan_id]
plan = Stripe::Plan.retrieve(plan_id)
token = params[:stripeToken]
customer = if current_user.stripe_id?
Stripe::Customer.retrieve(current_user.stripe_id)
else
Stripe::Customer.create(email: current_user.email, source: token)
end
subscription = customer.subscriptions.create(plan: plan.id)
options = {
stripe_id: customer.id,
stripe_subscription_id: subscription.id,
subscribed: true,
}
options.merge!(
card_last4: params[:user][:card_last4],
card_exp_month: params[:user][:card_exp_month],
card_exp_year: params[:user][:card_exp_year],
card_type: params[:user][:card_type]
) if params[:user][:card_last4]
current_user.update(options)
redirect_to root_path, notice: "Your subscription was set up successfully!"
end
def destroy
customer = Stripe::Customer.retrieve(current_user.stripe_id)
customer.subscriptions.retrieve(current_user.stripe_subscription_id).delete
current_user.update(stripe_subscription_id: nil)
redirect_to root_path, notice: "Your subscription has been cancelled."
end
end
这是我的 subscribe.html.erb (app/views/layouts/subscribe.html.erb)
<!DOCTYPE html>
<html>
<head>
<title><%= Rails.configuration.application_name %></title>
<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'https://js.stripe.com/v3/','data-turbolinks-track': 'reload' %>
<%= tag :meta, name: "stripe-key", content: Rails.application.credentials.stripe_publishable_key %>
</head>
<body class="<%= yield (:body_class) %>">
<% if flash[:notice] %>
<div class="notification is-success global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-dark" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<div class="navbar-item">
<h1 class="title is-5 has-text-white"><%= Rails.configuration.application_name %></h1>
</div>
</div>
</nav>
<div class="container">
<%= yield %>
</div>
</body>
</html>
这里是/app/views/subscriptions/new.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= Rails.configuration.application_name %></title>
<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'https://js.stripe.com/v3/','data-turbolinks-track': 'reload' %>
<%= tag :meta, name: "stripe-key", content: Rails.application.credentials.stripe_publishable_key %>
</head>
<body class="<%= yield (:body_class) %>">
<% if flash[:notice] %>
<div class="notification is-success global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-dark" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<div class="navbar-item">
<h1 class="title is-5 has-text-white"><%= Rails.configuration.application_name %></h1>
</div>
</div>
</nav>
<div class="container">
<%= yield %>
</div>
</body>
</html>
这是用于订阅的 javascript 文件 (app/assets/javascripts/subscriptions.js)
document.addEventListener("turbolinks:load", function() {
const publishableKey = document.querySelector("meta[name='stripe-key']").content;
const stripe = Stripe(publishableKey);
const elements = stripe.elements({
fonts: [{
cssSrc: "https://rsms.me/inter/inter-ui.css"
}],
locale: "auto"
});
const style = {
base: {
color: "#32325d",
fontWeight: 500,
fontFamily: "Inter UI, Open Sans, Segoe UI, sans-serif",
fontSize: "16px",
fontSmoothing: "antialiased",
"::placeholder": {
color: "#CFD7DF"
}
},
invalid: {
color: "#E25950"
}
};
const card = elements.create('card', { style });
card.mount("#card-element");
card.addEventListener('change', ( {error} ) => {
const displayError = document.getElementById('card-errors');
if(error) {
displayError.textContent = error.message;
} else {
displayError.textContent = "";
}
});
const form = document.getElementById('payment-form');
form.addEventListener('submit', async(event) => {
event.preventDefault();
const { token, error } = await stripe.createToken(card);
if (error) {
const errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
stripeTokenHandler(token);
}
});
const stripeTokenHandler = (token) => {
const form = document.getElementById('payment-form');
const hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
["type", "last4", "exp_month", "exp_year"].forEach(function(field) {
addCardField(form, token, field);
});
form.submit();
}
function addCardField(form, token, field) {
let hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', "user[card_" + field + "]");
hiddenInput.setAttribute('value', token.card[field]);
form.appendChild(hiddenInput);
}
});
这是我的 routes.rb (/config/routes.rb):
require 'sidekiq/web'
Rails.application.routes.draw do
resources :books do
member do
put "add", to: "books#library"
put "remove", to: "books#library"
end
end
resources :library, only:[:index]
resources :pricing, only:[:index]
devise_for :users, controllers: { registrations: "registrations" }
root to: 'books#index'
resources :subscriptions
end
这是显示索引错误时的控制台
console
任何想法都会很有帮助!谢谢你
有多种创建订阅的方法,如果我记得,那是一种较旧的方法,但现在您可以 - 并且应该 - 创建它 like this:
Stripe::Subscription.create({
customer: customer.id,
items: [
{price: plan.id},
],
})
在我使用 Stripe API 提交卡详细信息后,我将 运行 留在这两个错误中,然后该应用程序应创建一个新订阅者并将其重定向到图书馆,但我却得到了:
Undefined method `subscriptions' for #Stripe::Customer:0x00007f1ac4d0b548
和
The action 'index' could not be found for SubscriptionsController
而且我总是先遇到第一个错误,然后当我刷新页面时它会变成第二个错误。
这是我的 subscriptions_controller (/app/controllers/subscriptions_controller.rb):
class SubscriptionsController < ApplicationController
layout "subscribe"
before_action :authenticate_user!, except: [:new, :create]
def new
if user_signed_in? && current_user.subscribed?
redirect_to root_path, notice: "You are already a subscriber!"
end
end
def create
Stripe.api_key = Rails.application.credentials.stripe_api_key
plan_id = params[:plan_id]
plan = Stripe::Plan.retrieve(plan_id)
token = params[:stripeToken]
customer = if current_user.stripe_id?
Stripe::Customer.retrieve(current_user.stripe_id)
else
Stripe::Customer.create(email: current_user.email, source: token)
end
subscription = customer.subscriptions.create(plan: plan.id)
options = {
stripe_id: customer.id,
stripe_subscription_id: subscription.id,
subscribed: true,
}
options.merge!(
card_last4: params[:user][:card_last4],
card_exp_month: params[:user][:card_exp_month],
card_exp_year: params[:user][:card_exp_year],
card_type: params[:user][:card_type]
) if params[:user][:card_last4]
current_user.update(options)
redirect_to root_path, notice: "Your subscription was set up successfully!"
end
def destroy
customer = Stripe::Customer.retrieve(current_user.stripe_id)
customer.subscriptions.retrieve(current_user.stripe_subscription_id).delete
current_user.update(stripe_subscription_id: nil)
redirect_to root_path, notice: "Your subscription has been cancelled."
end
end
这是我的 subscribe.html.erb (app/views/layouts/subscribe.html.erb)
<!DOCTYPE html>
<html>
<head>
<title><%= Rails.configuration.application_name %></title>
<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'https://js.stripe.com/v3/','data-turbolinks-track': 'reload' %>
<%= tag :meta, name: "stripe-key", content: Rails.application.credentials.stripe_publishable_key %>
</head>
<body class="<%= yield (:body_class) %>">
<% if flash[:notice] %>
<div class="notification is-success global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-dark" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<div class="navbar-item">
<h1 class="title is-5 has-text-white"><%= Rails.configuration.application_name %></h1>
</div>
</div>
</nav>
<div class="container">
<%= yield %>
</div>
</body>
</html>
这里是/app/views/subscriptions/new.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= Rails.configuration.application_name %></title>
<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'https://js.stripe.com/v3/','data-turbolinks-track': 'reload' %>
<%= tag :meta, name: "stripe-key", content: Rails.application.credentials.stripe_publishable_key %>
</head>
<body class="<%= yield (:body_class) %>">
<% if flash[:notice] %>
<div class="notification is-success global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-dark" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<div class="navbar-item">
<h1 class="title is-5 has-text-white"><%= Rails.configuration.application_name %></h1>
</div>
</div>
</nav>
<div class="container">
<%= yield %>
</div>
</body>
</html>
这是用于订阅的 javascript 文件 (app/assets/javascripts/subscriptions.js)
document.addEventListener("turbolinks:load", function() {
const publishableKey = document.querySelector("meta[name='stripe-key']").content;
const stripe = Stripe(publishableKey);
const elements = stripe.elements({
fonts: [{
cssSrc: "https://rsms.me/inter/inter-ui.css"
}],
locale: "auto"
});
const style = {
base: {
color: "#32325d",
fontWeight: 500,
fontFamily: "Inter UI, Open Sans, Segoe UI, sans-serif",
fontSize: "16px",
fontSmoothing: "antialiased",
"::placeholder": {
color: "#CFD7DF"
}
},
invalid: {
color: "#E25950"
}
};
const card = elements.create('card', { style });
card.mount("#card-element");
card.addEventListener('change', ( {error} ) => {
const displayError = document.getElementById('card-errors');
if(error) {
displayError.textContent = error.message;
} else {
displayError.textContent = "";
}
});
const form = document.getElementById('payment-form');
form.addEventListener('submit', async(event) => {
event.preventDefault();
const { token, error } = await stripe.createToken(card);
if (error) {
const errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
stripeTokenHandler(token);
}
});
const stripeTokenHandler = (token) => {
const form = document.getElementById('payment-form');
const hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
["type", "last4", "exp_month", "exp_year"].forEach(function(field) {
addCardField(form, token, field);
});
form.submit();
}
function addCardField(form, token, field) {
let hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', "user[card_" + field + "]");
hiddenInput.setAttribute('value', token.card[field]);
form.appendChild(hiddenInput);
}
});
这是我的 routes.rb (/config/routes.rb):
require 'sidekiq/web'
Rails.application.routes.draw do
resources :books do
member do
put "add", to: "books#library"
put "remove", to: "books#library"
end
end
resources :library, only:[:index]
resources :pricing, only:[:index]
devise_for :users, controllers: { registrations: "registrations" }
root to: 'books#index'
resources :subscriptions
end
这是显示索引错误时的控制台 console
任何想法都会很有帮助!谢谢你
有多种创建订阅的方法,如果我记得,那是一种较旧的方法,但现在您可以 - 并且应该 - 创建它 like this:
Stripe::Subscription.create({
customer: customer.id,
items: [
{price: plan.id},
],
})