Skip to content

Commit

Permalink
added IndividualRecord with specs; improved skeleton models for futur…
Browse files Browse the repository at this point in the history
…e GoggleCups implementation;
  • Loading branch information
steveoro committed Apr 24, 2024
1 parent fea59d4 commit 1da928a
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

_Please, add the latest build info on top of the list; use Version::MAJOR only after gold release; keep semantic versioning in line with framework's_

- **0.7.10** [Steve A.] added IndividualRecord with specs; improved skeleton models for future GoggleCups implementation;
- **0.7.09** [Steve A.] SwimmerStat query fix: wasn't getting the proper min FIN score right; split fulltext indexes for Meeting, UserWorkshop & Team: search individual columns instead of groups to yield better results
- **0.7.08** [Steve A.] added some delegation helpers to Badge; added triggers and events to MariaDB dump file generated by "db:dump" (even if not currently used); minor rubocop fixes & bundle updates
- **0.7.06** [Steve A.] query fix for SwimmerStat
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
goggles_db (0.7.09)
goggles_db (0.7.10)
acts-as-taggable-on
acts_as_votable
cities
Expand Down
9 changes: 6 additions & 3 deletions app/models/goggles_db/goggle_cup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

module GogglesDb
#
# = GoggleCup model
# = GogglesDb::GoggleCup
#
# - version: 7.030
# - author: Steve A.
# - version: 7-0.7.10
# - author: Steve A.
#
class GoggleCup < ApplicationRecord
self.table_name = 'goggle_cups'

belongs_to :team
validates_associated :team

# TODO
end
end
12 changes: 9 additions & 3 deletions app/models/goggles_db/goggle_cup_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

module GogglesDb
#
# = GoggleCupDefinition model
# = GogglesDb::GoggleCupStandard
#
# - version: 7.030
# - author: Steve A.
# - version: 7-0.7.10
# - author: Steve A.
#
class GoggleCupDefinition < ApplicationRecord
self.table_name = 'goggle_cup_definitions'

belongs_to :goggle_cup
belongs_to :season

validates_associated :goggle_cup
validates_associated :season

# TODO
end
end
33 changes: 30 additions & 3 deletions app/models/goggles_db/goggle_cup_standard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,41 @@

module GogglesDb
#
# = GoggleCupStandard model
# = GogglesDb::GoggleCupStandard
#
# - version: 7.030
# - author: Steve A.
# - version: 7-0.7.10
# - author: Steve A.
#
class GoggleCupStandard < ApplicationRecord
self.table_name = 'goggle_cup_standards'

include TimingManageable

belongs_to :swimmer
belongs_to :goggle_cup
belongs_to :pool_type
belongs_to :event_type

validates_associated :swimmer
validates_associated :goggle_cup
validates_associated :pool_type
validates_associated :event_type

validates :minutes, presence: { length: { within: 1..3, allow_nil: false } }, numericality: true
validates :seconds, presence: { length: { within: 1..2, allow_nil: false } }, numericality: true
validates :hundredths, presence: { length: { within: 1..2, allow_nil: false } }, numericality: true
validates :reaction_time, presence: true, numericality: true

default_scope { includes(:swimmer, :goggle_cup, :pool_type, :event_type) }

delegate :first_name, :last_name, :complete_name, :year_of_birth, to: :swimmer, prefix: true
delegate :name, :editable_name, to: :team, prefix: true

delegate :team, to: :goggle_cup, prefix: false
delegate :length_in_meters, to: :event_type, prefix: false
#-- ------------------------------------------------------------------------
#++

# TODO
end
end
109 changes: 109 additions & 0 deletions app/models/goggles_db/individual_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# frozen_string_literal: true

module GogglesDb
#
# = GogglesDb::IndividualRecord
#
# - version: 7-0.7.10
# - author: Steve A.
#
class IndividualRecord < ApplicationRecord
self.table_name = 'individual_records'

include TimingManageable

belongs_to :swimmer
belongs_to :team
validates_associated :swimmer
validates_associated :team

belongs_to :pool_type
belongs_to :event_type
belongs_to :category_type
belongs_to :gender_type
belongs_to :season
belongs_to :federation_type
belongs_to :record_type

belongs_to :meeting_individual_result, optional: true

validates_associated :pool_type
validates_associated :event_type
validates_associated :category_type
validates_associated :gender_type
validates_associated :season
validates_associated :federation_type
validates_associated :record_type

validates :minutes, presence: { length: { within: 1..3, allow_nil: false } }, numericality: true
validates :seconds, presence: { length: { within: 1..2, allow_nil: false } }, numericality: true
validates :hundredths, presence: { length: { within: 1..2, allow_nil: false } }, numericality: true

has_one :season_type, through: :season

default_scope do
includes(
:swimmer, :team,
:pool_type, :event_type, :gender_type, :season, :season_type, :federation_type,
:record_type
)
end

delegate :first_name, :last_name, :complete_name, :year_of_birth, to: :swimmer, prefix: true
delegate :name, :editable_name, to: :team, prefix: true
delegate :length_in_meters, to: :event_type, prefix: false

# Sorting scopes:
scope :by_timing, lambda { |dir = :asc|
order(
Arel.sql('minutes * 6000 + seconds * 100 + hundredths') => dir.to_s.downcase.to_sym
# Using an all in one computed column with Arel for ordering is about the same order of speed
# than using 3 separate as (minutes: :desc, seconds: :desc, hundredths: :desc), but
# yields slightly faster results a bit more often. (Tested with benchmarks on real data)
)
}

# Filtering scopes:
scope :for_pool_type, ->(pool_type) { joins(:pool_type).where('pool_types.id': pool_type.id) }
scope :for_event_type, ->(event_type) { joins(:event_type).where(event_type_id: event_type.id) }
scope :for_season, ->(season) { joins(:season).where(season_id: season.id) }
scope :for_swimmer, ->(swimmer) { joins(:swimmer).where(swimmer_id: swimmer.id) }
#-- ------------------------------------------------------------------------
#++

# Override: returns the list of single association names (as symbols)
# included by <tt>#to_hash</tt> (and, consequently, by <tt>#to_json</tt>).
#
def single_associations
%w[swimmer team record_type pool_type event_type category_type gender_type season season_type federation_type]
end

# Override: include some of the decorated fields in the output.
#
def minimal_attributes(locale = I18n.locale)
super(locale).merge(
'timing' => to_timing.to_s,
'swimmer_name' => swimmer.complete_name,
'swimmer_label' => swimmer.decorate.display_label(locale),
'team_name' => team.editable_name,
'team_label' => team.decorate.display_label,
'event_label' => event_type.label(locale),
'category_label' => category_type.decorate.short_label,
'category_code' => category_type.code,
'gender_code' => gender_type.code
)
end

# Returns a commodity Hash summarizing the associated Swimmer.
def swimmer_attributes
{
'id' => swimmer_id,
'complete_name' => swimmer&.complete_name,
'last_name' => swimmer&.last_name,
'first_name' => swimmer&.first_name,
'year_of_birth' => swimmer&.year_of_birth,
'year_guessed' => swimmer&.year_guessed
}
end
end
end
9 changes: 5 additions & 4 deletions app/models/goggles_db/meeting_individual_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

module GogglesDb
#
# = MeetingIndividualResult model
# = GogglesDb::MeetingIndividualResult
#
# - version: 7-0.6.30
# - author: Steve A.
# - version: 7-0.7.10
# - author: Steve A.
#
class MeetingIndividualResult < AbstractResult
self.table_name = 'meeting_individual_results'
Expand All @@ -31,6 +31,8 @@ class MeetingIndividualResult < AbstractResult
belongs_to :team
validates_associated :team

has_many :individual_records, inverse_of: :meeting_individual_result

default_scope do
includes(
:swimmer, :team, :category_type, :gender_type,
Expand Down Expand Up @@ -85,7 +87,6 @@ class MeetingIndividualResult < AbstractResult
# TODO: CLEAR UNUSED
# scope :season_type_bests, -> { where(season_type_best: true) }
# scope :for_season_type, ->(season_type) { joins(:season_type).where(['season_types.id = ?', season_type.id]) }
# scope :for_team, ->(team) { where(team_id: team.id) }
# scope :for_category_type, ->(category_type) { joins(:category_type).where(['category_types.id = ?', category_type.id]) }
# scope :for_category_code, ->(category_code) { joins(:category_type).where(['category_types.code = ?', category_code]) }
# scope :for_date_range, ->(date_begin, date_end) { joins(:meeting).where(['meetings.header_date between ? and ?', date_begin, date_end]) }
Expand Down
5 changes: 3 additions & 2 deletions app/models/goggles_db/swimmer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

module GogglesDb
#
# = Swimmer model
# = GogglesDb::Swimmer
#
# - version: 7-0.7.09
# - version: 7-0.7.10
# - author: Steve A.
#
class Swimmer < ApplicationRecord
Expand Down Expand Up @@ -33,6 +33,7 @@ class Swimmer < ApplicationRecord
has_many :meeting_relay_results, through: :meeting_relay_swimmers
has_many :user_results, dependent: :delete_all
has_many :user_laps, dependent: :delete_all
has_many :individual_records, dependent: :delete_all

validates :complete_name, presence: { length: { within: 1..100, allow_nil: false } }
validates :last_name, length: { maximum: 50 }
Expand Down
2 changes: 2 additions & 0 deletions app/models/goggles_db/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class Team < ApplicationRecord
has_many :season_types, through: :team_affiliations

has_many :managed_affiliations, through: :team_affiliations
has_many :individual_records, dependent: :delete_all

# has_many :meeting_individual_results
# has_many :meetings, through: :meeting_individual_results
# has_many :meeting_relay_results
Expand Down
6 changes: 3 additions & 3 deletions lib/goggles_db/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
module GogglesDb
# Public gem version (uses Semantic versioning)
VERSION = '0.7.09'
VERSION = '0.7.10'

# == Versioning codes
#
Expand All @@ -19,8 +19,8 @@ module Version
CORE = 'C7'
MAJOR = '0'
MINOR = '7'
PATCH = '09'
BUILD = '20240415'
PATCH = '10'
BUILD = '20240424'

# Full label
FULL = "#{MAJOR}.#{MINOR}.#{PATCH} (#{CORE}-#{BUILD})".freeze
Expand Down
22 changes: 22 additions & 0 deletions spec/factories/goggles_db/individual_records.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FactoryBot.define do
factory :individual_record, class: 'GogglesDb::IndividualRecord' do
before_create_validate_instance

meeting_individual_result { GogglesDb::MeetingIndividualResult.last(150).sample }

swimmer { meeting_individual_result.swimmer }
team { meeting_individual_result.team }

pool_type { meeting_individual_result.pool_type }
event_type { meeting_individual_result.event_type }
category_type { meeting_individual_result.category_type }
gender_type { meeting_individual_result.gender_type }
season { meeting_individual_result.season }
federation_type { meeting_individual_result.federation_type }
record_type { GogglesDb::RecordType.first(3).sample }

minutes { 0 }
seconds { ((rand * 59) % 59).to_i } # Forced not to use 59
hundredths { ((rand * 99) % 99).to_i } # Forced not to use 99
end
end
Loading

0 comments on commit 1da928a

Please sign in to comment.