Subscription form with Stripe not passing parameters properly - ruby-on-rails

I am getting the following error on my Rails 4.2 application. I'm trying to setup subscriptions with Stripe. A subscription belongs to a business and has_one plan.
On my view I pass the params in the URL:
http://localhost:3000/subscriptions/new?plan_id=2&business_id=1001
After I submit the form I get the error below and my code follows. Forgive me if this is a beginner question.
Subscriptions Controller
class SubscriptionsController < ApplicationController
before_action :set_subscription, only: [:show, :edit, :update, :destroy]
# GET /subscriptions
def index
#subscriptions = Subscription.all
end
# GET /subscriptions/1
def show
end
# GET /subscriptions/new
def new
#subscription = Subscription.new
#plan = Plan.find_by id: params["plan_id"]
#business = Business.find_by id: params["business_id"]
end
# POST /subscriptions
def create
#subscription = Subscription.new subscription_params.merge(email: stripe_params["stripeEmail"],
card_token: stripe_params["stripeToken"])
raise "Please, check subscription errors" unless #subscription.valid?
#subscription.process_payment
#subscription.save
redirect_to #subscription, notice: 'Subscription was successfully created.'
rescue => e
flash[:error] = e.message
render :new
end
private
def stripe_params
params.permit :stripeEmail, :stripeToken
end
# Use callbacks to share common setup or constraints between actions.
def set_subscription
#subscription = Subscription.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def subscription_params
params.require(:subscription).permit(:plan_id, :business_id)
end
end
Subscription Model
class Subscription < ActiveRecord::Base
belongs_to :business
has_one :plan
def process_payment
customer = Stripe::Customer.create email: email,
card: card_token
Stripe::Charge.create customer: customer.id,
amount: plan.price * 100,
description: plan.name,
currency: 'usd'
end
end
Subscription View (new.html.erb)
<%= form_for #subscription do |f| %>
<% if #subscription.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#subscription.errors.count, "error") %>
prohibited this subscription from being saved:
</h2>
<ul>
<% #subscription.errors.full_messages.each do |message| %>
<li>
<%= message %>
</li>
<% end %>
</ul>
</div>
<% end %>
<h1><%= #business.name %></h1>
<div class="field">
<%= f.hidden_field :plan_id, value: #plan.id %>
</div>
<div class="field">
<%= f.hidden_field :business_id, value: #business.id %>
</div>
<div class="actions">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.application.secrets.stripe_publishable_key %>"
data-image="/img/documentation/checkout/marketplace.png"
data-name="Business Name"
data-description="<%= #plan.name %>"
data-amount="<%= #plan.price*100 %>">
</script>
</div>
<% end %>
Plan Model
class Plan < ActiveRecord::Base
belongs_to :subscription
end

Calling render only loads the view for an action, it doesn't run any of the logic in the method behind the action, which is why there is no #plan available when you render :new from the create action.

I figured out the issue was with my association between Plans and Subscriptions. I had Plans belongs_to Subscription when I should have had it the other way around.
class Subscription < ActiveRecord::Base
belongs_to :business
belongs_to :plan
...

Related

Only One Product Variant added to Cart, and It's always the first one added to my db

I'm setting up a simple online store with no user system - just a session following a cart.
Currently, I am able to select a Product (could be thought of as a product category), and within that product page select a ProductVariant (product_variant_id) belonging to it.
The problem is that when I add different product_variants, only the first one that is saved to the db is ever added to the cart. I can select the product_variants in the dropdown, but again only the first one added to the db in my record is added to the cart as an order_item.
My relevant Models:
Product
has_many :product_variants, dependent: :destroy
has_many :order_items, :through => :product_variants
ProductVariant
belongs_to :product
has_many :order_items, dependent: :destroy
OrderItem
belongs_to :order, optional: true
belongs_to :cart, optional: true
belongs_to :product_variant
belongs_to :product
Cart
has_many :order_items
And here is my product show page in show.html.erb with the option to select a product_variant
<%= link_to products_path do %>
<h4>Back to store gallery</h4>
<% end %>
<section class="flexbox">
<div class="flex">
<%= image_tag #product.image_1.show.url %>
</div>
<div class="flex">
<h2><%= #product.title %></h2>
<div class="product-description">
<h5>Description:</h5>
<p><%= #product.description %></p>
</div>
</div>
</section>
<%= simple_form_for [#product, #product_variant, #order_item] do |f| %>
<%= f.input :quantity %>
<%= f.button :submit, "Add to cart" %>
<% end %>
Product selection: <br>
<select name="product[product_variant_id]">
<% #product.product_variants.each do |product_variant| %>
<option value="<%= product_variant.id %>"><%= product_variant.item %>/<%= product_variant.size %>/<%= product_variant.color %>/<%= number_to_currency product_variant.price_in_dollars %></option>
<% end %>
</select>
Lastly, here is my order_items controller
class OrderItemsController < ApplicationController
def create
#product = Product.friendly.find(params[:product_id])
# find the product_variant
#product_variant = ProductVariant.find(params[:product_variant_id])
# quantity? - comes from the form data
#quantity = form_params[:quantity]
#current_cart.order_items.create(product: #product, product_variant: #product_variant, quantity: #quantity)
flash[:success] = "Thanks for adding to your cart"
redirect_to product_path(#product)
end
def update
#product = Product.friendly.find(params[:product_id])
#product_variant = ProductVariant.find(params[:product_variant_id])
#order_item = OrderItem.find(params[:id])
#order_item.update(form_params)
flash[:success] = "Thanks for updating your cart"
redirect_to cart_path
end
def destroy
#product = Product.friendly.find(params[:product_id])
#product_variant = ProductVariant.find(params[:product_variant_id])
#order_item = OrderItem.find(params[:id])
#order_item.delete
flash[:success] = "Product removed from cart"
redirect_to cart_path
end
def form_params
params.require(:order_item).permit(:quantity)
end
end
Thanks for any insight into what might be going wrong here, and please don't hesitate if you need me to provide any more relevant code, would be happy to.
Aaron

Twilio - phone number verification on Rails 5

I have done a phone number verification via Twilio, but I can't find a way how to implement a feature that sends pin code again (if user didn't received it) but also does it not more that 3 times (so users couldn't keep sending codes over and over again). Also, my code looks a bit anti-pattern, so feel free to suggest a better implementation.
When Devise User registers itself, I send him to create a Profile that belongs_to User. Profile holds all user info (and phone number). Here is the form:
<%= form_for #profile, remote: true do |f| %>
<%= f.label 'Your name' %><br />
<%= f.text_field :first_name, autofocus: true, class: 'form-control' %>
<%= f.label 'Phone number' %><br />
<%= f.text_field :phone, class: 'form-control' %>
</br>
<div id="hideAfterSubmit">
<%= f.submit 'Save', class: 'btn btn-lg btn-primary btn-block' %>
</div>
<% end %>
<div id="verify-pin">
<h3>Enter your PIN</h3>
<%= form_tag profiles_verify_path, remote: true do |f| %>
<div class="form-group">
<%= text_field_tag :pin %>
</div>
<%= submit_tag "Verify PIN", class: "btn btn-primary" %>
<% end %>
</div>
<div id="status-box" class="alert alert-success">
<p id="status-message">Status: Haven’t done anything yet</p>
</div>
#verify-pin and #status-box are display: none. I unhide them with responding create.js.erb.
Create action:
def create
if user_signed_in? && current_user.profile
redirect_to profile_path(current_user), notice: 'Jūs jau sukūrėte paskyrą'
else
#profile = Profile.new(profile_params)
#phone_number = params[:profile][:phone]
#profile.user_id = current_user.id
SmsTool.generate_pin
SmsTool.send_pin(phone_number: #phone_number)
if #profile.save
respond_to do |format|
format.js
end
else
render :new
end
end
end
So at this point profile been created, saved and pin code generated and sent to phone number that user just added.
SmsTool:
def self.generate_pin
##pin = rand(0000..9999).to_s.rjust(4, "0")
puts "#{##pin}, Generated"
end
def self.send_pin(phone_number:)
#client.messages.create(
from: ENV['TWILIO_PHONE_NUMBER'],
to: "+370#{phone_number}",
body: "Your pin is #{##pin}"
)
end
def self.verify(entered_pin)
puts "#{##pin}, pin #{entered_pin} entered"
if ##pin == entered_pin
Current.user.profile.update(verified: true)
else
return
end
end
And Profiles#verify :
def verify
SmsTool.verify(params[:pin])
#profile = current_user.profile
respond_to do |format|
format.js
end
if #profile.verified
redirect_to root_path, notice: 'Account created'
end
end
So what I dont like is SmsTool - as you see I use class variable - couldn't find another way. Also I created a separate Current module just to access Devise current_user object.. :
module Current
thread_mattr_accessor :user
end
ApplicationController:
around_action :set_current_user
def set_current_user
Current.user = current_user
yield
ensure
# to address the thread variable leak issues in Puma/Thin webserver
Current.user = nil
end
And as I mentioned above - I can't find a way how to implement a feature that sends pin code again (if user didn't received it).
And please - feel free to suggest elegant implementations.
p.s. this is my longest post yet. Sorry for that, but I think all info was needed to show you.
UPDATE:
So to resend pin was easy, I just added:
<div id="hiddenUnlessWrongPin">
<%= button_to "Re-send pin", action: "send_pin_again" %>
</div>
and action:
def send_pin_again
#phone_number = current_user.profile.phone
SmsTool.generate_pin
SmsTool.send_pin(phone_number: #phone_number)
end
But I still don't know how to stop sending pin if user already sent three of them. Only way I see is to make new row in db with integer value and increment it every time user sends pin. Is it the only way?
A good starting point would be to look at the Devise::Confirmable module which handles email confirmation. What I really like about it is that it models confirmations as a plain old resource.
I would try something similar but with a seperate model as it makes it really easy to add a time based limit.
class User < ApplicationRecord
has_one :profile
has_many :activations, through: :profiles
end
class Profile < ApplicationRecord
belongs_to :user
has_many :activations
end
# columns:
# - pin [int or string]
# - profile_id [int] - foreign_key
# - confirmed_at [datetime]
class Activation < ApplicationRecord
belongs_to :profile
has_one :user, through: :profile
delegate :phone_number, to: :profile
authenticate :resend_limit, if: :new_record?
authenticate :valid_pin, unless: :new_record?
attr_accessor :response_pin
after_initialize :set_random_pin!, if: :new_record?
def set_random_pin!
self.pin = rand(0000..9999).to_s.rjust(4, "0")
end
def resend_limit
if self.profile.activations.where(created_at: (1.day.ago..Time.now)).count >= 3
errors.add(:base, 'You have reached the maximum allow number of reminders!')
end
end
def valid_pin
unless response_pin.present? && response_pin == pin
errors.add(:response_pin, 'Incorrect pin number')
end
end
def send_sms!
// #todo add logic to send sms
end
end
Feel free to come up with a better name. Additionally this allows you to use plain old rails validations to handle the logic.
You can then CRUD it like any other resource:
devise_scope :user do
resources :activations, only: [:new, :create, :edit, :update]
end
class ActivationsController < ApplicationController
before_action :authenticate_user!
before_action :set_profile
before_action :set_activation, only: [:edit, :update]
# Form to resend a pin notification.
# GET /users/activations/new
def new
#activation = #profile.phone_authentication.new
end
# POST /users/activations/new
def create
#activation = #profile.phone_authentication.new
if #activation.save
#activation.send_sms!
redirect_to edit_user_phone_activations_path(#activation)
else
render :new
end
end
# Renders form where user enters the activation code
# GET /users/activations/:id/edit
def edit
end
# confirms the users entered the correct pin number.
# PATCH /users/activations/:id
def update
if #activation.update(update_params)
# cleans up
#profile.activations.where.not(id: #activation.id).destroy_all
redirect_to profile_path(#profile), success: 'Your account was activated'
else
render :edit
end
end
private
def update_params
params.require(:activation)
.permit(:response_pin)
.merge(confirmed_at: Time.now)
end
def set_profile
#profile = current_user.profile
end
def set_activation
#profile.activations.find(params[:id])
end
end
app/views/activations/new.html.erb:
<%= form_for(#activation) do |f| %>
<%= f.submit("Send activation to #{#activation.phone_number}") %>
<% end %>
No activation SMS? <%= link_ to "Resend", new_user_activation_path %>
app/views/activations/edit.html.erb:
<%= form_for(#activation) do |f| %>
<%= f.text_field :response_pin %>
<%= f.submit("Confirm") %>
<% end %>

Ruby on Rails: how to make a form for associated models (nested)

First of all I have this:
https://polar-scrubland-30279.herokuapp.com/ - my project which is deployed on heroku (Captain Obvious)
I've got projects and todos inside them.
For this moment I show all projects using this way:
------index.html.erb------
<%= render #projects %>
------_project.html.erb-----
<div class="project">
<div class="project-header">
<h2><%= project.title %></h2>
</div>
<div class="project-todos">
<% project.todos.all.each do |todo| %>
<p><%= check_box('tag', todo.__id__, {class: 'icheckbox_square-blue', checked: todo.isCompleted}) %> <%= content_tag :todotext, todo.text %></p>
<% end %>
</div>
</div>
And as you understand it doesn't allow me to change my todo's status when checkbox is checked. So that's why I need a form that will allow me to track all the checkboxes. Also I wanna make text-decoration: line-through when checkbox is pressed, but don't get how to.
Is there a way to creat a form which will satisfy my needs? Please can you help me, Any information will be appreciated.
ADDITIONAL INFORAMTION:
GitHub - https://github.com/NanoBreaker/taskmanager
project.rb
class Project < ActiveRecord::Base
has_many :todos
end
todo.rb
class Todo < ActiveRecord::Base
belongs_to :project
end
Lets start with the models:
class Project < ApplicationRecord
has_many :todos
accepts_nested_attributes_for :todos
end
class Todo < ApplicationRecord
belongs_to :project
end
accepts_nested_attributes_for lets you create or modify several nested Todo records at once when creating or updating a Project.
# will update 2 todos at once
#project.update(
todos_attributes: [ { id: 1, isComplete: true }, { id: 2, isComplete: false }]
)
We can use fields_for to create nested inputs for todos:
<%= f.form_for(#project) do |f| %>
<%= f.fields_for(:todos) do |tf| %>
<%= tf.check_box :isCompleted %>
<% end %>
<% end %>
This generates fields for todos nested under the key todos_attributes. We can whitelist them by using a hash key containing a array of permitted attributes.
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
def new
#project = Project.new
# this seeds the project with 3 empty tasks
# otherwise we don't have any inputs.
3.times { #project.todos.new }
end
def create
#project = Project.new(project_params)
if #project.save
# ...
else
# ...
end
end
def update
if #project.update(project_params)
# ...
else
# ...
end
end
private
def set_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project)
.permit(:foo, :bar,
todos_attributes: [:isCompleted, :text]
)
end
end
You can create a form for each project by creating a partial which uses a local instead of an instance variable:
# app/views/projects/_form.html.erb
<%= f.form_for(local_assigns[:project] || #project) do |f| %>
<%= f.fields_for(:todos) do |tf| %>
<%= tf.check_box :isCompleted %>
<% end %>
<% end %>
# app/views/projects/index.html.erb
<% #projects.each do |project| %>
<%= render partial: 'projects/form', project: project %>
<% end %>
You can reuse the same partial for the other views as well:
# app/views/projects/new.html.erb
<%= render partial: 'projects/form' %>
# app/views/projects/edit.html.erb
<%= render partial: 'projects/form' %>

Form Objects in Rails

The example code below is a contrived example of an attempt at a form object where it is probably overkill to utilize a form object. Nonetheless: it shows the issue I am having:
I have two models: a User and an Email:
# app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
# app/models/user.rb
class Email < ApplicationRecord
belongs_to :user
end
I want to create a form object which creates a user record, and then creates three associated email records.
Here are my form object classes:
# app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :name, :email_forms
validates :name, presence: true
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
puts "The Form is VALID!"
puts "I would proceed to create all the necessary objects by hand"
user = User.create(name: name)
email_forms.each do |email|
Email.create(user: user, email_text: email.email_text)
end
end
end
# app/forms/email_form.rb
class EmailForm
include ActiveModel::Model
attr_accessor :email_text, :user_id
validates :email_text, presence: true
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
puts "The Form is VALID!"
# DON'T THINK I WOULD PERSIST DATA HERE
# INSTEAD DO IT IN THE user_form
end
end
Notice: the validations on the form objects. A user_form is considered to be invalid if it's name attribute is blank, or if the email_text attribute is left blank for any of the email_form objects inside it's email_forms array.
For brevity: I will just be going through the new and create action of utilizing the user_form:
# app/controllers/user_controller.rb
class UsersController < ApplicationController
def new
#user_form = UserForm.new
#user_form.email_forms = [EmailForm.new, EmailForm.new, EmailForm.new]
end
def create
#user_form = UserForm.new(user_form_params)
if #user_form.save
redirect_to users_path, notice: 'User was successfully created.'
else
render :new
end
end
private
def user_form_params
params.require(:user_form).permit(:name, {email_forms: [:_destroy, :id, :email_text, :user_id]})
end
end
Lastly: the form itself:
# app/views/users/new.html.erb
<h1>New User</h1>
<%= render 'form', user_form: #user_form %>
<%= link_to 'Back', users_path %>
# app/views/users/_form.html.erb
<%= form_for(user_form, url: users_path) do |f| %>
<% if user_form.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user_form.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
# MESSY, but couldn't think of a better way to do this...
<% unique_index = 0 %>
<% user_form.email_forms.each do |email_form| %>
<div class="field">
<%= label_tag "user_form[email_forms][#{unique_index}][email_text]", "Email Text" %>
<%= text_field_tag "user_form[email_forms][#{unique_index}][email_text]" %>
</div>
<% unique_index += 1 %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The form does render:
And here is the form's html:
I go to submit the form. Here is the params hash:
Parameters: {"utf8"=>"✓", "authenticity_token"=>”abc123==", "user_form"=>{"name"=>"neil", "email_forms"=>{"0"=>{"email_text"=>"test_email_1"}, "1"=>{"email_text"=>"test_email_2"}, "2"=>{"email_text"=>""}}}, "commit"=>"Create User form"}
What should happen is the form should be re-rendered and nothing persisted because the form_object is invalid: All three associated emails must NOT be blank. However: the form_object thinks it is valid, and it blows up in the persist! method on the UserForm. It highlights the Email.create(user: user, email_text: email.email_text) line and says:
undefined method `email_text' for ["0", {"email_text"=>"test_email_1"}]:Array
Clearly there are a couple things going on: The nested validations appear to not be working, and I am having trouble rebuilding each of the emails from the params hash.
Resources I have already examined:
This Article seemed promising but I was having trouble getting it to work.
I have attempted an implementation with the virtus gem and the reform-rails gem. I have pending questions posted for both of those implementations as well: virtus attempt here and then reform-rails attempt here.
I have attempted plugging in accepts_nested_attributes, but was having trouble figuring out how to utilize that with a form object, as well as a nested form object (like in this code example). Part of the issue was that has_many and accepts_nested_attributes_for do not appear to be included in ActiveModel::Model.
Any guidance on getting this form object to do what is expected would be very much appreciated! Thanks!
Complete Answer
Models:
#app/models/user.rb
class User < ApplicationRecord
has_many :emails
end
#app/models/email.rb
class Email < ApplicationRecord
belongs_to :user
end
Controller:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user_form = UserForm.new
#user_form.emails = [EmailForm.new, EmailForm.new, EmailForm.new]
end
def create
#user_form = UserForm.new(user_form_params)
if #user_form.save
redirect_to users_path, notice: 'User was successfully created.'
else
render :new
end
end
private
def user_form_params
params.require(:user_form).permit(:name, {emails_attributes: [:email_text]})
end
end
Form Objects:
#app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :name, :emails
validates :name, presence: true
validate :all_emails_valid
def emails_attributes=(attributes)
#emails ||= []
attributes.each do |_int, email_params|
email = EmailForm.new(email_params)
#emails.push(email)
end
end
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
user = User.new(name: name)
new_emails = emails.map do |email_form|
Email.new(email_text: email_form.email_text)
end
user.emails = new_emails
user.save!
end
def all_emails_valid
emails.each do |email_form|
errors.add(:base, "Email Must Be Present") unless email_form.valid?
end
throw(:abort) if errors.any?
end
end
app/forms/email_form.rb
class EmailForm
include ActiveModel::Model
attr_accessor :email_text, :user_id
validates :email_text, presence: true
end
Views:
app/views/users/new.html.erb
<h1>New User</h1>
<%= render 'form', user_form: #user_form %>
<%= link_to 'Back', users_path %>
#app/views/users/_form.html.erb
<%= form_for(user_form, url: users_path) do |f| %>
<% if user_form.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user_form.errors.count, "error") %> prohibited this User from being saved:</h2>
<ul>
<% user_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.fields_for :emails do |email_form| %>
<div class="field">
<%= email_form.label :email_text %>
<%= email_form.text_field :email_text %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

splitting up the views of my stripe subscription details

I have stripe subscriptions on my site. yesterday i created a basic way for the user to view their payment history and cards used. i now want to break this up into two views so that the payment history is on one page and the card(s) used is on another page. I feel like i must be missing something but when i tried to do this nothing is showing on the page. I am pretty new to rails so the whole stripe subscriptions thing has been a bit of a challenge but getting there. This is the original code could someone offer some guidance as to the steps i need to follow. I tried literally splitting this into two different view file but that didn't work so i have gone back to where i was originally now!
subcriptions/show.html.erb
<h1>View your payment history and cards</h1>
<h4><%= #charges.data.length %> Charges! </h4>
<% #charges.data.each do |charge| %>
<%= charge.statement_description %>
£<%= charge.amount %>
<%= Time.at(charge.created).strftime("%d/%m/%y") %>
<% end %>
<h4><%= #charges.data.length %> Cards! </h4>
<% #cards.each do |card| %>
<%= card.brand %>
**** **** **** <%= card.last4 %>
<%= card.exp_month %>/<%= card.exp_year %>
<% end %>
subscriptions controller:
class SubscriptionsController < ApplicationController
def new
#subscription = Subscription.new
end
def create
# raise 'a'
#subscription = Subscription.new(params[:subscription].permit(:stripe_card_token))
#subscription.user = current_user
if #subscription.save_with_payment(params[:plan]) #(current_user)
redirect_to #subscription, :notice => "Thank you for subscribing!"
else
render :new
end
end
def destroy
end
def show
customer_token = current_user.subscription.try(:stripe_customer_token)
#charges = customer_token ? Stripe::Charge.all(customer: customer_token) : []
#cards = customer_token ? Stripe::Customer.retrieve(customer_token).cards : []
end
end
subscriptions model
class Subscription < ActiveRecord::Base
belongs_to :user
validates_presence_of :user_id #it should be always compulsary
# attr_accessible :plan
attr_accessor :stripe_card_token
def save_with_payment(plan)
if valid?
customer = Stripe::Customer.create(description: 'subscription', plan: plan, card: stripe_card_token)
self.stripe_customer_token = customer.id
save!
end
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
end
The most simple way to achieve it, is to create 2 methods in controller (for example payments and cards):
def payments
customer_token = current_user.subscription.try(:stripe_customer_token)
#charges = customer_token ? Stripe::Charge.all(customer: customer_token) : []
end
def cards
customer_token = current_user.subscription.try(:stripe_customer_token)
#cards = customer_token ? Stripe::Customer.retrieve(customer_token).cards : []
end
create 2 views for these (payments.html.erb and cards.html.erb under /views/subscriptions/ directory):
payments.html.erb:
<h1>View your payment history</h1>
<h4><%= #charges.data.length %> Charges! </h4>
<% #charges.data.each do |charge| %>
<%= charge.statement_description %>
£<%= charge.amount %>
<%= Time.at(charge.created).strftime("%d/%m/%y") %>
<% end %>
cards.html.erb:
<h1>View your cards</h1>
<h4><%= #charges.data.length %> Cards! </h4>
<% #cards.each do |card| %>
<%= card.brand %>
**** **** **** <%= card.last4 %>
<%= card.exp_month %>/<%= card.exp_year %>
<% end %>
and edit routes by:
resources :subscriptions do
get '/payments', to: 'subscriptions#payments' # or get 'subscriptions/payments', to: 'subscriptions#payments' (depending on which link you would like to see)
get '/cards', to: 'subscriptions#cards'
end
This would be pretty much it. Run rake routes to see generated routes to use it correctly and you're good to go. Please check for spelling mistakes in case you'll copy something - not sure if I didn't make any.

Resources