Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ActiveRecord basics and Postgres features

Dax Huiberts
November 22, 2016

ActiveRecord basics and Postgres features

A talk I gave on the Amsterdam Ruby meetup on Tuesday November 22nd.

Dax Huiberts

November 22, 2016
Tweet

More Decks by Dax Huiberts

Other Decks in Programming

Transcript

  1. Why postgres • It's a great tool • It gets

    the job done • I like having just one data source • It can handle a lot of data (+100M records) • Guarantee data consistency • It is much faster than your ruby code
  2. class Invoice < ActiveRecord::Base has_many :line_items end class LineItem <

    ActiveRecord::Base belongs_to :invoice validates :invoice, presence: true end
  3. class Invoice < ActiveRecord::Base has_many :line_items, dependent: :destroy end class

    LineItem < ActiveRecord::Base belongs_to :invoice validates :invoice, presence: true end
  4. class LineItem < ActiveRecord::Base belongs_to :invoice belongs_to :invoicable, polymorphic: true

    validates :invoice, presence: true validates :invoicable, presence: true end
  5. class LineItem < ActiveRecord::Base belongs_to :invoice belongs_to :product belongs_to :service

    validates :invoice, presence: true validates :product, presence: true, unless: :service? validates :product, absence: true, if: :service? validates :service, presence: true, unless: :product? validates :service, absence: true, if: :product? end
  6. class LineItem < ActiveRecord::Base belongs_to :invoice belongs_to :product belongs_to :service

    validates :invoice, presence: true validates :kind, inclusion: {in: ['product', 'service']} validates :product, presence: true, if: "kind == 'product'" validates :product, absence: true, if: "kind != 'product'" validates :service, presence: true, if: "kind == 'service'" validates :service, absence: true, if: "kind != 'service'" end
  7. ALTER TABLE line_items ADD CONSTRAINT kind_values CHECK (kind IN ('product',

    'service'); ALTER TABLE line_items ADD CONSTRAINT product_kind CHECK ( (kind = 'product' AND product_id IS NOT NULL) OR (kind != 'product' AND product_id IS NULL) ); ALTER TABLE line_items ADD CONSTRAINT service_kind CHECK ( (kind = 'service' AND service_id IS NOT NULL) OR (kind != 'service' AND service_id IS NULL) );
  8. CREATE VIEW invoicables AS SELECT concat('p', p.id) AS id, 'product'

    AS kind, p.id AS product_id, NULL AS service_id, p.name, p.price FROM products AS p UNION ALL SELECT concat('s', s.id) AS id, 'service' AS kind, NULL AS product_id, s.id AS service_id, s.name, s.price FROM services AS s;
  9. class Invoicable < ActiveRecord::Base self.primary_key = :id belongs_to :product belongs_to

    :service # attribute :kind # attribute :name # attribute :price end
  10. CREATE VIEW derived_invoices AS SELECT i.id AS id, i.id AS

    invoice_id, COUNT(li.id) AS item_count, SUM(li.price * li.quantity) AS total_price FROM invoices AS i LEFT JOIN line_items AS li ON i.id = li.invoice_id GROUP BY i.id;
  11. CREATE VIEW roster_days AS SELECT UNNEST(ARRAY( SELECT next_date FROM GENERATE_SERIES(

    start_date, end_date, '1 week' ) AS next_date ))::date AS date FROM roster_entries
  12. Learnings • Breathe SQL • Use The Index, Luke •

    Look out for slow queries • `explain analyze` is your friend • Postgres is awesome!