mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-03-25 01:14:43 +00:00
Compare commits
3 Commits
ae8d995b2c
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3fb68a932 | ||
| d359be3ea1 | |||
| e97aa0d680 |
2
Gemfile
2
Gemfile
@@ -40,7 +40,7 @@ gem 'sdoc', :group => :doc
|
|||||||
gem 'spring', :group => :development
|
gem 'spring', :group => :development
|
||||||
|
|
||||||
# Use ActiveModel has_secure_password
|
# Use ActiveModel has_secure_password
|
||||||
gem 'bcrypt', '~> 3.1.7'
|
gem 'bcrypt', '~> 3.1.22'
|
||||||
|
|
||||||
# Use unicorn as the app server
|
# Use unicorn as the app server
|
||||||
# gem 'unicorn'
|
# gem 'unicorn'
|
||||||
|
|||||||
18
Gemfile.lock
18
Gemfile.lock
@@ -77,9 +77,9 @@ GEM
|
|||||||
uri (>= 0.13.1)
|
uri (>= 0.13.1)
|
||||||
ast (2.4.3)
|
ast (2.4.3)
|
||||||
base64 (0.3.0)
|
base64 (0.3.0)
|
||||||
bcrypt (3.1.21)
|
bcrypt (3.1.22)
|
||||||
bigdecimal (4.0.1)
|
bigdecimal (4.0.1)
|
||||||
bootsnap (1.22.0)
|
bootsnap (1.23.0)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
brakeman (8.0.2)
|
brakeman (8.0.2)
|
||||||
racc
|
racc
|
||||||
@@ -157,12 +157,12 @@ GEM
|
|||||||
railties (>= 7.1)
|
railties (>= 7.1)
|
||||||
stimulus-rails
|
stimulus-rails
|
||||||
turbo-rails
|
turbo-rails
|
||||||
mocha (3.0.1)
|
mocha (3.0.2)
|
||||||
ruby2_keywords (>= 0.0.5)
|
ruby2_keywords (>= 0.0.5)
|
||||||
msgpack (1.8.0)
|
msgpack (1.8.0)
|
||||||
mysql2 (0.5.7)
|
mysql2 (0.5.7)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
net-imap (0.6.2)
|
net-imap (0.6.3)
|
||||||
date
|
date
|
||||||
net-protocol
|
net-protocol
|
||||||
net-pop (0.1.2)
|
net-pop (0.1.2)
|
||||||
@@ -257,7 +257,7 @@ GEM
|
|||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.3.1)
|
rake (13.3.1)
|
||||||
rb-readline (0.5.5)
|
rb-readline (0.5.5)
|
||||||
rdoc (7.1.0)
|
rdoc (7.2.0)
|
||||||
erb
|
erb
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
tsort
|
tsort
|
||||||
@@ -269,7 +269,7 @@ GEM
|
|||||||
chunky_png (~> 1.0)
|
chunky_png (~> 1.0)
|
||||||
rqrcode_core (~> 2.0)
|
rqrcode_core (~> 2.0)
|
||||||
rqrcode_core (2.1.0)
|
rqrcode_core (2.1.0)
|
||||||
rubocop (1.84.1)
|
rubocop (1.84.2)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
@@ -349,7 +349,7 @@ PLATFORMS
|
|||||||
x86_64-linux-musl
|
x86_64-linux-musl
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
bcrypt (~> 3.1.7)
|
bcrypt (~> 3.1.22)
|
||||||
bootsnap
|
bootsnap
|
||||||
brakeman
|
brakeman
|
||||||
bullet
|
bullet
|
||||||
@@ -384,7 +384,7 @@ DEPENDENCIES
|
|||||||
tzinfo-data
|
tzinfo-data
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 4.0.1p0
|
ruby 4.0.1p0
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.6.9
|
4.0.3
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ class Mat < ApplicationRecord
|
|||||||
|
|
||||||
QUEUE_SLOTS = %w[queue1 queue2 queue3 queue4].freeze
|
QUEUE_SLOTS = %w[queue1 queue2 queue3 queue4].freeze
|
||||||
|
|
||||||
|
after_save :clear_queue_matches_cache
|
||||||
|
|
||||||
def assign_next_match
|
def assign_next_match
|
||||||
slot = first_empty_queue_slot
|
slot = first_empty_queue_slot
|
||||||
return true unless slot
|
return true unless slot
|
||||||
@@ -86,8 +88,20 @@ class Mat < ApplicationRecord
|
|||||||
QUEUE_SLOTS.map { |slot| public_send(slot) }
|
QUEUE_SLOTS.map { |slot| public_send(slot) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# used to prevent N+1 query on each mat
|
||||||
def queue_matches
|
def queue_matches
|
||||||
queue_match_ids.map { |match_id| match_id ? Match.find_by(id: match_id) : nil }
|
slot_ids = queue_match_ids
|
||||||
|
if @queue_matches.nil? || @queue_match_slot_ids != slot_ids
|
||||||
|
ids = slot_ids.compact
|
||||||
|
@queue_matches = if ids.empty?
|
||||||
|
[nil, nil, nil, nil]
|
||||||
|
else
|
||||||
|
matches_by_id = Match.where(id: ids).index_by(&:id)
|
||||||
|
slot_ids.map { |match_id| match_id ? matches_by_id[match_id] : nil }
|
||||||
|
end
|
||||||
|
@queue_match_slot_ids = slot_ids
|
||||||
|
end
|
||||||
|
@queue_matches
|
||||||
end
|
end
|
||||||
|
|
||||||
def queue1_match
|
def queue1_match
|
||||||
@@ -175,9 +189,13 @@ class Mat < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def clear_queue_matches_cache
|
||||||
|
@queue_matches = nil
|
||||||
|
@queue_match_slot_ids = nil
|
||||||
|
end
|
||||||
|
|
||||||
def queue_match_at(position)
|
def queue_match_at(position)
|
||||||
match_id = public_send("queue#{position}")
|
queue_matches[position - 1]
|
||||||
match_id ? Match.find_by(id: match_id) : nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def first_empty_queue_slot
|
def first_empty_queue_slot
|
||||||
|
|||||||
34
app/views/tournaments/_up_matches_mat_row.html.erb
Normal file
34
app/views/tournaments/_up_matches_mat_row.html.erb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<% queue1_match, queue2_match, queue3_match, queue4_match = mat.queue_matches %>
|
||||||
|
<% cache ["up_matches_mat_row", mat, mat.queue1, mat.queue2, mat.queue3, mat.queue4] do %>
|
||||||
|
<tr>
|
||||||
|
<td><%= mat.name %></td>
|
||||||
|
<td>
|
||||||
|
<% if queue1_match %><strong><%= queue1_match.bout_number %></strong> (<%= queue1_match.bracket_position %>)<br>
|
||||||
|
<%= queue1_match.weight_max %> lbs
|
||||||
|
<br><%= queue1_match.w1_bracket_name %> vs. <br>
|
||||||
|
<%= queue1_match.w2_bracket_name %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<% if queue2_match %><strong><%= queue2_match.bout_number %></strong> (<%= queue2_match.bracket_position %>)<br>
|
||||||
|
<%= queue2_match.weight_max %> lbs
|
||||||
|
<br><%= queue2_match.w1_bracket_name %> vs. <br>
|
||||||
|
<%= queue2_match.w2_bracket_name %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<% if queue3_match %><strong><%= queue3_match.bout_number %></strong> (<%= queue3_match.bracket_position %>)<br>
|
||||||
|
<%= queue3_match.weight_max %> lbs
|
||||||
|
<br><%= queue3_match.w1_bracket_name %> vs. <br>
|
||||||
|
<%= queue3_match.w2_bracket_name %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<% if queue4_match %><strong><%= queue4_match.bout_number %></strong> (<%= queue4_match.bracket_position %>)<br>
|
||||||
|
<%= queue4_match.weight_max %> lbs
|
||||||
|
<br><%= queue4_match.w1_bracket_name %> vs. <br>
|
||||||
|
<%= queue4_match.w2_bracket_name %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
<% cache ["#{@tournament.id}_up_matches", @tournament] do %>
|
|
||||||
<script>
|
<script>
|
||||||
// $(document).ready(function() {
|
// $(document).ready(function() {
|
||||||
// $('#matchList').dataTable();
|
// $('#matchList').dataTable();
|
||||||
@@ -42,37 +41,7 @@
|
|||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<% @mats.each.map do |m| %>
|
<% @mats.each.map do |m| %>
|
||||||
<tr>
|
<%= render "up_matches_mat_row", mat: m %>
|
||||||
<td><%= m.name %></td>
|
|
||||||
<td>
|
|
||||||
<% if m.queue1_match %><strong><%=m.queue1_match.bout_number%></strong> (<%= m.queue1_match.bracket_position %>)<br>
|
|
||||||
<%= m.queue1_match.weight_max %> lbs
|
|
||||||
<br><%= m.queue1_match.w1_bracket_name %> vs. <br>
|
|
||||||
<%= m.queue1_match.w2_bracket_name %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<% if m.queue2_match %><strong><%=m.queue2_match.bout_number%></strong> (<%= m.queue2_match.bracket_position %>)<br>
|
|
||||||
<%= m.queue2_match.weight_max %> lbs
|
|
||||||
<br><%= m.queue2_match.w1_bracket_name %> vs. <br>
|
|
||||||
<%= m.queue2_match.w2_bracket_name %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<% if m.queue3_match %><strong><%=m.queue3_match.bout_number%></strong> (<%= m.queue3_match.bracket_position %>)<br>
|
|
||||||
<%= m.queue3_match.weight_max %> lbs
|
|
||||||
<br><%= m.queue3_match.w1_bracket_name %> vs. <br>
|
|
||||||
<%= m.queue3_match.w2_bracket_name %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<% if m.queue4_match %><strong><%=m.queue4_match.bout_number%></strong> (<%= m.queue4_match.bracket_position %>)<br>
|
|
||||||
<%= m.queue4_match.weight_max %> lbs
|
|
||||||
<br><%= m.queue4_match.w1_bracket_name %> vs. <br>
|
|
||||||
<%= m.queue4_match.w2_bracket_name %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -104,4 +73,3 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<% end %>
|
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ module Wrestling
|
|||||||
config.active_record.schema_format = :ruby
|
config.active_record.schema_format = :ruby
|
||||||
config.active_record.dump_schemas = :all
|
config.active_record.dump_schemas = :all
|
||||||
|
|
||||||
# Fix deprecation warning for to_time in Rails 8.1
|
|
||||||
config.active_support.to_time_preserves_timezone = :zone
|
|
||||||
|
|
||||||
# Please, add to the `ignore` list any other `lib` subdirectories that do
|
# Please, add to the `ignore` list any other `lib` subdirectories that do
|
||||||
# not contain `.rb` files, or that should not be reloaded or eager loaded.
|
# not contain `.rb` files, or that should not be reloaded or eager loaded.
|
||||||
# Common ones are `templates`, `generators`, or `middleware`, for example.
|
# Common ones are `templates`, `generators`, or `middleware`, for example.
|
||||||
|
|||||||
84
test/controllers/up_matches_cache_test.rb
Normal file
84
test/controllers/up_matches_cache_test.rb
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class UpMatchesCacheTest < ActionController::TestCase
|
||||||
|
tests TournamentsController
|
||||||
|
|
||||||
|
setup do
|
||||||
|
create_double_elim_tournament_1_6_with_multiple_weights_and_multiple_mats(16, 4, 2)
|
||||||
|
@tournament.update!(user_id: users(:one).id)
|
||||||
|
@tournament.reset_and_fill_bout_board
|
||||||
|
|
||||||
|
sign_in users(:one)
|
||||||
|
|
||||||
|
@original_perform_caching = ActionController::Base.perform_caching
|
||||||
|
ActionController::Base.perform_caching = true
|
||||||
|
Rails.cache.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
Rails.cache.clear
|
||||||
|
ActionController::Base.perform_caching = @original_perform_caching
|
||||||
|
end
|
||||||
|
|
||||||
|
test "up_matches row fragments hit cache and invalidate when a mat queue changes" do
|
||||||
|
first_events = cache_events_for_up_matches do
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_operator cache_writes(first_events), :>, 0, "Expected initial render to write row fragments"
|
||||||
|
|
||||||
|
second_events = cache_events_for_up_matches do
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 0, cache_writes(second_events), "Expected second render to reuse cached row fragments"
|
||||||
|
assert_operator cache_hits(second_events), :>, 0, "Expected second render to have cache hits"
|
||||||
|
|
||||||
|
mat = @tournament.mats.first
|
||||||
|
mat.reload
|
||||||
|
movable_match = mat.queue2_match || mat.queue1_match
|
||||||
|
assert movable_match, "Expected at least one queued match to move"
|
||||||
|
mat.assign_match_to_queue!(movable_match, 4)
|
||||||
|
|
||||||
|
third_events = cache_events_for_up_matches do
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_operator cache_writes(third_events), :>, 0, "Expected queue change to invalidate and rewrite at least one row fragment"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cache_events_for_up_matches
|
||||||
|
events = []
|
||||||
|
subscriber = lambda do |name, _start, _finish, _id, payload|
|
||||||
|
key = payload[:key].to_s
|
||||||
|
next unless key.include?("up_matches_mat_row")
|
||||||
|
|
||||||
|
events << { name: name, hit: payload[:hit] }
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveSupport::Notifications.subscribed(
|
||||||
|
subscriber,
|
||||||
|
/cache_(read|write|fetch_hit|generate)\.active_support/
|
||||||
|
) do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
|
||||||
|
events
|
||||||
|
end
|
||||||
|
|
||||||
|
def cache_writes(events)
|
||||||
|
events.count { |event| event[:name] == "cache_write.active_support" }
|
||||||
|
end
|
||||||
|
|
||||||
|
def cache_hits(events)
|
||||||
|
events.count do |event|
|
||||||
|
event[:name] == "cache_fetch_hit.active_support" ||
|
||||||
|
(event[:name] == "cache_read.active_support" && event[:hit])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -10,5 +10,20 @@ class MatTest < ActiveSupport::TestCase
|
|||||||
assert_not mat.valid?
|
assert_not mat.valid?
|
||||||
assert_equal [:tournament, :name], mat.errors.attribute_names
|
assert_equal [:tournament, :name], mat.errors.attribute_names
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "queue_matches refreshes after queue slots change and record reloads" do
|
||||||
|
create_double_elim_tournament_1_6_with_multiple_weights_and_multiple_mats(16, 4, 1)
|
||||||
|
@tournament.reset_and_fill_bout_board
|
||||||
|
|
||||||
|
mat = @tournament.mats.first
|
||||||
|
initial_queue_ids = mat.queue_matches.map { |match| match&.id }
|
||||||
|
assert initial_queue_ids.compact.any?, "Expected initial queue to contain matches"
|
||||||
|
|
||||||
|
Mat.where(id: mat.id).update_all(queue1: nil, queue2: nil, queue3: nil, queue4: nil)
|
||||||
|
mat.reload
|
||||||
|
|
||||||
|
refreshed_queue_ids = mat.queue_matches.map { |match| match&.id }
|
||||||
|
assert_equal [nil, nil, nil, nil], refreshed_queue_ids, "Expected queue_matches to refresh after reload and slot changes"
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user