Skip to content

Instantly share code, notes, and snippets.

@rob0t7
Created February 14, 2017 21:13
Show Gist options
  • Save rob0t7/43bef56ece6d1e04c5865177a7ab8cb8 to your computer and use it in GitHub Desktop.
Save rob0t7/43bef56ece6d1e04c5865177a7ab8cb8 to your computer and use it in GitHub Desktop.
AR Breakout
require 'pry'
require 'active_record'
ActiveRecord::Base.logger = Logger.new(STDOUT)
# Objects that we will be using
class Customer < ActiveRecord::Base
has_many :invoices
validates :first_name, presence: true
validates :last_name, presence: true
validates :email, presence: true,
uniqueness: true,
format: /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
before_validation { self.email = email.downcase }
def self.find_by_email(email)
find_by(email: email.downcase)
end
def name
"#{first_name} #{last_name}"
end
end
class Product < ActiveRecord::Base
#has_and_belongs_to_many :invoices #for pure many-to-many relationship
has_many :invoice_items
has_many :invoices, through: :invoice_items # many-to-many relations using an itermediate table
validates :name, presence: true
validates :description, presence: true
validates :price_cents, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :inventory, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
end
class Invoice < ActiveRecord::Base
belongs_to :customer
belongs_to :shipping_address, class_name: 'Address'
belongs_to :billing_address, class_name: 'Address'
has_many :invoice_items, autosave: true
has_many :products, through: :invoice_items # many-to-many relations using an itermediate table
def total_price
invoice_items.reduce(0) { |total, x| total + x.price_cents }
end
end
class InvoiceItem < ActiveRecord::Base
belongs_to :invoice
belongs_to :product
after_create :update_inventory
private
def update_inventory
product_inventory = product.inventory
product.update(inventory: product_inventory - quantity)
end
end
class Address < ActiveRecord::Base
belongs_to :customer
end
puts "Establishing connection to Database"
ActiveRecord::Base.establish_connection(
adapter: 'postgresql',
database: 'ar_breakout',
username: 'rob',
encoding: 'unicode'
)
puts "Creating DB Schema"
ActiveRecord::Schema.define do
drop_table :customers if ActiveRecord::Base.connection.table_exists?(:customers)
drop_table :invoices if ActiveRecord::Base.connection.table_exists?(:invoices)
drop_table :invoice_items if ActiveRecord::Base.connection.table_exists?(:invoice_items)
drop_table :products if ActiveRecord::Base.connection.table_exists?(:products)
drop_table :invoices_products if ActiveRecord::Base.connection.table_exists?(:invoices_products)
create_table :customers do |t|
t.string :first_name, null: false
t.string :last_name, null: false
t.string :email, null: false, index: true, unique: true
end
create_table :products do |t|
t.string :name, null: false
t.integer :inventory, null: false, default: 0
t.text :description, null: false, default: ''
t.integer :price_cents, null: false, default: 0
end
create_table :addresses do |t|
t.references :customer
t.string :address_1
t.string :city
end
create_table :invoices do |t|
t.references :customer, index: true, foreign: true
t.datetime :invoice_date, null: false
t.references :shipping_address
t.references :billing_address
end
# needed for a pure many-to-many relationship
create_table :invoices_products do |t|
t.references :product
t.references :invoice
end
create_table :invoice_items do |t|
t.references :product
t.references :invoice
t.integer :price_cents
t.integer :quantity
end
end
puts "SEED Database"
Customer.create!(first_name: 'Jane', last_name: 'Doe', email: '[email protected]')
Customer.create!(first_name: 'John', last_name: 'Smith', email: '[email protected]')
Product.create!(name: 'Beer', description: 'Best drink in the world', price_cents: 290, inventory: 100)
Product.create!(name: 'Whiskey', description: 'The Scottish like it', price_cents: 100000, inventory: 50)
customer.invoices.create!(invoice_date: DateTime.now)
customer.invoices.create!(invoice_date: 1.month.ago)
puts "Running class code"
customer = Customer.find_by_email('[email protected]')
# Creating an Invoice with 1 item related to a product
product = Product.first
invoice = customer.invoices.build(invoice_date: DateTime.now)
item = invoice.invoice_items.build(product: product, price_cents: product.price_cents, quantity: 2)
invoice.save
# after the invoice is save the inventory of the product should decrease by two
# <model>.reload reloads the model (ie syncs) from the DB (used a lot in testing)
product.reload.inventory == product.inventory - item.quantity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment