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

ActiveRecord basics and Postgres features

Avatar for Dax Huiberts Dax Huiberts
November 22, 2016

ActiveRecord basics and Postgres features

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

Avatar for Dax Huiberts

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!