Created
July 6, 2016 16:04
-
-
Save rob0t7/1d8032b3f123d4c0b6142dffb54d43f0 to your computer and use it in GitHub Desktop.
Intro to ActiveRecord
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_record' | |
require 'pry' | |
require 'pg' | |
# Set up logger | |
#ActiveRecord::Base.logger = ActiveSupport::Logger.new(File.open('database.log', 'w')) | |
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) | |
# Set up connection | |
ActiveRecord::Base.establish_connection( | |
adapter: 'postgresql', | |
database: 'active_record_store' | |
) | |
# Set up the schema of the database | |
ActiveRecord::Schema.define do | |
drop_table(:products) if table_exists?(:products) | |
create_table :products do |t| | |
t.string :name, null: false | |
t.text :description, null: false, default: '' | |
t.decimal :price, null: false, default: 0 | |
t.timestamps null: false | |
end | |
drop_table(:orders) if table_exists?(:orders) | |
create_table :orders do |t| | |
t.references :product, null: false, index: true | |
t.string :first_name, null: false | |
t.string :last_name, null: false | |
t.string :email, null: false | |
t.decimal :price, null: false | |
t.integer :quantity, null: false, default: 1 | |
t.timestamps null: false | |
end | |
end | |
# Now the models | |
class Product < ActiveRecord::Base | |
has_many :orders | |
validates :name, presence: true | |
validates :description, presence: true | |
validates :price, numericality: {greater_than_or_equal_to: 0} | |
# Creates a new order for a customer and copies the current price | |
# to the order object | |
def create_order(first_name, last_name, email, quantity) | |
orders.create(first_name: first_name, last_name: last_name, email: email, quantity: quantity, price: price) | |
end | |
end | |
class Order < ActiveRecord::Base | |
belongs_to :product | |
validates :first_name, presence: true | |
validates :last_name, presence: true | |
validates :email, presence: true, format: /\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/ | |
validates :price, presnce: true, numericality: { greater_than_or_equal_to: 0 } | |
validates :quantity, presence: true, numericality: { greater_than: 0 } | |
# Make sure all emails are lowercase in the DB | |
before_save { self.email.downcase! } | |
def name | |
"#{first_name} #{last_name}" | |
end | |
def total_price | |
price * quantity | |
end | |
end | |
# | |
# Lets create some objects | |
# | |
product1 = Product.new(name: 'Product 1', description: 'This is product 1', price: 50) | |
product1.save | |
product2 = Product.create(name: 'Product 2', description: 'This is product 2', price: 100) | |
# save runs validation rules first. If they fail then save fails (and create since it uses save underneath) | |
product3 = Product.new(description: 'This is product 3', price: 200) | |
product3.save # returns false | |
product3.errors # returns the errors | |
product3.name = 'Product 3' | |
product3.save # this works | |
order1 = product1.create_order('Bob', "Smith", '[email protected]', 2) | |
order1.total_price # == 100.00 | |
product1.create_order('Jane', 'Doe', '[email protected]', 1) | |
product1.orders # returns the two orders that are in the DB | |
order3 = Order.new(first_name: 'John', | |
last_name: 'Smith', | |
email: '[email protected]', | |
product: product2, | |
quantity: 1, | |
price: 5 | |
) | |
order3.save # it lowercases the email address and inserts it as [email protected] | |
product3.orders.create_order('John', 'Smith', '[email protected]', 4) | |
# | |
# Queries | |
# | |
# find all the products | |
Product.all | |
#find all product with price > 100 | |
Product.where('price > ?', 100) | |
#find all products with price > 100 and price < 200 order by name desc | |
Product.where('price > ?', 100).where('price < 200').order(name: :desc) | |
# Remove product2 (find using primary key) | |
Product.find(2).destroy | |
# Find all products that '[email protected]' has bought | |
# In efficient way (without joins) | |
product_with_orders = [] | |
Product.all.each do |product| | |
product_with_orders << product if product.orders.exists?(email: '[email protected]') | |
end | |
# return product_with_orders | |
# now using joins (1 DB call vs N+1) | |
Product.joins(:orders).where(orders: {email: '[email protected]'}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment