scrap_cbf_record 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/scrap_cbf_record.rb +72 -0
- data/lib/scrap_cbf_record/active_record.rb +105 -0
- data/lib/scrap_cbf_record/active_records/base.rb +196 -0
- data/lib/scrap_cbf_record/active_records/matches.rb +80 -0
- data/lib/scrap_cbf_record/active_records/rankings.rb +70 -0
- data/lib/scrap_cbf_record/active_records/rounds.rb +60 -0
- data/lib/scrap_cbf_record/active_records/teams.rb +42 -0
- data/lib/scrap_cbf_record/config.rb +217 -0
- data/lib/scrap_cbf_record/configs/base.rb +258 -0
- data/lib/scrap_cbf_record/configs/championship.rb +97 -0
- data/lib/scrap_cbf_record/configs/match.rb +164 -0
- data/lib/scrap_cbf_record/configs/ranking.rb +152 -0
- data/lib/scrap_cbf_record/configs/round.rb +113 -0
- data/lib/scrap_cbf_record/configs/team.rb +99 -0
- data/lib/scrap_cbf_record/errors.rb +83 -0
- data/lib/scrap_cbf_record/logger.rb +20 -0
- data/lib/scrap_cbf_record/models/base.rb +16 -0
- data/lib/scrap_cbf_record/models/championship.rb +28 -0
- data/lib/scrap_cbf_record/models/concerns/active_record_relation.rb +37 -0
- data/lib/scrap_cbf_record/models/match.rb +71 -0
- data/lib/scrap_cbf_record/models/ranking.rb +58 -0
- data/lib/scrap_cbf_record/models/round.rb +54 -0
- data/lib/scrap_cbf_record/models/team.rb +22 -0
- data/lib/scrap_cbf_record/version.rb +5 -0
- metadata +170 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
class Config
|
5
|
+
# Team settings
|
6
|
+
class Team < Base
|
7
|
+
class << self
|
8
|
+
# Default settings
|
9
|
+
#
|
10
|
+
# @return [Hash]
|
11
|
+
def default
|
12
|
+
{
|
13
|
+
class_name: 'Team',
|
14
|
+
rename_attrs: {},
|
15
|
+
exclude_attrs_on_create: %i[],
|
16
|
+
exclude_attrs_on_update: %i[],
|
17
|
+
associations: {}
|
18
|
+
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Settings use by the system
|
23
|
+
# Not configurable
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
26
|
+
def required
|
27
|
+
{ must_exclude_attrs: %i[] }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Record Attributes
|
31
|
+
# It must match with ScrapCbf
|
32
|
+
#
|
33
|
+
# @return [Array]
|
34
|
+
def record_attrs
|
35
|
+
%i[
|
36
|
+
name
|
37
|
+
state
|
38
|
+
avatar_url
|
39
|
+
]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :class_name,
|
44
|
+
:rename_attrs,
|
45
|
+
:exclude_attrs_on_create,
|
46
|
+
:exclude_attrs_on_update,
|
47
|
+
:associations
|
48
|
+
|
49
|
+
# Starts the settings with default
|
50
|
+
#
|
51
|
+
# @return [nil]
|
52
|
+
def initialize
|
53
|
+
@class_name = default_class_name
|
54
|
+
@rename_attrs = default_rename_attrs
|
55
|
+
@exclude_attrs_on_create = default_exclude_attrs_on_create
|
56
|
+
@exclude_attrs_on_update = default_exclude_attrs_on_update
|
57
|
+
@associations = default_associations
|
58
|
+
|
59
|
+
ScrapCbfRecord::Team.config = self
|
60
|
+
|
61
|
+
super(*configs)
|
62
|
+
end
|
63
|
+
|
64
|
+
# These method receives the users settings
|
65
|
+
# Missing settings are left as default
|
66
|
+
#
|
67
|
+
# @param [config] Hash contaning the settings
|
68
|
+
# @return [nil]
|
69
|
+
def config=(config)
|
70
|
+
raise ::ArgumentError, 'config must be a Hash' unless config.is_a?(Hash)
|
71
|
+
|
72
|
+
@class_name = config[:class_name] if config[:class_name]
|
73
|
+
@rename_attrs = config[:rename_attrs] if config[:rename_attrs]
|
74
|
+
if config[:exclude_attrs_on_create]
|
75
|
+
@exclude_attrs_on_create = config[:exclude_attrs_on_create]
|
76
|
+
end
|
77
|
+
if config[:exclude_attrs_on_update]
|
78
|
+
@exclude_attrs_on_update = config[:exclude_attrs_on_update]
|
79
|
+
end
|
80
|
+
@associations = config[:associations] if config[:associations]
|
81
|
+
|
82
|
+
super(*configs)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return the configurable settings
|
86
|
+
#
|
87
|
+
# @return [Array]
|
88
|
+
def configs
|
89
|
+
[
|
90
|
+
@class_name,
|
91
|
+
@rename_attrs,
|
92
|
+
@exclude_attrs_on_create,
|
93
|
+
@exclude_attrs_on_update,
|
94
|
+
@associations
|
95
|
+
]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Base error for all ScrapCbf errors.
|
5
|
+
class BaseError < ::StandardError; end
|
6
|
+
|
7
|
+
# Raise when error occurs while decoding
|
8
|
+
class JsonDecodeError < BaseError
|
9
|
+
def initialize(argument)
|
10
|
+
super(argument)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Raise when missing a Hash key
|
15
|
+
class MissingKeyError < BaseError
|
16
|
+
def initialize(arg)
|
17
|
+
message = "Hash missing required key: #{arg}"
|
18
|
+
super(message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Raise when a validation error is found
|
23
|
+
class ActiveRecordValidationError < BaseError
|
24
|
+
def initialize
|
25
|
+
message = 'An error raised while saving records.' \
|
26
|
+
' Check the log for more details'
|
27
|
+
super(message)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Raise when the championship instance is not found on database
|
32
|
+
class ChampionshipInstanceNotFoundError < BaseError
|
33
|
+
def initialize(year)
|
34
|
+
message = "The Championship instance for year #{year}" \
|
35
|
+
' was not found on database. Check if the values are right' \
|
36
|
+
' or the instance exist on database, before saving records'
|
37
|
+
|
38
|
+
super(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class RecordClassNotDefinedError < BaseError
|
43
|
+
def initialize(record)
|
44
|
+
message = "The record class #{record.class_name}" \
|
45
|
+
' was not defined. Check if the class exist or is being loaded'
|
46
|
+
|
47
|
+
super(message)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class RecordAssociationAttributeNotDefinedError < BaseError
|
52
|
+
def initialize(record, attribute)
|
53
|
+
message = "The record class #{record.class_name}" \
|
54
|
+
" has not defined the attribute #{attribute}." \
|
55
|
+
" If you don't want define this attribute," \
|
56
|
+
' remove it from the config associations.'
|
57
|
+
|
58
|
+
super(message)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class RecordAttributeNotDefinedError < BaseError
|
63
|
+
def initialize(record, attribute)
|
64
|
+
message = "The record class #{record.class}" \
|
65
|
+
" has not defined the attribute #{attribute}." \
|
66
|
+
" If you don't want define this attribute," \
|
67
|
+
' add it to the config lists of excludes on create and update.'
|
68
|
+
|
69
|
+
super(message)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class RecordRenameAttributeNotDefinedError < BaseError
|
74
|
+
def initialize(record, attribute)
|
75
|
+
message = "The record class #{record.class}" \
|
76
|
+
" has not defined the renamed attribute #{attribute}." \
|
77
|
+
' Check if you write the attribute name correct, or' \
|
78
|
+
' if you don\'t want rename, remove it from the config list rename attrs.'
|
79
|
+
|
80
|
+
super(message)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/logger'
|
4
|
+
require 'active_support/tagged_logging'
|
5
|
+
|
6
|
+
class ScrapCbfRecord
|
7
|
+
class TagLogger
|
8
|
+
class << self
|
9
|
+
attr_writer :logger
|
10
|
+
|
11
|
+
def logger
|
12
|
+
@logger ||= ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_context(tags, message)
|
16
|
+
logger.tagged(*tags) { logger.info message }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Base class for the models abstractions
|
5
|
+
class Base
|
6
|
+
class << self
|
7
|
+
# Create a instance for the real model, the one used by the user
|
8
|
+
#
|
9
|
+
# @param [args] arguments passed to new instance
|
10
|
+
# @return [Object] the instance model
|
11
|
+
def new(args)
|
12
|
+
@config.klass.new(args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Abstraction for the class Championship
|
5
|
+
class Championship < Base
|
6
|
+
class << self
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
def find_by!(attributes)
|
10
|
+
year = attributes[:year]
|
11
|
+
associate = attributes[:associate]
|
12
|
+
|
13
|
+
# if associate is nil, that means self is calling this method
|
14
|
+
instance = if associate.nil? || associate
|
15
|
+
@config.klass.find_by(
|
16
|
+
"#{@config.searchable_attr(:year)}": year
|
17
|
+
)
|
18
|
+
else
|
19
|
+
year
|
20
|
+
end
|
21
|
+
|
22
|
+
raise ChampionshipInstanceNotFoundError, year unless instance
|
23
|
+
|
24
|
+
instance
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# This class helps with the communication between models association
|
5
|
+
class ActiveRecordRelation
|
6
|
+
# @param [association_class] the class associated that will be searched
|
7
|
+
# @param [associate] boolean true if associate, false if it's not
|
8
|
+
# @return [ActiveRecordRelation]
|
9
|
+
def initialize(association_class, associate)
|
10
|
+
@association_class = association_class
|
11
|
+
@associate = associate
|
12
|
+
end
|
13
|
+
|
14
|
+
# Searchs on the association. Dependes on the associate value,
|
15
|
+
# the search on db will be made if more or less arguments, or none.
|
16
|
+
# be made on database level. If it's not, it may be using
|
17
|
+
#
|
18
|
+
# @param [attributes] hash contaning the attributes use to search
|
19
|
+
# @return [Object] return the obj found on db or their identifier
|
20
|
+
def find_by(attributes)
|
21
|
+
attributes[:associate] = @associate
|
22
|
+
@association_class.send __method__, attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
# Searchs on the association. Dependes on the associate value,
|
26
|
+
# the search on db will be made if more or less arguments, or none.
|
27
|
+
# be made on database level. If it's not, it may be using
|
28
|
+
#
|
29
|
+
# @note Raises a exception if not found
|
30
|
+
# @param [attributes] hash contaning the attributes use to search
|
31
|
+
# @return [Object] return the obj found on db or their identifier
|
32
|
+
def find_by!(attributes)
|
33
|
+
attributes[:associate] = @associate
|
34
|
+
@association_class.send __method__, attributes
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Abstraction for the class Match
|
5
|
+
class Match < Base
|
6
|
+
class << self
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
def championship
|
10
|
+
ActiveRecordRelation.new(
|
11
|
+
Championship,
|
12
|
+
@config.championship_associate?
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def round
|
17
|
+
ActiveRecordRelation.new(
|
18
|
+
Round,
|
19
|
+
@config.round_associate?
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def team
|
24
|
+
ActiveRecordRelation.new(
|
25
|
+
Team,
|
26
|
+
@config.team_associate?
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def opponent
|
31
|
+
ActiveRecordRelation.new(
|
32
|
+
Team,
|
33
|
+
@config.opponent_associate?
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Find the current model on db. If current model is associate
|
38
|
+
# to championship, the attribute serie is not need, as the
|
39
|
+
# association can be used as a unique identifer for the model.
|
40
|
+
#
|
41
|
+
# @param attributes [Hash] the attrs used to find on db
|
42
|
+
# @return [Object, nil] returns Object if find, else nil
|
43
|
+
def find_by(attributes)
|
44
|
+
id_match = attributes[:id_match]
|
45
|
+
championship = attributes[:championship]
|
46
|
+
serie = attributes[:serie]
|
47
|
+
|
48
|
+
if @config.championship_associate?
|
49
|
+
find_match_associated(id_match, championship)
|
50
|
+
else
|
51
|
+
find_match(id_match, championship, serie)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_match(id_match, championship, serie)
|
56
|
+
@config.klass.find_by(
|
57
|
+
"#{@config.searchable_attr(:id_match)}": id_match,
|
58
|
+
"#{@config.searchable_attr(:championship)}": championship,
|
59
|
+
"#{@config.searchable_attr(:serie)}": serie
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def find_match_associated(id_match, championship)
|
64
|
+
@config.klass.find_by(
|
65
|
+
"#{@config.searchable_attr(:id_match)}": id_match,
|
66
|
+
"#{@config.searchable_attr(:championship_id)}": championship.id
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Abstraction for the class Ranking
|
5
|
+
class Ranking < Base
|
6
|
+
class << self
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
def championship
|
10
|
+
ActiveRecordRelation.new(
|
11
|
+
Championship,
|
12
|
+
@config.championship_associate?
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def team
|
17
|
+
ActiveRecordRelation.new(
|
18
|
+
Team,
|
19
|
+
@config.team_associate?
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_opponent
|
24
|
+
ActiveRecordRelation.new(
|
25
|
+
Team,
|
26
|
+
@config.next_opponent_associate?
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_by(attributes)
|
31
|
+
position = attributes[:position]
|
32
|
+
championship = attributes[:championship]
|
33
|
+
serie = attributes[:serie]
|
34
|
+
|
35
|
+
if @config.championship_associate?
|
36
|
+
find_ranking_associated(position, championship)
|
37
|
+
else
|
38
|
+
find_ranking(position, championship, serie)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_ranking(position, championship, serie)
|
43
|
+
@config.klass.find_by(
|
44
|
+
"#{@config.searchable_attr(:position)}": position,
|
45
|
+
"#{@config.searchable_attr(:championship)}": championship,
|
46
|
+
"#{@config.searchable_attr(:serie)}": serie
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_ranking_associated(position, championship)
|
51
|
+
@config.klass.find_by(
|
52
|
+
"#{@config.searchable_attr(:position)}": position,
|
53
|
+
"#{@config.searchable_attr(:championship_id)}": championship.id
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ScrapCbfRecord
|
4
|
+
# Abstraction for the class Round
|
5
|
+
class Round < Base
|
6
|
+
class << self
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
def championship
|
10
|
+
ActiveRecordRelation.new(
|
11
|
+
Championship,
|
12
|
+
@config.championship_associate?
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by(attributes)
|
17
|
+
number = attributes[:number]
|
18
|
+
championship = attributes[:championship]
|
19
|
+
serie = attributes[:serie]
|
20
|
+
associate = attributes[:associate]
|
21
|
+
|
22
|
+
# if associate is nil, that means self is calling this method
|
23
|
+
if associate.nil? || associate
|
24
|
+
find_round_on_database(number, championship, serie)
|
25
|
+
else
|
26
|
+
number
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_round_on_database(number, championship, serie)
|
31
|
+
if @config.championship_associate?
|
32
|
+
find_round_associated(number, championship)
|
33
|
+
else
|
34
|
+
find_round(number, championship, serie)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_round(number, championship, serie)
|
39
|
+
@config.klass.find_by(
|
40
|
+
"#{@config.searchable_attr(:number)}": number,
|
41
|
+
"#{@config.searchable_attr(:championship)}": championship,
|
42
|
+
"#{@config.searchable_attr(:serie)}": serie
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_round_associated(number, championship)
|
47
|
+
@config.klass.find_by(
|
48
|
+
"#{@config.searchable_attr(:number)}": number,
|
49
|
+
"#{@config.searchable_attr(:championship_id)}": championship.id
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|