From 992138fa713b98824c73cd284acbfeaa334eb958 Mon Sep 17 00:00:00 2001
From: Paul DobbinSchmaltz
Date: Fri, 15 Nov 2024 11:54:26 -0600
Subject: [PATCH] Extract object inspection from *::Console objects
Moving object inspection into *::Console objects was an experiment in
processing optimization. But, I think it was a failed one. It just made
it too hard to see the pretty inspection results, especially when
chaining methods together in e.g. ARel queries.
Also, the Console object accessor / insulation layer was always a bit of
a doubling up on processing optimization. ObjectInspector itself has
scopes for dealing with this sort of thing, wherever necessary. For this
project, however, I can't think of any relevant cases (yet).
---
app/models/board.rb | 35 ++++++++-------
app/models/board/settings.rb | 12 ++---
app/models/calc_3bv.rb | 43 +++++++++++-------
app/models/cell.rb | 30 +++++++------
app/models/coordinates.rb | 16 +++----
app/models/game.rb | 45 +++++++++++--------
app/models/grid.rb | 35 +++++++--------
app/models/null_coordinates.rb | 5 +--
app/models/pattern.rb | 26 ++++++-----
app/models/pattern/settings.rb | 8 ++--
app/models/transactions/cell_transaction.rb | 8 ++--
app/models/transactions/game_transaction.rb | 8 ++--
.../transactions/user_update_transaction.rb | 8 ++--
app/models/user.rb | 29 ++++--------
lib/console_object_behaviors.rb | 4 --
15 files changed, 155 insertions(+), 157 deletions(-)
diff --git a/app/models/board.rb b/app/models/board.rb
index d1cb51de..b55ceeb2 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -93,6 +93,24 @@ def validate_settings
errors.merge!(settings.errors)
end
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = identify
+
+ def inspect_info(scope:)
+ scope.join_info([
+ "#{Emoji.cell} x#{cells_count} (#{dimensions})",
+ "#{Emoji.revealed_cell} #{revealed_cells_count}",
+ "#{Emoji.mine} #{mines}",
+ "#{Emoji.flag} #{flags_count}",
+ ])
+ end
+
+ def cells_count = cells.size
+ def revealed_cells_count = cells.count(&:revealed?)
+ end
+
# Board::Console acts like a {Board} but otherwise handles IRB
# Console-specific methods/logic.
class Console
@@ -126,22 +144,5 @@ def reset!
self
end
-
- private
-
- def inspect_info(scope:)
- scope.join_info([
- "#{Emoji.cell} x#{cells_count} (#{dimensions})",
- "#{Emoji.revealed_cell} #{revealed_cells_count}",
- "#{Emoji.mine} #{mines}",
- "#{Emoji.flag} #{flags_count}",
- ])
- end
-
- def cells_count = cells.size
-
- def revealed_cells_count
- cells.count(&:revealed?)
- end
end
end
diff --git a/app/models/board/settings.rb b/app/models/board/settings.rb
index 012c85f5..75e55322 100644
--- a/app/models/board/settings.rb
+++ b/app/models/board/settings.rb
@@ -23,8 +23,6 @@ class Board::Settings
include ActiveModel::Model
include ActiveModel::Attributes
- include ObjectInspector::InspectorsHelper
-
attribute :type, :string
attribute :name, :string
attribute :width, :integer, default: -> { RANGES.fetch(:width).begin }
@@ -118,11 +116,13 @@ def to_h = { type:, name:, width:, height:, mines: }.tap(&:compact!)
def as_json = to_h
def to_a = to_h.values
- private
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- def inspect_identification = identify(:width, :height, :mines)
+ def inspect_identification = identify(:width, :height, :mines)
- def inspect_name
- pattern? ? "#{type} (#{name.inspect})" : type
+ def inspect_name
+ pattern? ? "#{type} (#{name.inspect})" : type
+ end
end
end
diff --git a/app/models/calc_3bv.rb b/app/models/calc_3bv.rb
index fa03d404..9f08bb55 100644
--- a/app/models/calc_3bv.rb
+++ b/app/models/calc_3bv.rb
@@ -42,12 +42,17 @@ def process_cells
def count = cells.sum(&:count)
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = identify(:grid)
+ end
+
# :reek:InstanceVariableAssumption
# Calc3BV::Cell wraps {Cell} for performing 3BV scoring functions.
class Cell
include WrapMethodBehaviors
- include ObjectInspector::InspectorsHelper
delegate_missing_to :to_model
@@ -94,17 +99,21 @@ def count = @count.to_i
attr_reader :calculator
- def inspect_flags(scope:)
- scope.join_flags([
- (Emoji.mine if mine?),
- (visited? ? Emoji.eyes : "🙈"),
- ])
- end
-
- def inspect_name = @count.inspect
-
def neighbors = calculator.cells_at(neighboring_coordinates)
def neighboring_coordinates = coordinates.neighbors
+
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_flags(scope:)
+ scope.join_flags([
+ (Emoji.mine if mine?),
+ (visited? ? Emoji.eyes : "🙈"),
+ ])
+ end
+
+ def inspect_name = @count.inspect
+ end
end
# Calc3BV::Console acts like a {Calc3BV} but otherwise handles IRB
@@ -113,8 +122,7 @@ class Console
include ConsoleObjectBehaviors
# @example
- # calc = Calc3BV.new(Board.last.grid).cons
- # calc.call
+ # Calc3BV.new(Board.last.grid).cons.call
def call
process_cells
count
@@ -129,17 +137,18 @@ def process_cells
# Show where the clicks came from.
#
# @example
- # calc = Calc3BV.new(Board.last.grid).cons
- # calc.call
- # calc.render # Compare to `calc.grid.render`
+ # # Compare output against `calc.grid.render`:
+ # Calc3BV.new(Board.last.grid).cons.render
def render
cells.map(&:count).in_groups_of(grid.columns_count)
end
def grid = super.console
- private
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- def inspect_identification = identify(:grid, klass: __class__)
+ def inspect_identification = identify(:grid, klass: __class__)
+ end
end
end
diff --git a/app/models/cell.rb b/app/models/cell.rb
index 586c9a0d..5e77699b 100644
--- a/app/models/cell.rb
+++ b/app/models/cell.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
# :reek:TooManyMethods
+# :reek:RepeatedConditional
# Cell represents a clickable position on the {Board}. Cells:
# - may secretly contain a mine
@@ -141,19 +142,10 @@ def neighboring_flags_count
@neighboring_flags_count ||= neighbors.count(&:flagged?)
end
- # Cell::Console acts like a {Cell} but otherwise handles IRB Console-specific
- # methods/logic.
- class Console
- include ConsoleObjectBehaviors
-
- def coordinates = super.console
- def neighbors = super.map(&:console)
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- def render(cells_count: nil)
- "#{current_state}#{coordinates.console.render(cells_count:)}"
- end
-
- private
+ def inspect_identification = identify
def inspect_flags(scope:)
scope.join_flags([
@@ -168,8 +160,20 @@ def inspect_issues
"INCORRECTLY_FLAGGED" if incorrectly_flagged?
end
- def inspect_info = coordinates.console
+ def inspect_info = coordinates
def inspect_name = value.inspect
+ end
+
+ # Cell::Console acts like a {Cell} but otherwise handles IRB Console-specific
+ # methods/logic.
+ class Console
+ include ConsoleObjectBehaviors
+
+ def render(cells_count: value)
+ "#{current_state}#{coordinates.console.render(cells_count:)}"
+ end
+
+ private
def current_state
if revealed?
diff --git a/app/models/coordinates.rb b/app/models/coordinates.rb
index d0175f68..09995ac5 100644
--- a/app/models/coordinates.rb
+++ b/app/models/coordinates.rb
@@ -45,6 +45,14 @@ def to_a
[x, y]
end
+ def to_s
+ inspect
+ end
+
+ def inspect
+ "(#{x}, #{y})"
+ end
+
# Coordinates::Console acts like a {Coordinates} but otherwise handles IRB
# Console-specific methods/logic.
class Console
@@ -59,16 +67,8 @@ def render(cells_count:)
"(#{pad(x, cells_count:)}, #{pad(y, cells_count:)})"
end
- def to_s
- inspect
- end
-
private
- def inspect
- "(#{x}, #{y})"
- end
-
def pad(value, cells_count:)
return value if cells_count <= BEGINNER_DIFFICULTY_LEVEL_CELLS_COUNT
diff --git a/app/models/game.rb b/app/models/game.rb
index a6e3b5e9..56c0c657 100644
--- a/app/models/game.rb
+++ b/app/models/game.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
# :reek:TooManyConstants
+# :reek:TooManyMethods
# Game represents a game of Minesweeper Alliance. It handles creation of new
# Games and keeps track of the {#status} of each Game in the database, win or
@@ -190,6 +191,31 @@ def set_stats
CalcStats.(self)
end
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = identify
+
+ def inspect_flags(scope:)
+ scope.join_flags([
+ type,
+ status,
+ ])
+ end
+
+ def inspect_info(scope:)
+ return unless score || bbbv || efficiency
+
+ scope.join_info([
+ "Score: #{score.inspect}",
+ "3BV: #{bbbv.inspect}",
+ "Efficiency: #{efficiency.inspect}",
+ ])
+ end
+
+ def inspect_name = display_id
+ end
+
# Game::CalcStats determines and updates the given {Game} object with relevant
# statistical values (on {Game} end).
class CalcStats
@@ -268,25 +294,6 @@ def reset!
private
- def inspect_flags(scope:)
- scope.join_flags([
- type,
- status,
- ])
- end
-
- def inspect_info(scope:)
- return unless score || bbbv || efficiency
-
- scope.join_info([
- "Score: #{score.inspect}",
- "3BV: #{bbbv.inspect}",
- "Efficiency: #{efficiency.inspect}",
- ])
- end
-
- def inspect_name = display_id
-
# :reek:TooManyStatements
def do_reset
check_for_current_game
diff --git a/app/models/grid.rb b/app/models/grid.rb
index 5b9f1dd0..2fd26075 100644
--- a/app/models/grid.rb
+++ b/app/models/grid.rb
@@ -19,6 +19,7 @@ def initialize(cells, context: nil)
end
def cells_count = cells.size
+ def rows_count = count
def columns_count = first.size
# rubocop:disable Layout/LineLength
@@ -58,6 +59,20 @@ def organizer
context&.transpose? ? TRANSPOSE_ORGANIZER : STANDARD_ORGANIZER
end
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = self.class.name
+
+ def inspect_info
+ "#{Emoji.cell} x#{cells_count} (#{dimensions})"
+ end
+
+ def dimensions
+ "#{rows_count}x#{columns_count}"
+ end
+ end
+
# rubocop:enable Layout/LineLength
# Grid::Console acts like a {Grid} but otherwise handles IRB Console-specific
@@ -65,16 +80,6 @@ def organizer
class Console
include ConsoleObjectBehaviors
- def cells = super.map(&:console)
-
- def to_h
- super.transform_values { |row| row.map(&:console) }
- end
-
- def to_a
- super.map { |row| row.map(&:console) }
- end
-
# @example
# 0 => ◻️ (0, 0) ◻️ (1, 0) ◻️ (2, 0)
# 1 => ◻️ (0, 1) ◻️ (1, 1) ◻️ (2, 1)
@@ -89,16 +94,6 @@ def render
private
- def inspect_identification = __model__.class.name
-
- def inspect_info
- "#{Emoji.cell} x#{cells_count} (#{dimensions})"
- end
-
- def dimensions
- "#{count}x#{to_a.first.size}"
- end
-
# rubocop:disable Rails/Output
def render_row(y:, row:)
print "#{pad(y)}: "
diff --git a/app/models/null_coordinates.rb b/app/models/null_coordinates.rb
index a60e24e2..5d9abd4b 100644
--- a/app/models/null_coordinates.rb
+++ b/app/models/null_coordinates.rb
@@ -11,11 +11,10 @@ def y = nil
def neighbors = []
def to_h = {}
def to_json(*) = "{}"
+ def to_s = inspect
+ def render = inspect
def inspect
"(nil, nil)"
end
-
- def to_s = inspect
- def render = inspect
end
diff --git a/app/models/pattern.rb b/app/models/pattern.rb
index 9bd660b8..6744c4c0 100644
--- a/app/models/pattern.rb
+++ b/app/models/pattern.rb
@@ -17,8 +17,6 @@
class Pattern < ApplicationRecord
self.implicit_order_column = "created_at"
- include ObjectInspector::InspectorsHelper
-
attribute :coordinates_array, Type::CoordinatesArray.new
validates :name,
@@ -73,18 +71,24 @@ def reset
private
- def inspect_info(scope:)
- scope.join_info([
- dimensions,
- "#{Emoji.flag} x#{flags_count}",
- ])
- end
-
- def inspect_name = name
-
def validate_settings
return if settings.valid?
errors.merge!(settings.errors)
end
+
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = identify
+
+ def inspect_info(scope:)
+ scope.join_info([
+ dimensions,
+ "#{Emoji.flag} x#{flags_count}",
+ ])
+ end
+
+ def inspect_name = name
+ end
end
diff --git a/app/models/pattern/settings.rb b/app/models/pattern/settings.rb
index 77c78065..3f714c39 100644
--- a/app/models/pattern/settings.rb
+++ b/app/models/pattern/settings.rb
@@ -11,8 +11,6 @@ class Pattern::Settings
include ActiveModel::Model
include ActiveModel::Attributes
- include ObjectInspector::InspectorsHelper
-
attribute :width, :integer, default: -> { RANGES.fetch(:width).begin }
attribute :height, :integer, default: -> { RANGES.fetch(:height).begin }
@@ -43,7 +41,9 @@ def to_h = { width:, height: }
def to_a = to_h.values
def as_json = to_h
- private
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- def inspect_identification = identify(:width, :height)
+ def inspect_identification = identify(:width, :height)
+ end
end
diff --git a/app/models/transactions/cell_transaction.rb b/app/models/transactions/cell_transaction.rb
index d6937cd3..81b1bd71 100644
--- a/app/models/transactions/cell_transaction.rb
+++ b/app/models/transactions/cell_transaction.rb
@@ -39,12 +39,10 @@ def self.exists_between?(user:, cell:)
for_user(user).for_cell(cell).exists?
end
- # CellTransaction::Console acts like a {CellTransaction} but otherwise handles
- # IRB Console-specific methods/logic.
- class Console
- include ConsoleObjectBehaviors
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- private
+ def inspect_identification = identify
def inspect_info
[
diff --git a/app/models/transactions/game_transaction.rb b/app/models/transactions/game_transaction.rb
index 9c23c6ba..87f610e3 100644
--- a/app/models/transactions/game_transaction.rb
+++ b/app/models/transactions/game_transaction.rb
@@ -32,12 +32,10 @@ def self.exists_between?(user:, game:)
for_user(user).for_game(game).exists?
end
- # GameTransaction::Console acts like a {GameTransaction} but otherwise handles
- # IRB Console-specific methods/logic.
- class Console
- include ConsoleObjectBehaviors
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- private
+ def inspect_identification = identify
def inspect_info
[
diff --git a/app/models/transactions/user_update_transaction.rb b/app/models/transactions/user_update_transaction.rb
index 6d000c4b..42f94b81 100644
--- a/app/models/transactions/user_update_transaction.rb
+++ b/app/models/transactions/user_update_transaction.rb
@@ -21,12 +21,10 @@ def self.create_for(user:, change_set:)
user.user_update_transactions.create!(change_set:)
end
- # UserUpdateTransaction::Console acts like a {UserUpdateTransaction} but
- # otherwise handles IRB Console-specific methods/logic.
- class Console
- include ConsoleObjectBehaviors
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
- private
+ def inspect_identification = identify
def inspect_info
[
diff --git a/app/models/user.rb b/app/models/user.rb
index bf831f74..9d999aa0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -72,6 +72,15 @@ def completed_games_count
def bests = @bests ||= Bests.new(self)
+ concerning :ObjectInspection do
+ include ObjectInspector::InspectorsHelper
+
+ def inspect_identification = identify(:truncated_id)
+ def truncated_id = id[TRUNCATED_ID_RANGE]
+
+ def inspect_info = time_zone
+ end
+
# User::Bests is a specialization on User for finding "best" (e.g.
# top-scoring) {Game}s.
class Bests
@@ -100,24 +109,4 @@ def _score_arel = games.by_score_asc
def _bbbvps_arel = games.by_bbbvps_desc
def _efficiency_arel = games.by_efficiency_desc
end
-
- # User::Console acts like a {User} but otherwise handles IRB Console-specific
- # methods/logic.
- class Console
- TRUNCATED_ID_RANGE = (-7..)
-
- include ConsoleObjectBehaviors
-
- private
-
- def inspect_identification
- identify(:truncated_id, klass: __class__)
- end
-
- def inspect_info
- time_zone
- end
-
- def truncated_id = id[TRUNCATED_ID_RANGE]
- end
end
diff --git a/lib/console_object_behaviors.rb b/lib/console_object_behaviors.rb
index 0b5bfe88..d66a2826 100644
--- a/lib/console_object_behaviors.rb
+++ b/lib/console_object_behaviors.rb
@@ -8,8 +8,6 @@
module ConsoleObjectBehaviors
extend ActiveSupport::Concern
- include ObjectInspector::InspectorsHelper
-
included do
# *::Console::Error represents any StandardError related to Console
# processing on the including object.
@@ -65,6 +63,4 @@ def method_missing(...)
def respond_to_missing?(method, include_private = true)
__model__.respond_to?(method, include_private) || super
end
-
- def inspect_identification(...) = __model__.identify(...)
end