Get Stripe charge information rails 5 create order - ruby

So I'm implementing Stripe and users are able to purchase successfully, however, I would like to get the charge information, last 4 card numbers, card type etc so I can generate receipts using https://github.com/excid3/receipts.
Here is what I have so far:
PaymentsController
class PaymentsController < ApplicationController
before_action :authenticate_user!
def create
token = params[:stripeToken]
#course = Course.find(params[:course_id])
#user = current_user
begin
charge = Stripe::Charge.create(
amount: (#course.price*100).to_i,
currency: "gbp",
source: token,
description: params[:stripeEmail],
receipt_email: params[:stripeEmail]
)
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
Amount: #course.price
)
end
flash[:success] = "Your payment was processed successfully"
rescue Stripe::CardError => e
body = e.json_body
err = body[:error]
flash[:error] = "Unfortunately, there was an error processing your payment: #{err[:message]}"
end
redirect_to course_path(#course)
end
end
OrdersController
class OrdersController < ApplicationController
layout proc { user_signed_in? ? "dashboard" : "application" }
before_action :authenticate_user!
def index
#orders = Order.includes(:course).all
end
def show
#order = Order.find(params[:id])
respond_to do |format|
format.pdf {
send_data #order.receipt.render,
filename: "#{#order.created_at.strftime("%Y-%m-%d")}-aurameir-courses-receipt.pdf",
type: "application/pdf",
disposition: :inline
}
end
end
def create
end
def destroy
end
end
Order.rb
class Order < ApplicationRecord
belongs_to :course
belongs_to :user
validates :stripe_id, uniqueness: true
def receipt
Receipts::Receipt.new(
id: id,
subheading: "RECEIPT FOR CHARGE #%{id}",
product: "####",
company: {
name: "####",
address: "####",
email: "####",
logo: "####"
},
line_items: [
["Date", created_at.to_s],
["Account Billed", "#{user.full_name} (#{user.email})"],
["Product", "####"],
["Amount", "£#{amount / 100}.00"],
["Charged to", "#{card_type} (**** **** **** #{card_last4})"],
["Transaction ID", uuid]
],
font: {
normal: Rails.root.join('app/assets/fonts-converted/font-files/AvenirBook.ttf')
}
)
end
end
schema.rb
create_table "orders", force: :cascade do |t|
t.integer "user_id"
t.integer "course_id"
t.integer "stripe_id"
t.integer "amount"
t.string "card_last4"
t.string "card_type"
t.integer "card_exp_month"
t.integer "card_exp_year"
t.string "uuid"
t.index ["course_id"], name: "index_orders_on_course_id"
t.index ["user_id"], name: "index_orders_on_user_id"
end
How would I go about getting the charge information?

All the information you need is in the charge object you created.
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
amount: #course.price,
card_last4: charge.source.last4,
card_type: charge.source.brand,
card_exp_month: charge.source.exp_month,
card_exp_year: charge.source.exp_year
)
end
See https://stripe.com/docs/api/ruby#charge_object for all the information available to you about a charge.

I guess you are not storing the Stripe Charge ID anywhere on successful payment.
My suggestion, store the charge ID in your Order record
if charge.paid
Order.create(
course_id: #course.id,
user_id: #user.id,
amount: #course.price,
stripe_charge_id: charge.id
)
end
In your receipt method you can fetch the stripe charge as follows:
def receipt
stripe_charge = Stripe::Charge.retrieve(stripe_charge_id)
...
end
The stripe_charge objects contains all the information and you can use whatever data you need.
Hope this helped.

Related

Rails Paperclip - Duplicating the attachment file name in another field

I've got the following table:
create_table "documents", force: true do |t|
t.string "title"
t.integer "subject_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "attachment_file_name"
t.string "attachment_content_type"
t.integer "attachment_file_size"
t.datetime "attachment_updated_at"
end
Whenever I upload a file (using Paperclip), I want to duplicate the param of 'attachment_file_name' to 'title'.
This app is an API, but I'm using a debugs_controller to test it.
DebugsController
class DebugsController < ApplicationController
def index
#document = Document.new
#documents = Document.all
#subject = Subject.new
end
end
debugs/index.html.erb
<form action="http://0.0.0.0:3000/documents" method="POST" enctype="multipart/form-data">
<input name="document[title]" type="text" placeholder="doc naam">
<input name='document[attachment]' type="file">
<input name="document[subject_id]" type="text" placeholder="Subject id">
<input type="submit">
</form>
DocumentsController
class DocumentsController < ApplicationController
before_action :set_document, only: [:show, :update, :destroy]
skip_before_action :verify_authenticity_token
respond_to :json
def index
#documents = Document.all
end
def new
#document = Document.new
#documents = Document.all
end
def show
end
def create
#document = Document.new(document_params)
#document.title = params[:attachment].original_filename
if #document.save
respond_with(#document, status: :created)
else
respond_with(#document, status: 403)
end
end
def update
if #document.update(document_params)
respond_with(#document)
else
respond_with(#document.errors, status: :unprocessable_entity)
end
end
def destroy
#document.destroy
respond_with(#document, status: :destroyed)
end
private
def set_document
#document = Document.find(params[:id])
end
def document_params
params.require(:document).permit(:title, :attachment, :subject_id)
end
end
Document.rb
class Document < ActiveRecord::Base
belongs_to :subject
has_many :notes
has_attached_file :attachment, url: '/system/:attachment/:id_partition/:basename.:extension'
validates_attachment :attachment, presence: {
message: 'You have to upload a file!' }, content_type: {
content_type: %w( application/pdf ), message: 'PDF files only.' }, size: {
in: 0..10.megabytes, message: 'The maximum file-size is 10MB.' }
validates :subject_id, presence: { message: 'Assign your document to a case!' }
end
This outputs 'undefined method `original_filename' for nil:NilClass' for me.
Params:
{"document"=>{"title"=>"",
"attachment"=>#<ActionDispatch::Http::UploadedFile:0x007fbcea87c518 #tempfile=#<Tempfile:/var/folders/sy/9v_t59x974qg_m2nvmcyvkjr0000gn/T/RackMultipart20141202-14285-z5aj46>,
#original_filename="Teamsweet.pdf",
#content_type="application/pdf",
#headers="Content-Disposition: form-data; name=\"document[attachment]\"; filename=\"Teamsweet.pdf\"\r\nContent-Type: application/pdf\r\n">,
"subject_id"=>"1"},
"format"=>:json}
Does anyone know how I can duplicate the contents of the 'attachment_file_name' to the 'title' field of Documents? Also; is it possible to remove the extention of the uploaded file in the process of duplicating the file name?
You can do that in the model instead of in the controller.
class Document < ActiveRecord::Base
before_save :set_title
def set_title
self.title = self.attachment_file_name
end
...
end

How can I combine two Rails 4 where queries that query either side of a boolean condition?

Question:
Is there a way to combine the following two queries (including the assignments) into one query? I'm not sure how much time I'd really save. In other words, I'm not sure if it is worth it, but I'd like to be as efficient as possible.
#contacts = #something.user.contacts.where.not(other_user_id: 0)
#user_contacts = #something.user.contacts.where(other_user_id: 0)
More context:
Here is my contacts table from schema.rb:
create_table "contacts", force: true do |t|
t.string "name"
t.string "email"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "profile_picture"
t.string "phone_number"
t.integer "other_user_id"
end
And here is the important stuff from the users table:
create_table "users", force: true do |t|
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
...
t.string "first_name"
t.string "second_name"
end
And here is the pertinent information of the models:
class Contact < ActiveRecord::Base
belongs_to :user
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :name, presence: true
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }
validates :user_id, presence: true
def get_email_from_name
self.email
end
end
[...]
class User < ActiveRecord::Base
has_many :contacts
has_many :relationships,
foreign_key: 'follower_id',
dependent: :destroy
has_many :reverse_relationships,
foreign_key: 'followed_id',
class_name: 'Relationship',
dependent: :destroy
has_many :commitments,
class_name: 'Commitment',
dependent: :destroy
has_many :followers,
through: :reverse_relationships
has_many :followed_users,
through: :relationships,
source: :followed
[...]
before_save { email.downcase! || email }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email,
presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
[...]
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
if create_contact?(self, id, other_user.id)
create_contact(other_user.name,
other_user.email,
self.id,
other_user.id,
other_user.gravatar_url)
elsif create_contact?(other_user, other_user.id, id)
create_contact(name, email, other_user.id, id, gravatar_url)
end
end
def create_contact?(user, followed_id, follower_id)
user.admin? && ! Relationship.where(followed_id: followed_id, follower_id: follower_id).empty?
end
def create_contact(name, email, user_id, other_user_id, profile_picture)
Contact.create!(name: name,
email: email,
user_id: user_id,
other_user_id: other_user_id,
profile_picture: profile_picture)
end
def unfollow!(other_user)
relationships.find_by(followed_id: other_user.id).destroy
Contact.destroy_all(user_id: self.id, other_user_id: other_user.id)
end
[...]
end
The other contacts that may not have an account with the website (yet), and I'd like to distinguish that in the view. So I keep track of which contacts I import through Google contacts using the omniauth gem. For the other contacts, I gather the other users that are friends with current_user.
Goal:
I'd like to save these two record collections to use in the view, but I'd like to avoid looking through all the user's contacts twice, checking the same column in each pass-through.
Any ideas? I'm sure there are lots of ways this can be done, and I'd like to learn as much as I can from this! Thanks in advance!
You can use Array#partition to split up the array in memory, after the query was performed.
#user_contacts, #contacts = #something.user.contacts.partition{|u| other.id == 0 }
However checking for this magic 0 id is smelly. You should try to get rid of such special cases whenever possible.
It is not the best solution, but if you think partition hard to understand, it can be an optional.
#user_contacts, #users = [], []
#something.user.contacts.each do |record|
if record.other_user_id == 0
#user_contacts << record
else
#users << record
end
end

Ruby on Rails : Tricky Many to Many relationship does not work

I am designing a "Lists" mapping feature in my application for transcoding purposes.
So that my mappins_list object points to a source_list object and a target_list object, both being of an instance values_list class.
The design looks classical, but it does not behave as expected:
<td><%= link_to #mappings_list.source_list.name, #mappings_list.source_list%>
raises a
undefined method `source_list' for #<ActiveRecord::Relation::ActiveRecord_Relation_MappingsList:0x00000004217718>
in the index view.
(note that one record was crated with correct attributes, it should be displayed there)
Here is the code:
# == Schema Information
#
# Table name: values_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# table_name :string(255)
# created_at :datetime
# updated_at :datetime
# software_id :integer
# software_name :string(255)
#
class ValuesList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :code, length: { maximum: 100 }
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :software, :class_name => "Parameter", :foreign_key => "software_id" # helps retrieving the software name
has_many :values
has_many :mappings_lists
### private functions definitions
private
### before filters
def set_code
self.code = name.gsub(/[^0-9A-Za-z]/, '_').upcase
end
end
.
# == Schema Information
#
# Table name: mappings_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# source_list_id :integer
# target_list_id :integer
# created_at :datetime
# updated_at :datetime
#
class MappingsList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :source_list, :class_name => "ValuesList", :foreign_key => "source_list_id" # helps retrieving the source list name
belongs_to :target_list, :class_name => "ValuesList", :foreign_key => "target_list_id" # helps retrieving the target list name
has_many :mappings
### private functions definitions
private
### before filters
def set_code
self.code = "#{source_list.code}_TO_#{target_list.code}"
end
end
routes contains this:
resources :values_lists do
resources :values
resources :mappings_lists
end
The controller is here:
class MappingsListsController < ApplicationController
# Check for active session
before_action :signed_in_user
# Retrieve current current mapping
before_action :set_mappings_list, only: [:show, :edit, :update, :destroy]
# Retrieve all lists of values
before_action :set_values_lists
# GET /mappings_list
# GET /mappings_list.json
def index
#mappings_list = MappingsList.pgnd(current_playground).order("name")
end
# GET /mappings_list/1
# GET /mappings_list/1.json
def show
### Retrieved by Callback function
end
# GET /mappings_list/new
def new
#mappings_list = MappingsList.new
end
# GET /mappings_list/1/edit
def edit
### Retrieved by Callback function
end
# POST /mappings_list
# POST /mappings_list.json
def create
#mappings_list = MappingsList.new(mappings_list_params)
#mappings_list.updated_by = current_user.login
#mappings_list.created_by = current_user.login
#mappings_list.playground_id = current_user.current_playground_id
#mappings_list.owner_id = current_user.id
respond_to do |format|
if #mappings_list.save
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully created.' }
format.json { render action: 'show', status: :created, location: #mappings_list }
else
format.html { render action: 'new' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /mappings_list/1
# PATCH/PUT /mappings_list/1.json
def update
### Retrieved by Callback function
#mappings_list.updated_by = current_user.login
respond_to do |format|
if #mappings_list.update(mappings_list_params)
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /mappings_list/1
# DELETE /mappings_list/1.json
def destroy
### Retrieved by Callback function
#mappings_list.destroy
respond_to do |format|
format.html { redirect_to mappings_lists_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
# Check for active session
def signed_in_user
redirect_to signin_url, notice: "You must log in to access this page." unless signed_in?
end
def set_mappings_list
#mappings_list = MappingsList.pgnd(current_playground).find(params[:id])
end
# retrieve the list of values lists
def set_values_lists
#lists_of_values = ValuesList.all
end
# Never trust mappings from the scary internet, only allow the white list through.
def mappings_list_params
params.require(:mappings_list).permit(:name, :description, :source_list_id, :target_list_id)
end
end
Would the double reference to values_list turn my application into trouble ?
Thanks for your help,
Best regards,
Fred
In the class MappingsList < ActiveRecord::Base model
you have MappingList belonging to source_list.
which I believe is backwards:
class Order < ActiveRecord::Base
belongs_to :customer
end
#order = #customer.orders
OK, I got it !!!
In the index view, I cannot refer to one instance variable such as #mappings_list as I work on a list of instances.
The code works fine with :
<td><%= link_to mappings_list.source_list.name, mappings_list.source_list%>
Being a beginner at RoR, I hope my interpretation is right ...
Thanks for your help,
Best regards,
Fred

Rails 4 ActiveModel::MissingAttributeError in OrdersController#create

I m trying to build a shopping cart for a website. I have the cart working so you can add to the cart. The problem I am having is when I try and checkout items in the cart and try to submit my order. I am getting the following error:
ActiveModel::MissingAttributeError in OrdersController#create
along with
can't write unknown attribute `order_id'
The problem is highlighting this piece of code in my orders_controller.rb file
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id]) session[:cart_id] = nil
I just cant seem to fix this error.
Below is the create method in my orders_controller.rb file
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to store_url,
notice: 'Thank you for your order.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
my migration file
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order, :reference
end
end
my order.rb model
class Order < ActiveRecord::Base
has_many :line_items, dependent: :destroy
validates :name, :address, :email, presence: true
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :pay_type, inclusion: PAYMENT_TYPES
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
migration order table
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.string :name
t.text :address
t.string :email
t.string :pay_type
t.timestamps
end
end
end
Ok, I think I see the problem. Your migration for orders in line items probably didn't create the order_id column you expected, it probably created an orders column or something.
Verify that this is the case in the database. If so, undo your previous migration and try this instead:
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order_id, :int
end
end
If not, please respond to this answer.

Rails ActiveRecord Ignoring Params and Saving Nil Data

This is stumping me; For some reason the db is saving the record with nil fields instead of my params. Can anyone help me understand why ActiveRecord isn't using my params?
db migration:
class CreateRoutes < ActiveRecord::Migration
def change
create_table :routes do |t|
t.integer :user_id
t.string :start_address
t.string :end_address
t.text :waypoints
t.text :schedule
t.integer :duration
t.timestamps
end
add_index :routes, :user_id
end
end
route.rb:
class Route < ActiveRecord::Base
attr_accessor :start_address, :end_address, :waypoints, :schedule, :duration
belongs_to :user
#serialize :waypoints, :schedule
validates :user_id, presence: true
validates :start_address, presence: true
validates :end_address, presence: true
validates :schedule, presence: true
validates :duration, presence: true, numericality: { only_integer: true, greater_than: 0 }
end
routes_controller.rb:
class RoutesController < ApplicationController
.
.
.
def create
logger.debug "\n\n*** #{params[:route]} ***"
#route = current_user.routes.build(params[:route])
logger.debug "*** The route is #{#route.inspect} ***\n\n"
if #route.save
flash[:success] = "Route saved!"
redirect_to user_path(current_user)
else
render 'new'
end
end
.
.
.
end
logger output:
*** {"start_address"=>"123 Sample St.", "end_address"=>"321 Elpmas St.", "waypoints"=>"None", "schedule"=>"Mondays", "duration"=>"15"} ***
*** The route is #<Route id: nil, user_id: 1, start_address: nil, end_address: nil, waypoints: nil, schedule: nil, duration: nil, created_at: nil, updated_at: nil> ***
The attr_accessors will overwrite the accessors generated by ActiveRecord, causing them to not be persisted in the DB--they'll be like plain old Ruby properties/members instead of the meta-programmed magic of ActiveRecord.
DB properties (persistent properties) can have things like attr_accessible, though.

Resources