about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-01-14 13:06:18 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-01-14 13:06:18 -0500
commit30cd66e1521bc760df45908adb2f7d3ba6683900 (patch)
treeb730fbfc687516be2e4df95250d02598e9e7fa73
parent91eeaa33a436ba2233f1fe7509f7c104db1d4533 (diff)
downloadpokeviewer-30cd66e1521bc760df45908adb2f7d3ba6683900.tar.gz
pokeviewer-30cd66e1521bc760df45908adb2f7d3ba6683900.tar.bz2
pokeviewer-30cd66e1521bc760df45908adb2f7d3ba6683900.zip
Cached a Pokémon's latest revision
This removes the need to use a GROUP or DISTINCT in eager-loading Pokémon on the front page. It duplicates data, but provisions are in place to keep the cache up-to-date. When a Pokémon record is updated, it is required that its cache points to the current revision. When a revision is created, it updates the Pokémon's cache to point to it, because a new revision will always be the most recent one, and it is impossible to reorder revisions.

This does not affect the number of queries used on the front page (see #1).

refs #4
-rw-r--r--app/controllers/pokeviewer/pokemon_controller.rb3
-rw-r--r--app/models/pokeviewer/pokemon.rb16
-rw-r--r--app/models/pokeviewer/revision.rb9
-rw-r--r--db/migrate/20180114170238_cache_current_pokemon_revision.rb19
-rw-r--r--test/dummy/db/schema.rb4
5 files changed, 47 insertions, 4 deletions
diff --git a/app/controllers/pokeviewer/pokemon_controller.rb b/app/controllers/pokeviewer/pokemon_controller.rb index 0e19c6a..f2d2187 100644 --- a/app/controllers/pokeviewer/pokemon_controller.rb +++ b/app/controllers/pokeviewer/pokemon_controller.rb
@@ -7,8 +7,7 @@ module Pokeviewer
7 order(trainer_id: :asc). 7 order(trainer_id: :asc).
8 order(box: :asc). 8 order(box: :asc).
9 order(slot: :asc). 9 order(slot: :asc).
10 select(:uuid).distinct. 10 joins(:current).
11 order("pokeviewer_revisions.sequential_id DESC").
12 includes(:current). 11 includes(:current).
13 chunk do |p| 12 chunk do |p|
14 if p.trainer_id.nil? 13 if p.trainer_id.nil?
diff --git a/app/models/pokeviewer/pokemon.rb b/app/models/pokeviewer/pokemon.rb index 012abab..77ee89a 100644 --- a/app/models/pokeviewer/pokemon.rb +++ b/app/models/pokeviewer/pokemon.rb
@@ -4,7 +4,9 @@ module Pokeviewer
4 extend ActiveModel::Naming 4 extend ActiveModel::Naming
5 5
6 has_many :revisions, -> { order "sequential_id ASC" }, dependent: :destroy 6 has_many :revisions, -> { order "sequential_id ASC" }, dependent: :destroy
7 has_one :current, -> { order "sequential_id DESC" }, class_name: "Revision" 7
8 belongs_to :current, class_name: "Revision", optional: true
9 validate :current_is_cached
8 10
9 belongs_to :trainer, optional: true 11 belongs_to :trainer, optional: true
10 12
@@ -149,5 +151,17 @@ module Pokeviewer
149 def uuid_is_constant 151 def uuid_is_constant
150 errors.add(:uuid, "can't be changed") if self.uuid_changed? 152 errors.add(:uuid, "can't be changed") if self.uuid_changed?
151 end 153 end
154
155 def current_is_cached
156 if self.revisions.empty?
157 unless self.current_id.nil?
158 errors.add(:current, "must be null when there are no revisions")
159 end
160 else
161 unless self.current_id = self.revisions.last.id
162 errors.add(:current, "is not up-to-date")
163 end
164 end
165 end
152 end 166 end
153end 167end
diff --git a/app/models/pokeviewer/revision.rb b/app/models/pokeviewer/revision.rb index 64b0e99..e5ad1dd 100644 --- a/app/models/pokeviewer/revision.rb +++ b/app/models/pokeviewer/revision.rb
@@ -17,6 +17,8 @@ module Pokeviewer
17 belongs_to :pokemon 17 belongs_to :pokemon
18 acts_as_sequenced scope: :pokemon_id 18 acts_as_sequenced scope: :pokemon_id
19 19
20 after_create :cache_pokemon_current
21
20 belongs_to :species 22 belongs_to :species
21 23
22 validates :nickname, presence: true 24 validates :nickname, presence: true
@@ -483,5 +485,12 @@ module Pokeviewer
483 485
484 result 486 result
485 end 487 end
488
489 private
490
491 def cache_pokemon_current
492 self.pokemon.current_id = self.id
493 self.pokemon.save!
494 end
486 end 495 end
487end 496end
diff --git a/db/migrate/20180114170238_cache_current_pokemon_revision.rb b/db/migrate/20180114170238_cache_current_pokemon_revision.rb new file mode 100644 index 0000000..a0e1747 --- /dev/null +++ b/db/migrate/20180114170238_cache_current_pokemon_revision.rb
@@ -0,0 +1,19 @@
1class CacheCurrentPokemonRevision < ActiveRecord::Migration[5.1]
2 def up
3 change_table :pokeviewer_pokemon do |t|
4 t.references :current, null: true
5 end
6
7 add_foreign_key :pokeviewer_pokemon, :pokeviewer_revisions,
8 column: :current_id
9
10 Pokeviewer::Pokemon.all.each do |p|
11 p.current_id = p.revisions.last.id
12 p.save!
13 end
14 end
15
16 def down
17 remove_column :pokeviewer_pokemon, :current_id
18 end
19end
diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index 9752892..5f8c1c0 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb
@@ -10,7 +10,7 @@
10# 10#
11# It's strongly recommended that you check this file into your version control system. 11# It's strongly recommended that you check this file into your version control system.
12 12
13ActiveRecord::Schema.define(version: 20180113200119) do 13ActiveRecord::Schema.define(version: 20180114170238) do
14 14
15 create_table "pokeviewer_abilities", force: :cascade do |t| 15 create_table "pokeviewer_abilities", force: :cascade do |t|
16 t.string "name", limit: 191, null: false 16 t.string "name", limit: 191, null: false
@@ -76,6 +76,8 @@ ActiveRecord::Schema.define(version: 20180113200119) do
76 t.integer "slot" 76 t.integer "slot"
77 t.integer "location_id" 77 t.integer "location_id"
78 t.string "pokeball", null: false 78 t.string "pokeball", null: false
79 t.integer "current_id"
80 t.index ["current_id"], name: "index_pokeviewer_pokemon_on_current_id"
79 t.index ["key"], name: "index_pokeviewer_pokemon_on_key", unique: true 81 t.index ["key"], name: "index_pokeviewer_pokemon_on_key", unique: true
80 t.index ["trainer_id"], name: "index_pokeviewer_pokemon_on_trainer_id" 82 t.index ["trainer_id"], name: "index_pokeviewer_pokemon_on_trainer_id"
81 t.index ["uuid"], name: "index_pokeviewer_pokemon_on_uuid", unique: true 83 t.index ["uuid"], name: "index_pokeviewer_pokemon_on_uuid", unique: true