rails_db_views 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff2f855836b239c4af2dae529189588761c22ff3
4
- data.tar.gz: 027d2f0e0f45ddb654d5ba70f4613219aa581eba
3
+ metadata.gz: 377a7268197020fe62a087261f12cd94ead05b30
4
+ data.tar.gz: 90090417d3607056ba577fa159f6b29366ca870b
5
5
  SHA512:
6
- metadata.gz: c1289482ced1e66da617ad275fd184e68fd2050aaa1ed0f53288066931e35418a6424ab4e7b09fc2bef98e598a90c382bb3d7311ff5107344061ed80b31d7bcd
7
- data.tar.gz: 871085dcaac1dc9663bdc6c4b4ce983f9e9d9be8363c41f0cfeced6ca70023334598d09c9481efbca3aaa722411d7412fe6cefe23653e225a7d388e3b4e76f7e
6
+ metadata.gz: a1f7de8e87be5f0de472bcc4a19d11934b69bee78520ed7704c0b33c686e7d942af8755c66a644757c076b073d1e77490aab5f945f219f61046b6efc3ddef446
7
+ data.tar.gz: 13c1b6a148618a475a9185fcaaba6b41e7905de85eaa0d4a45b7c373fa169b679b51748fe7a319361a6ec3fb860ec8bde007dc6dcbcfd03aedbecf8ed1d5b8cc
@@ -48,6 +48,10 @@ class RailsDbViews::DatabaseSymbol
48
48
  status == Status::UNLOADED
49
49
  end
50
50
 
51
+ def uncommented_sql_content
52
+ sql_content.split("\n").reject{|x| x=~ COMMENTS }.join("\n")
53
+ end
54
+
51
55
  def create!
52
56
  return if marked_as_deleted? || loaded?
53
57
 
@@ -82,8 +86,8 @@ class RailsDbViews::DatabaseSymbol
82
86
 
83
87
  begin
84
88
  ActiveRecord::Base.connection.execute(drop_sql)
85
- #rescue ActiveRecord::ActiveRecordError => e #Probably because the symbol doesn't exists yet.
86
- # handle_error_on_drop
89
+ rescue ActiveRecord::ActiveRecordError => e #Probably because the symbol doesn't exists yet.
90
+ handle_error_on_drop
87
91
  end
88
92
 
89
93
  self.status = Status::LOADED
@@ -107,6 +111,11 @@ protected
107
111
  SHARP_CHAR_DIRECTIVE_START = /^#[ \t]*!/
108
112
  DIRECTIVE_START = /#{TWO_DASH_DIRECTIVE_START}|#{SHARP_CHAR_DIRECTIVE_START}/
109
113
 
114
+ #It's not very safe in case we start a line into a string with the characters -- or #.
115
+ COMMENTS_TWO_DASH = /^--.*$/
116
+ COMMENTS_SHARP = /^#.*$/
117
+ COMMENTS = /#{COMMENTS_TWO_DASH}|#{COMMENTS_SHARP}/
118
+
110
119
  def circular_reference_error
111
120
  raise CircularReferenceError, "Circular file reference! (file: #{path})"
112
121
  end
@@ -1,7 +1,7 @@
1
1
  class RailsDbViews::Function < RailsDbViews::DatabaseSymbol
2
2
  def create_sql
3
3
  puts "CREATE OR REPLACE FUNCTION #{name}..."
4
- "CREATE OR REPLACE FUNCTION #{name} #{sql_content}"
4
+ "CREATE OR REPLACE FUNCTION #{name} #{uncommented_sql_content}"
5
5
  end
6
6
 
7
7
  def drop_sql
@@ -1,3 +1,3 @@
1
1
  module RailsDbViews
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  class RailsDbViews::View < RailsDbViews::DatabaseSymbol
2
2
  def create_sql
3
3
  puts "CREATE VIEW #{name}..."
4
- "CREATE VIEW #{name} AS #{sql_content}"
4
+ "CREATE VIEW #{name} AS #{uncommented_sql_content}"
5
5
  end
6
6
 
7
7
  def drop_sql
@@ -0,0 +1,2 @@
1
+ class Chat < ActiveRecord::Base
2
+ end
@@ -0,0 +1,6 @@
1
+ class Message < ActiveRecord::Base
2
+ #receiver_name, receiver_id, sender_name, sender_id, content, updated_at, created_at
3
+ belongs_to :receiver, class_name: "User"
4
+ belongs_to :sender, class_name: "Sender"
5
+
6
+ end
@@ -0,0 +1,18 @@
1
+ class User < ActiveRecord::Base
2
+ validates :name, presence: true, uniqueness: true
3
+
4
+
5
+ has_many :sended_messages, class_name: "UserMessage", foreign_key: :from
6
+ has_many :received_messages, class_name: "UserMessage", foreign_key: :to
7
+
8
+ has_many :messages
9
+
10
+ def message! user, content
11
+ UserMessage.create! from: self, to: user, content: content
12
+ end
13
+
14
+ # Return all chats of this guy!
15
+ def chats
16
+ Chat.where("'{?}' && ids", self.id)
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ class UserMessage < ActiveRecord::Base
2
+ belongs_to :from, class_name: "User"
3
+ belongs_to :to, class_name: "User"
4
+ end
5
+
6
+
@@ -5,7 +5,7 @@
5
5
  # gem 'sqlite3'
6
6
  development:
7
7
  adapter: postgresql
8
- database: rails_db_views
8
+ database: rails_db_views_development
9
9
  pool: 5
10
10
  timeout: 5000
11
11
 
@@ -13,13 +13,7 @@ development:
13
13
  # re-generated from your development database when you run "rake".
14
14
  # Do not set this db to the same as development or production.
15
15
  test:
16
- adapter: sqlite3
17
- database: db/test.sqlite3
18
- pool: 5
19
- timeout: 5000
20
-
21
- production:
22
- adapter: sqlite3
23
- database: db/production.sqlite3
16
+ adapter: postgresql
17
+ database: rails_db_views_test
24
18
  pool: 5
25
19
  timeout: 5000
@@ -0,0 +1,10 @@
1
+ (x int[]) RETURNS int[] AS $$
2
+ BEGIN
3
+ -- Note to myself: selection in array start at 1, not at zero !
4
+ IF x[1]::int > x[2]::int THEN
5
+ RETURN ARRAY[x[2], x[1]];
6
+ ELSE
7
+ RETURN x;
8
+ END IF;
9
+ END;
10
+ $$ LANGUAGE plpgsql;
@@ -0,0 +1,18 @@
1
+ class CreateTestTables < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :name, index: true
5
+
6
+ t.timestamps null: false
7
+ end
8
+
9
+ create_table :user_messages do |t|
10
+ t.integer :from_id, index: true
11
+ t.integer :to_id, index: true
12
+
13
+ t.text :content
14
+
15
+ t.timestamps null: false
16
+ end
17
+ end
18
+ end
@@ -11,9 +11,28 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 0) do
14
+ ActiveRecord::Schema.define(version: 20160208084226) do
15
15
 
16
16
  # These are extensions that must be enabled in order to support this database
17
17
  enable_extension "plpgsql"
18
18
 
19
+ create_table "user_messages", force: :cascade do |t|
20
+ t.integer "from_id"
21
+ t.integer "to_id"
22
+ t.text "content"
23
+ t.datetime "created_at", null: false
24
+ t.datetime "updated_at", null: false
25
+ end
26
+
27
+ add_index "user_messages", ["from_id"], name: "index_user_messages_on_from_id", using: :btree
28
+ add_index "user_messages", ["to_id"], name: "index_user_messages_on_to_id", using: :btree
29
+
30
+ create_table "users", force: :cascade do |t|
31
+ t.string "name"
32
+ t.datetime "created_at", null: false
33
+ t.datetime "updated_at", null: false
34
+ end
35
+
36
+ add_index "users", ["name"], name: "index_users_on_name", using: :btree
37
+
19
38
  end
Binary file
@@ -0,0 +1,6 @@
1
+ # This is the request for virtual chat object.
2
+ # !require messages
3
+ SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
4
+ MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
5
+ FROM messages
6
+ GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
@@ -0,0 +1,20 @@
1
+ -- Sample virtual model to test the gem.
2
+ -- output:
3
+ -- receiver_name, receiver_id, sender_name, sender_id, content, updated_at, created_at
4
+ SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
5
+ FROM
6
+ (SELECT u2.name as receiver_name, u2.id as receiver_id,
7
+ u1.name as sender_name, u1.id as sender_id,
8
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
9
+ FROM users u1
10
+ INNER JOIN user_messages um ON ( u1.id = um.from_id )
11
+ INNER JOIN users u2 ON (u2.id = um.to_id)
12
+ UNION
13
+ SELECT u1.name as receiver_name, u1.id as receiver_id,
14
+ u2.name as sender_name, u2.id as sender_id,
15
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
16
+ FROM users u1
17
+ INNER JOIN user_messages um ON ( u1.id = um.to_id )
18
+ INNER JOIN users u2 ON ( u2.id = um.from_id )
19
+ ORDER BY created_at ASC
20
+ ) AS _
@@ -0,0 +1,30 @@
1
+ # I've no idea of what I'm doing... haha.
2
+ # No, really, I don't know what's the best way to test
3
+ # this gem since it's launched during rake process and not during
4
+ # application time.
5
+ task :test do
6
+ begin
7
+ Rake::Task["db:drop"].invoke
8
+ rescue
9
+ # Case the database is not created, we ignore this error
10
+ end
11
+ # But if the database can't be created, we don't ignore.
12
+ Rake::Task["db:create"].invoke
13
+ Rake::Task["db:migrate"].invoke
14
+
15
+ # Launch RoR
16
+ Rake::Task["environment"].invoke
17
+
18
+ #Create some models
19
+ jack = User.create! name: "Jack"
20
+ cindy = User.create! name: "Cindy"
21
+ henry = User.create! name: "Henry"
22
+
23
+ jack.message! cindy, "Hey, how are you?"
24
+ cindy.message! jack, "I'm fine, and you?"
25
+ henry.message! cindy, "Me too, I want to chat with you babe!"
26
+
27
+ puts henry.chats.inspect
28
+ puts cindy.chats.inspect
29
+ puts jack.chats.inspect
30
+ end
@@ -482,3 +482,244 @@ $$ LANGUAGE plpgsql;
482
482
   (12.4ms) CREATE VIEW required AS SELECT 1 as id
483
483
   (12.6ms) CREATE VIEW hello_world AS --!require required
484
484
  SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
485
+  (2.3ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
486
+ BEGIN
487
+ RETURN x + y;
488
+ END;
489
+ $$ LANGUAGE plpgsql;
490
+  (7.2ms) DROP VIEW hello_world
491
+  (6.7ms) DROP VIEW required
492
+ ActiveRecord::SchemaMigration Load (0.7ms) SELECT "schema_migrations".* FROM "schema_migrations"
493
+  (13.2ms) CREATE VIEW required AS SELECT 1 as id
494
+  (7.1ms) CREATE VIEW hello_world AS --!require required
495
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
496
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
497
+  (2.0ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
498
+ BEGIN
499
+ RETURN x + y;
500
+ END;
501
+ $$ LANGUAGE plpgsql;
502
+  (6.1ms) CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
503
+ BEGIN
504
+ IF x[0] > x[1] THEN
505
+ RETURN ARRAY[x[1], x[0]];
506
+ ELSE
507
+ RETURN x;
508
+ END IF;
509
+ END;
510
+ $$ LANGUAGE plpgsql;
511
+  (0.4ms) DROP VIEW chats
512
+ PG::UndefinedTable: ERROR: view "chats" does not exist
513
+ : DROP VIEW chats
514
+  (0.2ms) DROP VIEW messages
515
+ PG::UndefinedTable: ERROR: view "messages" does not exist
516
+ : DROP VIEW messages
517
+  (7.3ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL) 
518
+  (0.9ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
519
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
520
+ Migrating to CreateTestTables (20160208084226)
521
+  (0.1ms) BEGIN
522
+  (3.7ms) CREATE TABLE "users" ("id" serial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) 
523
+  (0.8ms) CREATE INDEX "index_users_on_name" ON "users" ("name")
524
+  (2.4ms) CREATE TABLE "user_messages" ("id" serial primary key, "from_id" integer, "to_id" integer, "content" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) 
525
+  (0.7ms) CREATE INDEX "index_user_messages_on_from_id" ON "user_messages" ("from_id")
526
+  (0.8ms) CREATE INDEX "index_user_messages_on_to_id" ON "user_messages" ("to_id")
527
+ SQL (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20160208084226"]]
528
+  (0.5ms) COMMIT
529
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
530
+  (1.8ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
531
+ FROM pg_constraint c
532
+ JOIN pg_class t1 ON c.conrelid = t1.oid
533
+ JOIN pg_class t2 ON c.confrelid = t2.oid
534
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
535
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
536
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
537
+ WHERE c.contype = 'f'
538
+ AND t1.relname = 'user_messages'
539
+ AND t3.nspname = ANY (current_schemas(false))
540
+ ORDER BY c.conname
541
+ 
542
+  (1.5ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
543
+ FROM pg_constraint c
544
+ JOIN pg_class t1 ON c.conrelid = t1.oid
545
+ JOIN pg_class t2 ON c.confrelid = t2.oid
546
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
547
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
548
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
549
+ WHERE c.contype = 'f'
550
+ AND t1.relname = 'users'
551
+ AND t3.nspname = ANY (current_schemas(false))
552
+ ORDER BY c.conname
553
+
554
+  (10.5ms) CREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
555
+ FROM
556
+ (SELECT u2.name as receiver_name, u2.id as receiver_id,
557
+ u1.name as sender_name, u1.id as sender_id,
558
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
559
+ FROM users u1
560
+ INNER JOIN user_messages um ON ( u1.id = um.from_id )
561
+ INNER JOIN users u2 ON (u2.id = um.to_id)
562
+ UNION
563
+ SELECT u1.name as receiver_name, u1.id as receiver_id,
564
+ u2.name as sender_name, u2.id as sender_id,
565
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
566
+ FROM users u1
567
+ INNER JOIN user_messages um ON ( u1.id = um.to_id )
568
+ INNER JOIN users u2 ON ( u2.id = um.from_id )
569
+ ORDER BY created_at ASC
570
+ ) AS _
571
+  (7.1ms) CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
572
+ MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
573
+ FROM messages
574
+ GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
575
+  (1.5ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
576
+ BEGIN
577
+ RETURN x + y;
578
+ END;
579
+ $$ LANGUAGE plpgsql;
580
+  (0.7ms) CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
581
+ BEGIN
582
+ IF x[0] > x[1] THEN
583
+ RETURN ARRAY[x[1], x[0]];
584
+ ELSE
585
+ RETURN x;
586
+ END IF;
587
+ END;
588
+ $$ LANGUAGE plpgsql;
589
+  (1.6ms) DROP VIEW chats
590
+  (0.8ms) DROP VIEW messages
591
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
592
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
593
+  (1.9ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
594
+ FROM pg_constraint c
595
+ JOIN pg_class t1 ON c.conrelid = t1.oid
596
+ JOIN pg_class t2 ON c.confrelid = t2.oid
597
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
598
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
599
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
600
+ WHERE c.contype = 'f'
601
+ AND t1.relname = 'user_messages'
602
+ AND t3.nspname = ANY (current_schemas(false))
603
+ ORDER BY c.conname
604
+ 
605
+  (1.4ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
606
+ FROM pg_constraint c
607
+ JOIN pg_class t1 ON c.conrelid = t1.oid
608
+ JOIN pg_class t2 ON c.confrelid = t2.oid
609
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
610
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
611
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
612
+ WHERE c.contype = 'f'
613
+ AND t1.relname = 'users'
614
+ AND t3.nspname = ANY (current_schemas(false))
615
+ ORDER BY c.conname
616
+
617
+  (8.5ms) CREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
618
+ FROM
619
+ (SELECT u2.name as receiver_name, u2.id as receiver_id,
620
+ u1.name as sender_name, u1.id as sender_id,
621
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
622
+ FROM users u1
623
+ INNER JOIN user_messages um ON ( u1.id = um.from_id )
624
+ INNER JOIN users u2 ON (u2.id = um.to_id)
625
+ UNION
626
+ SELECT u1.name as receiver_name, u1.id as receiver_id,
627
+ u2.name as sender_name, u2.id as sender_id,
628
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
629
+ FROM users u1
630
+ INNER JOIN user_messages um ON ( u1.id = um.to_id )
631
+ INNER JOIN users u2 ON ( u2.id = um.from_id )
632
+ ORDER BY created_at ASC
633
+ ) AS _
634
+  (7.6ms) CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
635
+ MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
636
+ FROM messages
637
+ GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
638
+  (0.1ms) SELECT 1;
639
+  (0.3ms) SELECT 1;
640
+  (0.3ms) SELECT 2;
641
+  (0.2ms) SELECT 2;
642
+  (0.3ms) SELECT 2
643
+  (8.3ms) SELECT tuple_sort(ARRAY[1,3])
644
+  (0.9ms) SELECT tuple_sort(ARRAY[3,1])
645
+  (0.9ms) SELECT tuple_sort(ARRAY[3,1])
646
+  (2.4ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
647
+ BEGIN
648
+ RETURN x + y;
649
+ END;
650
+ $$ LANGUAGE plpgsql;
651
+  (0.6ms) CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
652
+ BEGIN
653
+ IF x[0]::int > x[1]::int THEN
654
+ RETURN ARRAY[x[1], x[0]];
655
+ ELSE
656
+ RETURN x;
657
+ END IF;
658
+ END;
659
+ $$ LANGUAGE plpgsql;
660
+  (0.3ms) DROP VIEW chats
661
+ PG::UndefinedTable: ERROR: view "chats" does not exist
662
+ : DROP VIEW chats
663
+  (0.2ms) DROP VIEW messages
664
+ PG::UndefinedTable: ERROR: view "messages" does not exist
665
+ : DROP VIEW messages
666
+  (2.3ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL) 
667
+  (1.2ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
668
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
669
+ Migrating to CreateTestTables (20160208084226)
670
+  (0.1ms) BEGIN
671
+  (5.8ms) CREATE TABLE "users" ("id" serial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) 
672
+  (0.6ms) CREATE INDEX "index_users_on_name" ON "users" ("name")
673
+  (2.2ms) CREATE TABLE "user_messages" ("id" serial primary key, "from_id" integer, "to_id" integer, "content" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) 
674
+  (0.6ms) CREATE INDEX "index_user_messages_on_from_id" ON "user_messages" ("from_id")
675
+  (0.6ms) CREATE INDEX "index_user_messages_on_to_id" ON "user_messages" ("to_id")
676
+ SQL (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20160208084226"]]
677
+  (0.5ms) COMMIT
678
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
679
+  (2.0ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
680
+ FROM pg_constraint c
681
+ JOIN pg_class t1 ON c.conrelid = t1.oid
682
+ JOIN pg_class t2 ON c.confrelid = t2.oid
683
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
684
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
685
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
686
+ WHERE c.contype = 'f'
687
+ AND t1.relname = 'user_messages'
688
+ AND t3.nspname = ANY (current_schemas(false))
689
+ ORDER BY c.conname
690
+ 
691
+  (1.5ms) SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
692
+ FROM pg_constraint c
693
+ JOIN pg_class t1 ON c.conrelid = t1.oid
694
+ JOIN pg_class t2 ON c.confrelid = t2.oid
695
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
696
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
697
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
698
+ WHERE c.contype = 'f'
699
+ AND t1.relname = 'users'
700
+ AND t3.nspname = ANY (current_schemas(false))
701
+ ORDER BY c.conname
702
+
703
+  (7.7ms) CREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
704
+ FROM
705
+ (SELECT u2.name as receiver_name, u2.id as receiver_id,
706
+ u1.name as sender_name, u1.id as sender_id,
707
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
708
+ FROM users u1
709
+ INNER JOIN user_messages um ON ( u1.id = um.from_id )
710
+ INNER JOIN users u2 ON (u2.id = um.to_id)
711
+ UNION
712
+ SELECT u1.name as receiver_name, u1.id as receiver_id,
713
+ u2.name as sender_name, u2.id as sender_id,
714
+ um.content as content, um.updated_at as updated_at, um.created_at as created_at
715
+ FROM users u1
716
+ INNER JOIN user_messages um ON ( u1.id = um.to_id )
717
+ INNER JOIN users u2 ON ( u2.id = um.from_id )
718
+ ORDER BY created_at ASC
719
+ ) AS _
720
+  (7.7ms) CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
721
+ MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
722
+ FROM messages
723
+ GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
724
+  (1.0ms) SELECT tuple_sort(ARRAY[3,1])
725
+  (2.1ms) SELECT tuple_sort(ARRAY[1,3])