· 7 years ago · Oct 11, 2018, 07:14 PM
1# require 'pg'; PG.connect(dbname: 'postgres').exec('create database josh_testing') # <-- uncomment to create the db (only needs to run once)
2
3# ===== Setup ActiveRecord =====
4require 'active_record'
5require 'logger'
6ActiveRecord::Base.establish_connection adapter: 'postgresql', database: 'josh_testing'
7ActiveRecord::Base.logger = Logger.new $stdout
8ActiveSupport::LogSubscriber.colorize_logging = false
9
10# ===== Migration =====
11ActiveRecord::Schema.define do
12 self.verbose = false
13
14 # reset db
15 drop_table :workers, if_exists: true
16 execute "drop type if exists worker_type;"
17
18 # create the type
19 execute "create type worker_type as enum ('person', 'script', 'model');"
20
21 # create the table
22 create_table :workers do |t|
23 t.column :type, :worker_type, null: false
24 end
25end
26
27# ===== Model =====
28class Worker < ActiveRecord::Base
29 # Rails convention is for the `type` column to be used for STI
30 # we aren't using STI and we have a type column,
31 # so we need to override the convention to use some nonexistant column
32 self.inheritance_column = :_sti_disabled
33
34 enum type: {
35 people: 'person',
36 scripts: 'script',
37 models: 'model',
38 }
39end
40
41# ===== Creating Data =====
42Worker.create! [
43 {type: 'person'},
44 {type: 'person'},
45 {type: 'script'},
46 {type: 'model' },
47]
48
49# ===== Querying =====
50Worker.people.to_sql
51# => "SELECT \"workers\".* FROM \"workers\" WHERE \"workers\".\"type\" = 'person'"
52
53Worker.people
54# => [#<Worker:0x00007f9684bf2558 id: 1, type: "people">,
55# #<Worker:0x00007f9684bf2378 id: 2, type: "people">]
56Worker.scripts
57# => [#<Worker:0x00007f96868361b0 id: 3, type: "scripts">]
58Worker.models
59# => [#<Worker:0x00007f9684bf6180 id: 4, type: "models">]
60
61# ===== Invalid Values =====
62# All three of these seem like strange behaviour to me, feels like it should just add a validation
63Worker.new(type: 'something_else') rescue $! # => #<ArgumentError: 'something_else' is not a valid type>
64Worker.new.valid? # => true
65Worker.new.save rescue $! # => #<ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "type" violates not-null constraint\nDETAIL: Failing row contains (5, null).\n: INSERT INTO "workers" DEFAULT VALUES RETURNING "id">
66
67# We can address the last two with our own validation
68Worker.validates :type, inclusion: { in: %w[person script model] }
69
70Worker.new(type: 'something_else') rescue $! # => #<ArgumentError: 'something_else' is not a valid type>
71w = Worker.new
72w.valid? # => false
73w.errors.full_messages # => ["Type is not included in the list"]
74
75# >> D, [2018-10-11T11:35:22.832577 #55812] DEBUG -- : (3.7ms) DROP TABLE IF EXISTS "workers"
76# >> D, [2018-10-11T11:35:22.834320 #55812] DEBUG -- : (1.5ms) drop type if exists worker_type;
77# >> D, [2018-10-11T11:35:22.836611 #55812] DEBUG -- : (2.1ms) create type worker_type as enum ('person', 'script', 'model');
78# >> D, [2018-10-11T11:35:22.842889 #55812] DEBUG -- : (5.4ms) CREATE TABLE "workers" ("id" bigserial primary key, "type" worker_type NOT NULL)
79# >> D, [2018-10-11T11:35:22.885089 #55812] DEBUG -- : ActiveRecord::InternalMetadata Load (0.5ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", "environment"], ["LIMIT", 1]]
80# >> D, [2018-10-11T11:35:22.891333 #55812] DEBUG -- : (0.2ms) BEGIN
81# >> D, [2018-10-11T11:35:22.892533 #55812] DEBUG -- : (0.2ms) COMMIT
82# >> D, [2018-10-11T11:35:22.900873 #55812] DEBUG -- : (0.2ms) BEGIN
83# >> D, [2018-10-11T11:35:22.902100 #55812] DEBUG -- : Worker Create (0.6ms) INSERT INTO "workers" ("type") VALUES ($1) RETURNING "id" [["type", "person"]]
84# >> D, [2018-10-11T11:35:22.903688 #55812] DEBUG -- : (1.3ms) COMMIT
85# >> D, [2018-10-11T11:35:22.904200 #55812] DEBUG -- : (0.2ms) BEGIN
86# >> D, [2018-10-11T11:35:22.904931 #55812] DEBUG -- : Worker Create (0.3ms) INSERT INTO "workers" ("type") VALUES ($1) RETURNING "id" [["type", "person"]]
87# >> D, [2018-10-11T11:35:22.906561 #55812] DEBUG -- : (1.4ms) COMMIT
88# >> D, [2018-10-11T11:35:22.907113 #55812] DEBUG -- : (0.2ms) BEGIN
89# >> D, [2018-10-11T11:35:22.908105 #55812] DEBUG -- : Worker Create (0.4ms) INSERT INTO "workers" ("type") VALUES ($1) RETURNING "id" [["type", "script"]]
90# >> D, [2018-10-11T11:35:22.909961 #55812] DEBUG -- : (1.4ms) COMMIT
91# >> D, [2018-10-11T11:35:22.910556 #55812] DEBUG -- : (0.2ms) BEGIN
92# >> D, [2018-10-11T11:35:22.911279 #55812] DEBUG -- : Worker Create (0.3ms) INSERT INTO "workers" ("type") VALUES ($1) RETURNING "id" [["type", "model"]]
93# >> D, [2018-10-11T11:35:22.913072 #55812] DEBUG -- : (1.5ms) COMMIT
94# >> D, [2018-10-11T11:35:22.915092 #55812] DEBUG -- : Worker Load (0.3ms) SELECT "workers".* FROM "workers" WHERE "workers"."type" = $1 [["type", "person"]]
95# >> D, [2018-10-11T11:35:22.916361 #55812] DEBUG -- : Worker Load (0.3ms) SELECT "workers".* FROM "workers" WHERE "workers"."type" = $1 [["type", "script"]]
96# >> D, [2018-10-11T11:35:22.917269 #55812] DEBUG -- : Worker Load (0.3ms) SELECT "workers".* FROM "workers" WHERE "workers"."type" = $1 [["type", "model"]]
97# >> D, [2018-10-11T11:35:22.918083 #55812] DEBUG -- : (0.2ms) BEGIN
98# >> D, [2018-10-11T11:35:22.919092 #55812] DEBUG -- : Worker Create (0.6ms) INSERT INTO "workers" DEFAULT VALUES RETURNING "id"
99# >> D, [2018-10-11T11:35:22.919416 #55812] DEBUG -- : (0.1ms) ROLLBACK