diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-01-14 13:06:18 -0500 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-01-14 13:06:18 -0500 |
commit | 30cd66e1521bc760df45908adb2f7d3ba6683900 (patch) | |
tree | b730fbfc687516be2e4df95250d02598e9e7fa73 | |
parent | 91eeaa33a436ba2233f1fe7509f7c104db1d4533 (diff) | |
download | pokeviewer-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.rb | 3 | ||||
-rw-r--r-- | app/models/pokeviewer/pokemon.rb | 16 | ||||
-rw-r--r-- | app/models/pokeviewer/revision.rb | 9 | ||||
-rw-r--r-- | db/migrate/20180114170238_cache_current_pokemon_revision.rb | 19 | ||||
-rw-r--r-- | test/dummy/db/schema.rb | 4 |
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 |
153 | end | 167 | end |
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 |
487 | end | 496 | end |
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 @@ | |||
1 | class 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 | ||
19 | end | ||
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 | ||
13 | ActiveRecord::Schema.define(version: 20180113200119) do | 13 | ActiveRecord::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 |