Skip to content

Instantly share code, notes, and snippets.

@mankind
Created October 11, 2013 13:53
Show Gist options
  • Save mankind/6935000 to your computer and use it in GitHub Desktop.
Save mankind/6935000 to your computer and use it in GitHub Desktop.
Files with debug code and comments explaining stuff while building my store rails app
class Ability
include CanCan::Ability
def initialize(user)
#to ensure user object is not nil when no user object is passed in
user ||= User.new
can :manage, User, :id => user.id
#can :manage, User do |user|
#this exposes the destroy and edit links for all users including users not yet signed_in
#user.id == user.id
#this hid the destroy and edit links for all users including signed_in user
#user == user
#user.id == :user_id
#end
can :manage, Product do | product |
#both versions are working
product.try(:user_id) == user.id &&
#product.user == user
product.try(:user).try(:seller) == true
end
end
end
class Order < ActiveRecord::Base
validates :order_items, presence: true
has_many :payments
has_many :order_items, dependent: :destroy
belongs_to :user
belongs_to :address
attr_accessor :stripe_card_token
after_save :update_payment
def total
@b = order_items.map(&:subtotal).sum
@c = (@b*100).to_i
Rails.logger.debug("total method in Order model has total of : #{@c.inspect}")
end
#ability to add lineitems ie items in the cart to order
#add_orders_items_from_cart(cart) says for item transfered from the cart to the order we need to do 3 things
#first, using cart.order_items.each, we take every order_items from that cart and "give them the name" item
#secondly, #set the cart_id to nil to prevent the item being called when we destroy the cart.
#thirdly, using << item we add the item itself to the order_items collection for the order
def add_orders_items_from_cart(cart)
cart.order_items.each do |item|
#item.cart_id = nil
Rails.logger.debug("item is: #{item.inspect}")
order_items << item
total
end
end
def create_customer(params)
@payment_info = Payment.new
@payment_info.create_customer_in_stripe(params)
@payment_info.order = self
Rails.logger.debug("create_customer has: #{params.inspect}")
Rails.logger.debug("user id is: #{params[:user_id].inspect}")
Rails.logger.debug("stripe token is: #{params[:token].inspect}")
#Rails.logger.debug("create_customer has: #{@payment_info.order.inspect}")
end
def me(params)
Rails.logger.debug("me is: #{params.inspect}")
end
def update_payment
@payment_info.order_id = self.id
@payment_info.save!
d = @c
@payment_info.charge_customer(d)
Rails.logger.debug("payment order id is: #{@payment_info.order_id.inspect}")
Rails.logger.debug("update_payment method in Order model has total of : #{@c.inspect}")
end
end
class OrderItemsController < ApplicationController
before_action :load_current_cart, only: [:create]
before_action :set_order_item, only: [:show, :edit, :destroy]
respond_to :html, :json
#we don't need the :index, :show and :new actions, so to be removed
def index
@order_items = OrderItem.all
respond_with @order_items
end
def show
end
#def new
# @order_item = OrderItem.new
#end
def edit
end
# since the form that gets created by the 'Add to cart' in products/index uses a button_to helper,
# and button_helper doesn’t nest data in an order_item hash, it simply submits to the URL provided.
# we will need to change this @order_item = OrderItem.new(order_item_params)
#also, we build the order_item through the relationship with the order
# with find_or_initialize, we want to look first look for order_item with the matching product_id first
# += increases the product quantity by 1 if in the order & If it’s not in the order, add it to the order with quantity 1
# for += to work as described above, the default value for quantity must be set to zero in the database
def create
#@order_item = OrderItem.new(product_id: params[:product_id], cart_id: @cart_id)
#@order_item = @cart.order_items.new(product_id: params[:product_id], quantity: 1)
#product = Product.find(params[:product_id])
#@order_item = @cart.order_items.find_or_initialize_by(product_id: product.id)
Rails.logger.debug("My object: #{@cart.inspect}")
Rails.logger.debug("My object: #{@cart.user_id.inspect}")
Rails.logger.debug("The Product id is : #{params[:product_id].inspect}")
@order_item = @cart.order_items.find_or_initialize_by(product_id: params[:product_id])
@order_item.quantity += 1
Rails.logger.debug("The order_item contains : #{@order_item.inspect}")
if @order_item.save
redirect_to @cart, {notice: 'Successfully added product to cart.' }
else
render 'new'
end
end
#instead of giving users an error message when they change quantity to zero, we just delete that order.
def update
@order_item = OrderItem.find(params[:id])
if params[:order_item][:quantity].to_i == 0
@order_item.destroy
redirect_to products_path, {notice: 'Item was deleted from your cart.' }
elsif @order_item.update(order_item_params)
redirect_to @order_item.cart, {notice: 'successfully updated the order item.' }
else
render 'edit'
end
end
def destroy
@order_item.destroy
#redirect_to products_path
redirect_to @order_item.cart
#redirect_to cart_path
end
private
def set_order_item
@order_item = OrderItem.find(params[:id])
end
def order_item_params
params.require(:order_item).permit(:order_id, :product_id, :quantity)
end
=begin
# tries to find the Order with the :order_id in the session
# raise an ActiveRecord::RecordNotFound error If the session hash does not have a key named :order_id
#The rescue statement watches for this error and, if it occurs, creates a new Order
def load_order
begin
@order = Order.find(session[:order_id])
rescue ActiveRecord::RecordNotFound
@order = Order.create(status: 'unsubmitted')
session([:order_id]) = @order.id
end
=end
end
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
before_action :load_current_cart, only: [:new, :create]
#before_action :authenticate_user!
#skips the authentication for the mentioned methods
#skip_before_action :authenticate_user!, only: [:new, :create]
respond_to :html, :json
def index
@orders = Order.all
respond_with @orders
end
def show
end
def edit
end
def new
@order = Order.new
@order.user_id = current_user.id
end
def create
#@order = Order.new(order_params)
@order = Order.new(user_id: current_user.id, address_id: current_user.addresses(&:id))
@order.add_orders_items_from_cart(@cart)
a = @order.create_customer(:token => params[:stripe_card_token], user_id: current_user.id)
b = params[:stripe_card_token]
Rails.logger.debug(" for a the token id is : #{a}")
Rails.logger.debug(" b id is : #{b}")
#Rails.logger.debug(" order has: #{@order.order_items.inspect}")
@order.status = "completed"
Rails.logger.debug("Cart has: #{@cart.order_items.inspect}")
if @order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
#redirect_to @order
redirect_to confirm_order_path(@order), notice: 'Order was successfully updated.'
else
render 'new'
end
end
def update
if @order.update(order_params)
else
render 'edit'
end
end
def destroy
@order.destroy
redirect_to products_path
end
def confirm
end
private
def set_order
@order = Order.find(params[:id])
@address = Address.find_by(id: @order.user_id)
# @addresses = @order.user.addresses
@addresses = current_user.addresses
respond_with @order
end
def order_params
params.require(:order).permit(:user_id, :address_id, :status)
end
end
class Payment < ActiveRecord::Base
belongs_to :user
belongs_to :order
def create_customer_in_stripe(params)
#if valid?
#self.order_id = params[:order_id]
my_user = User.find(params[:user_id])
self.user = my_user
if self.user.stripe_card_token.blank?
user_email = self.user.email
customer = Stripe::Customer.create(email: user_email, card: params[:token])
Rails.logger.debug("customer object has: #{customer.inspect}")
Rails.logger.debug("cards object has: #{customer.cards.data.inspect}")
Rails.logger.debug("first cards object has: #{customer.cards.first.inspect}")
Rails.logger.debug("last4 from first cards object has: #{customer.cards.first.last4.inspect}")
Rails.logger.debug("last4 from card data object has: #{customer.cards.data[0].last4.inspect}")
=begin
self.user.stripe_card_token = customer.id
card = customer.cards.first
#self.card_last4 = card["last4"]
self.card_last4 = card.last4
#self.card_type = card["type"]
self.card_type = card.type
self.card_exp_month = card["exp_month"]
self.card_exp_year = card["exp_year"]
=end
card = customer.cards.data
self.last4 = card[0].last4
self.user.save
end
self.save!
#end closes the valid line
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
def charge_customer(amount)
a = amount
charge = Stripe::Charge.create(
#amount: (self.order.total*100).to_i,
amount: a,
currency: "usd",
customer: self.user.stripe_card_token,
description: "Charges for your order"
)
end
handle_asynchronously :charge_customer
end
class Product < ActiveRecord::Base
mount_uploader :image_url, ImageUrlUploader
has_many :order_items
belongs_to :user
#validates :user_id, :inclusion => { :in => [true, false] }
validates :price, presence: true, numericality: true
validates :stock, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validate :user_should_be_a_seller
before_destroy :ensure_not_referenced_by_any_line_item
#removes any dollar signs. Then, with the value changed, super invokes the original price= method.
def price=(input)
input.delete!("$")
super
end
private
def user_should_be_a_seller
if self.user.seller == false
errors.add('to create or manage a product, you must be a seller')
end
end
#ensures that there are no line items referencing this product
#A base error adds an error to the base object instead of any particular attribute
#that is adds the error to something like an exact duplicate of the existing record,
#where the problem wasn't tied to any specific field but rather to the record as a whole
def ensure_not_referenced_by_any_line_item
if line_items.empty?
return true
else
#errors[:base] << "Error message" #this an alternative way
errors.add(:base, 'An line-item or A customer has an item in the cart')
return false
end
end
end
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, except: [:index, :show]
load_and_authorize_resource only: [ :create, :edit, :destroy]
respond_to :html, :json
def index
@products = Product.all
respond_with @products
end
def show
end
def new
@product = Product.new
end
def edit
end
def create
@user = User.find_by(id: current_user.id)
@product = @user.products.build(product_params)
#old working code used when we didn't association to user
#@product = Product.new(product_params)
if @product.save
redirect_to products_path, {notice: 'Product was successfully created.' }
else
#render 'new'
render action: 'new'
end
end
def update
if @product.update(product_params)
redirect_to @product, {notice: 'Product was successfully updated.'}
#redirect_to product_path, notice: 'Product was successfully updated.'
else
render action: 'edit'
end
end
def destroy
@product.destroy
redirect_to products_path
end
private
def set_product
@product = Product.find(params[:id])
#@product = Product.find_by(id: params[:id])
end
# note that :remote_image_url_url refers to us appending :remote_ before :image_url db field
#and adding _url after :image_url db field to allow for carrierwave's remote upload
def product_params
params.require(:product).permit(:title, :price, :stock, :description, :image_url, :user_id, :remote_image_url_url)
end
end
class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
before_filter :authenticate_user!, except: [:new, :create]
load_and_authorize_resource only: [:index, :edit, :destroy]
respond_to :html, :json
def index
@users = User.all
respond_with @users
end
def show
end
def edit
#@user = User.find(params[:id])
#respond_with @user
end
def new
@user = User.new
end
#load_current_cart is called to transfer cart from guest to signed_in user
#load_current_cart is defined in ApplicationController
def create
@user = User.new(user_params)
if @user.save
sign_in :user, @user #immediately signs in newly registerd user
load_current_cart if session[:guest_user_id] != nil
#current_user.move_guest_cart_to_user(@user) #if current_user && current_user.guest?
redirect_to @user, {notice: 'User was created'}
else
render 'new'
end
end
def update
# required for settings form to submit when password is left blank
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
end
if @user.update(user_params)
#After updating user, we reset Current_User and CanCan's Current Ability
@current_ability = nil
@current_user = nil
# Sign in the user by passing validation in case his password changed
sign_in :user, @user, :bypass => true
redirect_to @user, {notice: 'Your user details were updated'}
else
render 'edit'
end
end
def destroy
@user.destroy
redirect_to users_path, {notice: 'A user was removed'}
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
<div class="row">
<%= form_for @order do |f| %>
<% if @order.errors.any? %>
<% @order.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
<fieldset>
<%= debug @order %>
<%= debug current_user.addresses %>
<div class="col-lg-8">
<div class="form-group">
<label for="address">Add an address</label>
<div class="form-control"><%= f.select :address_id, current_user.addresses.collect{|a| [a.to_s, a.id]} %></div>
<%= link_to 'Add an Address', new_address_path %>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<% if @order.user.stripe_card_token.present? %>
Credit card has been provided. We will charge the card we have by the order total
<% else %>
<!-- <%= render 'stripe_checkout_form' %> -->
<%= render 'stripejs_form' %>
<% end %>
</div>
</div>
<div class="col-lg-8">
<div class="btn btn-primary">
<%= f.submit "Complete your Order" %>
</div>
</div>
</fieldset>
<% end %>
</div>
<%= @session %>
<%= @cart.inspect %><br/>
<%= @cart.id.inspect %>
<div> <%= render "cart" %></div>
<div class="row">
<%= form_for @order_item do |f| %>
<% if @order_item.errors.any? %>
<% @order_item.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
<fieldset>
<!-- this fields are auto-created
<div class=col-lg-8>
<div class="form-group">
<label class="control-label"> <%= f.label :product_id %></label>
<div class="form-control"><% f.number_field :product_id %> </div>
</div>
</div>
<div class=col-lg-8>
<div class="form-group">
<label class="control-label"> <%= f.label :order_id %></label>
<div class="form-control"><% f.number_field :order_id %> </div>
</div>
</div>
-->
<div class=col-lg-8>
<div class="form-group">
<label class="control-label"> <%= f.label :quantity %></label>
<div class="form-control"><%= f.number_field :quantity %> </div>
</div>
</div>
<div class=col-lg-8>
<div class="btn btn-primary">
<%= f.submit %>
</div>
</div>
</fieldset>
<% end %>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment