beerdb-models 0.10.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/.gemtest +0 -0
- data/HISTORY.md +3 -0
- data/Manifest.txt +25 -0
- data/README.md +97 -0
- data/Rakefile +31 -0
- data/lib/beerdb/deleter.rb +27 -0
- data/lib/beerdb/models.rb +103 -0
- data/lib/beerdb/models/beer.rb +201 -0
- data/lib/beerdb/models/brand.rb +62 -0
- data/lib/beerdb/models/brewery.rb +256 -0
- data/lib/beerdb/models/forward.rb +46 -0
- data/lib/beerdb/models/tag.rb +13 -0
- data/lib/beerdb/models/world/city.rb +14 -0
- data/lib/beerdb/models/world/country.rb +14 -0
- data/lib/beerdb/models/world/region.rb +14 -0
- data/lib/beerdb/reader.rb +219 -0
- data/lib/beerdb/reader_file.rb +62 -0
- data/lib/beerdb/reader_zip.rb +112 -0
- data/lib/beerdb/schema.rb +195 -0
- data/lib/beerdb/serializers/beer.rb +45 -0
- data/lib/beerdb/serializers/brewery.rb +46 -0
- data/lib/beerdb/stats.rb +27 -0
- data/lib/beerdb/version.rb +21 -0
- data/test/helper.rb +63 -0
- data/test/test_fixture_matchers.rb +85 -0
- data/test/test_values.rb +240 -0
- metadata +118 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module BeerDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class Brand < ActiveRecord::Base
|
7
|
+
|
8
|
+
# NB: use extend - is_<type>? become class methods e.g. self.is_<type>?
|
9
|
+
extend TextUtils::ValueHelper # e.g. self.find_key_n_title, self.is_year?, self.is_region?, is_address?, is_taglist? etc.
|
10
|
+
|
11
|
+
belongs_to :country, :class_name => 'WorldDb::Model::Country', :foreign_key => 'country_id'
|
12
|
+
belongs_to :region, :class_name => 'WorldDb::Model::Region', :foreign_key => 'region_id'
|
13
|
+
belongs_to :city, :class_name => 'WorldDb::Model::City', :foreign_key => 'city_id'
|
14
|
+
|
15
|
+
belongs_to :brewery, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'brewery_id'
|
16
|
+
|
17
|
+
has_many :beers, :class_name => 'BeerDb::Model::Beer', :foreign_key => 'brand_id'
|
18
|
+
|
19
|
+
validates :key, :format => { :with => /\A[a-z][a-z0-9]+\z/, :message => 'expected two or more lowercase letters a-z or 0-9 digits' }
|
20
|
+
|
21
|
+
|
22
|
+
def self.create_or_update_from_values( values, more_attribs = {} )
|
23
|
+
attribs, more_values = find_key_n_title( values )
|
24
|
+
attribs = attribs.merge( more_attribs )
|
25
|
+
|
26
|
+
Brand.create_or_update_from_attribs( attribs, more_values )
|
27
|
+
end
|
28
|
+
|
29
|
+
# convenience helper Brand.create_or_update_from_title
|
30
|
+
def self.create_or_update_from_title( title, more_attribs = {} )
|
31
|
+
values = [title]
|
32
|
+
Brand.create_or_update_from_values( values, more_attribs )
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def self.create_or_update_from_attribs( attribs, values )
|
37
|
+
|
38
|
+
## fix: add/configure logger for ActiveRecord!!!
|
39
|
+
logger = LogKernel::Logger.root
|
40
|
+
|
41
|
+
## check for grades (e.g. ***/**/*) in titles (will add attribs[:grade] to hash)
|
42
|
+
## if grade missing; set default to 4; lets us update overwrite 1,2,3 values on update
|
43
|
+
attribs[:grade] ||= 4
|
44
|
+
|
45
|
+
rec = Brand.find_by_key( attribs[:key] )
|
46
|
+
|
47
|
+
if rec.present?
|
48
|
+
logger.debug "update Brand #{rec.id}-#{rec.key}:"
|
49
|
+
else
|
50
|
+
logger.debug "create Brand:"
|
51
|
+
rec = Brand.new
|
52
|
+
end
|
53
|
+
|
54
|
+
logger.debug attribs.to_json
|
55
|
+
|
56
|
+
rec.update_attributes!( attribs )
|
57
|
+
end
|
58
|
+
|
59
|
+
end # class Brand
|
60
|
+
|
61
|
+
end # module Model
|
62
|
+
end # module BeerDb
|
@@ -0,0 +1,256 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module BeerDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class Brewery < ActiveRecord::Base
|
7
|
+
|
8
|
+
extend TextUtils::TagHelper # will add self.find_tags, self.find_tags_in_attribs!, etc.
|
9
|
+
|
10
|
+
# NB: use extend - is_<type>? become class methods e.g. self.is_<type>? for use in
|
11
|
+
# self.create_or_update_from_values
|
12
|
+
extend TextUtils::ValueHelper # e.g. self.is_year?, self.is_region?, is_address?, is_taglist? etc.
|
13
|
+
extend TextUtils::AddressHelper # e.g self.normalize_addr, self.find_city_in_addr, etc.
|
14
|
+
|
15
|
+
self.table_name = 'breweries'
|
16
|
+
|
17
|
+
belongs_to :country, :class_name => 'WorldDb::Model::Country', :foreign_key => 'country_id'
|
18
|
+
belongs_to :region, :class_name => 'WorldDb::Model::Region', :foreign_key => 'region_id'
|
19
|
+
belongs_to :city, :class_name => 'WorldDb::Model::City', :foreign_key => 'city_id'
|
20
|
+
|
21
|
+
has_many :beers, :class_name => 'BeerDb::Model::Beer', :foreign_key => 'brewery_id'
|
22
|
+
has_many :brands, :class_name => 'BeerDb::Model::Brand', :foreign_key => 'brand_id'
|
23
|
+
|
24
|
+
has_many :taggings, class_name: 'TagDb::Model::Tagging', :as => :taggable
|
25
|
+
has_many :tags, class_name: 'TagDb::Model::Tag', :through => :taggings
|
26
|
+
|
27
|
+
|
28
|
+
validates :key, :format => { :with => /\A[a-z][a-z0-9]+\z/, :message => 'expected two or more lowercase letters a-z or 0-9 digits' }
|
29
|
+
|
30
|
+
|
31
|
+
### support old names (read-only) for now (remove later ??)
|
32
|
+
|
33
|
+
def founded() since; end
|
34
|
+
def founded=(value) self.since = value; end
|
35
|
+
|
36
|
+
def opened() since; end
|
37
|
+
def openend=(value) self.since = value; end
|
38
|
+
|
39
|
+
def m?() prod_m == true; end
|
40
|
+
def l?() prod_l == true; end
|
41
|
+
|
42
|
+
## TODO: activerecord supplies brewpub? already? same as attrib; check w/ test case (and remove here)
|
43
|
+
def brewpub?() brewpub == true; end
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
def as_json_v2( opts={} )
|
48
|
+
# NB: do NOT overwrite "default" / builtin as_json, thus, lets use as_json_v2
|
49
|
+
BrewerySerializer.new( self ).as_json
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
def self.create_or_update_from_values( values, more_attribs={} )
|
55
|
+
attribs, more_values = find_key_n_title( values )
|
56
|
+
attribs = attribs.merge( more_attribs )
|
57
|
+
|
58
|
+
# check for optional values
|
59
|
+
Brewery.create_or_update_from_attribs( attribs, more_values )
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def self.create_or_update_from_attribs( new_attributes, values )
|
64
|
+
|
65
|
+
## fix: add/configure logger for ActiveRecord!!!
|
66
|
+
logger = LogKernel::Logger.root
|
67
|
+
|
68
|
+
value_tag_keys = []
|
69
|
+
value_brands = ''
|
70
|
+
|
71
|
+
## check for grades (e.g. ***/**/*) in titles (will add new_attributes[:grade] to hash)
|
72
|
+
## if grade missing; set default to 4; lets us update overwrite 1,2,3 values on update
|
73
|
+
new_attributes[ :grade ] ||= 4
|
74
|
+
|
75
|
+
### check for "default" tags - that is, if present new_attributes[:tags] remove from hash
|
76
|
+
value_tag_keys += find_tags_in_attribs!( new_attributes )
|
77
|
+
|
78
|
+
## check for optional values
|
79
|
+
values.each_with_index do |value,index|
|
80
|
+
if match_country(value) do |country|
|
81
|
+
new_attributes[ :country_id ] = country.id
|
82
|
+
end
|
83
|
+
elsif match_region_for_country(value,new_attributes[:country_id]) do |region|
|
84
|
+
new_attributes[ :region_id ] = region.id
|
85
|
+
end
|
86
|
+
elsif match_city(value) do |city|
|
87
|
+
if city.present?
|
88
|
+
new_attributes[ :city_id ] = city.id
|
89
|
+
else
|
90
|
+
## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
|
91
|
+
logger.warn "city with key #{value[5..-1]} missing - for brewery #{new_attributes[:key]}"
|
92
|
+
end
|
93
|
+
|
94
|
+
## for easy queries: cache region_id (from city)
|
95
|
+
# - check if city w/ region if yes, use it for brewery too
|
96
|
+
if city.present? && city.region.present?
|
97
|
+
new_attributes[ :region_id ] = city.region.id
|
98
|
+
end
|
99
|
+
end
|
100
|
+
elsif match_year( value ) do |num| # founded/established year e.g. 1776
|
101
|
+
new_attributes[ :since ] = num
|
102
|
+
end
|
103
|
+
elsif match_hl( value ) do |num| # e.g. 20_000 hl or 50hl etc.
|
104
|
+
new_attributes[ :prod ] = num
|
105
|
+
end
|
106
|
+
elsif match_website( value ) do |website| # check for url/internet address e.g. www.ottakringer.at
|
107
|
+
# fix: support more url format (e.g. w/o www. - look for .com .country code etc.)
|
108
|
+
new_attributes[ :web ] = website
|
109
|
+
end
|
110
|
+
elsif is_address?( value ) # if value includes // assume address e.g. 3970 Weitra // Sparkasseplatz 160
|
111
|
+
new_attributes[ :address ] = normalize_addr( value )
|
112
|
+
elsif value =~ /^brands:/ # brands:
|
113
|
+
value_brands = value[7..-1] ## cut off brands: prefix
|
114
|
+
value_brands = value_brands.strip # remove leading and trailing spaces
|
115
|
+
# NB: brands get processed after record gets created (see below)
|
116
|
+
elsif (values.size==(index+1)) && is_taglist?( value ) # tags must be last entry
|
117
|
+
logger.debug " found tags: >>#{value}<<"
|
118
|
+
value_tag_keys += find_tags( value )
|
119
|
+
else
|
120
|
+
# issue warning: unknown type for value
|
121
|
+
logger.warn "unknown type for value >#{value}< - key #{new_attributes[:key]}"
|
122
|
+
end
|
123
|
+
end # each value
|
124
|
+
|
125
|
+
## todo: check better style using self.find_by_key?? why? why not?
|
126
|
+
rec = Brewery.find_by_key( new_attributes[ :key ] )
|
127
|
+
|
128
|
+
if rec.present?
|
129
|
+
logger.debug "update Brewery #{rec.id}-#{rec.key}:"
|
130
|
+
else
|
131
|
+
logger.debug "create Brewery:"
|
132
|
+
rec = Brewery.new
|
133
|
+
end
|
134
|
+
|
135
|
+
logger.debug new_attributes.to_json
|
136
|
+
|
137
|
+
rec.update_attributes!( new_attributes )
|
138
|
+
|
139
|
+
|
140
|
+
##############################
|
141
|
+
# auto-add city if not present and country n region present
|
142
|
+
|
143
|
+
if new_attributes[:city_id].blank? &&
|
144
|
+
new_attributes[:country_id].present? &&
|
145
|
+
new_attributes[:region_id].present?
|
146
|
+
|
147
|
+
country_key = rec.country.key
|
148
|
+
|
149
|
+
###
|
150
|
+
## see textutils/helper/address_helper for details about countries supported e.g.
|
151
|
+
## github.com/rubylibs/textutils/blob/master/lib/textutils/helper/address_helper.rb
|
152
|
+
|
153
|
+
if country_key == 'be' || country_key == 'at' ||
|
154
|
+
country_key == 'de' ||
|
155
|
+
country_key == 'cz' || country_key == 'sk' ||
|
156
|
+
country_key == 'us'
|
157
|
+
|
158
|
+
## todo: how to handle nil/empty address lines?
|
159
|
+
|
160
|
+
city_title = find_city_in_addr( new_attributes[:address], country_key )
|
161
|
+
|
162
|
+
if city_title.present?
|
163
|
+
|
164
|
+
## for czech - some cleanup
|
165
|
+
## remove any (remaining) digits in city title
|
166
|
+
city_title = city_title.gsub( /[0-9]/, '' ).strip
|
167
|
+
|
168
|
+
city_values = [city_title]
|
169
|
+
city_attributes = {
|
170
|
+
country_id: rec.country_id,
|
171
|
+
region_id: rec.region_id
|
172
|
+
}
|
173
|
+
# todo: add convenience helper create_or_update_from_title
|
174
|
+
city = City.create_or_update_from_values( city_values, city_attributes )
|
175
|
+
|
176
|
+
### fix/todo: set new autoadd flag too?
|
177
|
+
## e.g. check if updated? e.g. timestamp created <> updated otherwise assume created?
|
178
|
+
|
179
|
+
## now at last add city_id to brewery!
|
180
|
+
rec.city_id = city.id
|
181
|
+
rec.save!
|
182
|
+
else
|
183
|
+
logger.warn "auto-add city for #{new_attributes[:key]} (#{country_key}) >>#{new_attributes[:address]}<< failed; no city title found"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
###################
|
190
|
+
# auto-add brands if presents
|
191
|
+
|
192
|
+
if value_brands.present?
|
193
|
+
logger.debug " auto-adding brands >#{value_brands}<"
|
194
|
+
|
195
|
+
## todo/fix: use strip_inline_comments (e.g #() or (()) - why?? why not??)
|
196
|
+
# - allows titles as usual (use new syntax for inline comments e.g. #() or (()) for example)
|
197
|
+
|
198
|
+
# remove optional longer title part in () e.g. Las Palmas (de Gran Canaria), Palma (de Mallorca)
|
199
|
+
value_brands = TextUtils.strip_subtitles( value_brands )
|
200
|
+
|
201
|
+
brand_titles = value_brands.split( ',' )
|
202
|
+
|
203
|
+
# pass 1) remove leading n trailing spaces
|
204
|
+
brand_titles = brand_titles.map { |value| value.strip }
|
205
|
+
|
206
|
+
brand_attribs = {
|
207
|
+
brewery_id: rec.id,
|
208
|
+
country_id: rec.country_id,
|
209
|
+
region_id: rec.region_id,
|
210
|
+
city_id: rec.city_id
|
211
|
+
}
|
212
|
+
|
213
|
+
brand_titles.each do |brand_title|
|
214
|
+
Brand.create_or_update_from_title( brand_title, brand_attribs )
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
##################
|
219
|
+
## add taggings
|
220
|
+
|
221
|
+
##
|
222
|
+
## fix: delete all tags first or only add diff?
|
223
|
+
## fix e.g.
|
224
|
+
##
|
225
|
+
# [debug] adding 1 taggings: >>trappist<<...
|
226
|
+
# rake aborted!
|
227
|
+
# ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: columns taggable_id, taggable_type, tag_id are not unique: INSERT INTO "taggings" ("created_at", "tag_id", "taggable_id", "taggable_type", "updated_at") VALUES (?, ?, ?, ?, ?)
|
228
|
+
# if value_tag_keys.size > 0
|
229
|
+
|
230
|
+
=begin
|
231
|
+
value_tag_keys.uniq! # remove duplicates
|
232
|
+
logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
|
233
|
+
|
234
|
+
### fix/todo: check tag_ids and only update diff (add/remove ids)
|
235
|
+
|
236
|
+
value_tag_keys.each do |key|
|
237
|
+
tag = Tag.find_by_key( key )
|
238
|
+
if tag.nil? # create tag if it doesn't exit
|
239
|
+
logger.debug " creating tag >#{key}<"
|
240
|
+
tag = Tag.create!( key: key )
|
241
|
+
end
|
242
|
+
rec.tags << tag
|
243
|
+
end
|
244
|
+
end
|
245
|
+
=end
|
246
|
+
|
247
|
+
rec # NB: return created or updated obj
|
248
|
+
|
249
|
+
end # method create_or_update_from_values
|
250
|
+
|
251
|
+
|
252
|
+
end # class Brewery
|
253
|
+
|
254
|
+
end # module Model
|
255
|
+
end # module BeerDb
|
256
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
|
4
|
+
### forward references
|
5
|
+
## require first to resolve circular references
|
6
|
+
|
7
|
+
|
8
|
+
module BeerDb
|
9
|
+
module Model
|
10
|
+
|
11
|
+
## todo: why? why not use include WorldDb::Models here???
|
12
|
+
|
13
|
+
Continent = WorldDb::Model::Continent
|
14
|
+
Country = WorldDb::Model::Country
|
15
|
+
Region = WorldDb::Model::Region
|
16
|
+
City = WorldDb::Model::City
|
17
|
+
|
18
|
+
Tag = TagDb::Model::Tag
|
19
|
+
Tagging = TagDb::Model::Tagging
|
20
|
+
|
21
|
+
Prop = ConfDb::Model::Prop
|
22
|
+
|
23
|
+
class Beer < ActiveRecord::Base ; end
|
24
|
+
class Brand < ActiveRecord::Base ; end
|
25
|
+
class Brewery < ActiveRecord::Base ; end
|
26
|
+
|
27
|
+
end # module Model
|
28
|
+
|
29
|
+
## convenience alias (for better english ;-) )
|
30
|
+
## lets you use => include Models (instead of include Model)
|
31
|
+
Models = Model
|
32
|
+
|
33
|
+
end # module BeerDb
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
module WorldDb
|
38
|
+
module Model
|
39
|
+
|
40
|
+
Beer = BeerDb::Model::Beer
|
41
|
+
Brand = BeerDb::Model::Brand
|
42
|
+
Brewery = BeerDb::Model::Brewery
|
43
|
+
|
44
|
+
end # module Model
|
45
|
+
end # module WorldDb
|
46
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module TagDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class Tag
|
7
|
+
has_many :beers, :through => :taggings, :source => :taggable, :source_type => 'BeerDb::Model::Beer', :class_name => 'BeerDb::Model::Beer'
|
8
|
+
has_many :breweries, :through => :taggings, :source => :taggable, :source_type => 'BeerDb::Model::Brewery', :class_name => 'BeerDb::Model::Brewery'
|
9
|
+
end # class Country
|
10
|
+
|
11
|
+
end # module Model
|
12
|
+
end # module TagDb
|
13
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module WorldDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class City
|
7
|
+
has_many :beers, :class_name => 'BeerDb::Model::Beer', :foreign_key => 'city_id'
|
8
|
+
has_many :brands, :class_name => 'BeerDb::Model::Brand', :foreign_key => 'city_id'
|
9
|
+
has_many :breweries, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'city_id'
|
10
|
+
end # class Country
|
11
|
+
|
12
|
+
end # module Model
|
13
|
+
end # module WorldDb
|
14
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module WorldDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class Country
|
7
|
+
has_many :beers, :class_name => 'BeerDb::Model::Beer', :foreign_key => 'country_id'
|
8
|
+
has_many :brands, :class_name => 'BeerDb::Model::Brand', :foreign_key => 'country_id'
|
9
|
+
has_many :breweries, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'country_id'
|
10
|
+
end # class Country
|
11
|
+
|
12
|
+
end # module Model
|
13
|
+
end # module WorldDb
|
14
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module WorldDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
class Region
|
7
|
+
has_many :beers, :class_name => 'BeerDb::Model::Beer', :foreign_key => 'region_id'
|
8
|
+
has_many :brands, :class_name => 'BeerDb::Model::Brand', :foreign_key => 'region_id'
|
9
|
+
has_many :breweries, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'region_id'
|
10
|
+
end # class Region
|
11
|
+
|
12
|
+
end # module Model
|
13
|
+
end # module WorldDb
|
14
|
+
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module BeerDb
|
4
|
+
|
5
|
+
|
6
|
+
module Matcher
|
7
|
+
|
8
|
+
def match_beers_for_country( name, &blk )
|
9
|
+
match_xxx_for_country( name, 'beers', &blk )
|
10
|
+
end
|
11
|
+
|
12
|
+
def match_beers_for_country_n_region( name, &blk )
|
13
|
+
match_xxx_for_country_n_region( name, 'beers', &blk )
|
14
|
+
end
|
15
|
+
|
16
|
+
def match_breweries_for_country( name, &blk )
|
17
|
+
match_xxx_for_country( name, 'breweries', &blk )
|
18
|
+
end
|
19
|
+
|
20
|
+
def match_breweries_for_country_n_region( name, &blk )
|
21
|
+
match_xxx_for_country_n_region( name, 'breweries', &blk )
|
22
|
+
end
|
23
|
+
|
24
|
+
def match_brewpubs_for_country( name, &blk )
|
25
|
+
match_xxx_for_country( name, 'brewpubs', &blk )
|
26
|
+
end
|
27
|
+
|
28
|
+
def match_brewpubs_for_country_n_region( name, &blk )
|
29
|
+
match_xxx_for_country_n_region( name, 'brewpubs', &blk )
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end # module Matcher
|
34
|
+
|
35
|
+
|
36
|
+
class ReaderBase
|
37
|
+
|
38
|
+
include LogUtils::Logging
|
39
|
+
|
40
|
+
include BeerDb::Models
|
41
|
+
|
42
|
+
include WorldDb::Matcher ## fix: move to BeerDb::Matcher module ??? - cleaner?? why? why not?
|
43
|
+
include BeerDb::Matcher # lets us use match_teams_for_country etc.
|
44
|
+
|
45
|
+
|
46
|
+
def load_setup( name )
|
47
|
+
reader = create_fixture_reader( name ) ### "virtual" method - required by concrete class
|
48
|
+
|
49
|
+
reader.each do |fixture_name|
|
50
|
+
load( fixture_name )
|
51
|
+
end
|
52
|
+
end # method load_setup
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
def load( name )
|
57
|
+
|
58
|
+
if match_beers_for_country_n_region( name ) do |country_key, region_key|
|
59
|
+
load_beers_for_country_n_region( country_key, region_key, name )
|
60
|
+
end
|
61
|
+
elsif match_beers_for_country( name ) do |country_key|
|
62
|
+
load_beers_for_country( country_key, name )
|
63
|
+
end
|
64
|
+
elsif match_breweries_for_country_n_region( name ) do |country_key, region_key|
|
65
|
+
load_breweries_for_country_n_region( country_key, region_key, name )
|
66
|
+
end
|
67
|
+
elsif match_breweries_for_country( name ) do |country_key|
|
68
|
+
load_breweries_for_country( country_key, name )
|
69
|
+
end
|
70
|
+
elsif match_brewpubs_for_country_n_region( name ) do |country_key, region_key|
|
71
|
+
load_breweries_for_country_n_region( country_key, region_key, name, brewpub: true )
|
72
|
+
end
|
73
|
+
elsif match_brewpubs_for_country( name ) do |country_key|
|
74
|
+
load_breweries_for_country( country_key, name, brewpub: true )
|
75
|
+
end
|
76
|
+
else
|
77
|
+
logger.error "unknown beer.db fixture type >#{name}<"
|
78
|
+
# todo/fix: exit w/ error
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def load_beers_for_country_n_region( country_key, region_key, name, more_attribs={} )
|
84
|
+
country = Country.find_by_key!( country_key )
|
85
|
+
logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
|
86
|
+
more_attribs[ :country_id ] = country.id
|
87
|
+
|
88
|
+
# NB: region lookup requires country id (region key only unique for country)
|
89
|
+
region = Region.find_by_key_and_country_id( region_key, country.id )
|
90
|
+
if region.nil?
|
91
|
+
# note: allow unknown region keys; issue warning n skip region
|
92
|
+
logger.warn "Region w/ key >#{region_key}< not found; skip adding region"
|
93
|
+
else
|
94
|
+
logger.debug "Region #{region.key} >#{region.title}<"
|
95
|
+
more_attribs[ :region_id ] = region.id
|
96
|
+
end
|
97
|
+
|
98
|
+
more_attribs[ :txt ] = name # store source ref
|
99
|
+
|
100
|
+
load_beers_worker( name, more_attribs )
|
101
|
+
end
|
102
|
+
|
103
|
+
def load_beers_for_country( country_key, name, more_attribs={} )
|
104
|
+
country = Country.find_by_key!( country_key )
|
105
|
+
logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
|
106
|
+
|
107
|
+
more_attribs[ :country_id ] = country.id
|
108
|
+
|
109
|
+
more_attribs[ :txt ] = name # store source ref
|
110
|
+
|
111
|
+
load_beers_worker( name, more_attribs )
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def load_beers_worker( name, more_attribs={} )
|
116
|
+
|
117
|
+
reader = create_beers_reader( name, more_attribs ) ### "virtual" method - required by concrete class
|
118
|
+
|
119
|
+
### todo: cleanup - check if [] works for build_title...
|
120
|
+
# better cleaner way ???
|
121
|
+
if more_attribs[:region_id].present?
|
122
|
+
known_breweries_source = Brewery.where( region_id: more_attribs[:region_id] )
|
123
|
+
elsif more_attribs[:country_id].present?
|
124
|
+
known_breweries_source = Brewery.where( country_id: more_attribs[:country_id] )
|
125
|
+
else
|
126
|
+
logger.warn "no region or country specified; use empty brewery ary for header mapper"
|
127
|
+
known_breweries_source = []
|
128
|
+
end
|
129
|
+
|
130
|
+
known_breweries = TextUtils.build_title_table_for( known_breweries_source )
|
131
|
+
|
132
|
+
|
133
|
+
reader.each_line do |new_attributes, values|
|
134
|
+
|
135
|
+
## note: check for header attrib; if present remove
|
136
|
+
### todo: cleanup code later
|
137
|
+
## fix: add to new_attributes hash instead of values ary
|
138
|
+
## - fix: match_brewery() move region,city code out of values loop for reuse at the end
|
139
|
+
if new_attributes[:header].present?
|
140
|
+
brewery_line = new_attributes[:header].dup # note: make sure we make a copy; will use in-place string ops
|
141
|
+
new_attributes.delete(:header) ## note: do NOT forget to remove from hash!
|
142
|
+
|
143
|
+
logger.debug " trying to find brewery in line >#{brewery_line}<"
|
144
|
+
## todo: check what map_titles_for! returns (nothing ???)
|
145
|
+
TextUtils.map_titles_for!( 'brewery', brewery_line, known_breweries )
|
146
|
+
brewery_key = TextUtils.find_key_for!( 'brewery', brewery_line )
|
147
|
+
logger.debug " brewery_key = >#{brewery_key}<"
|
148
|
+
unless brewery_key.nil?
|
149
|
+
## bingo! add brewery_id upfront, that is, as first value in ary
|
150
|
+
values = values.unshift "by:#{brewery_key}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
Beer.create_or_update_from_attribs( new_attributes, values )
|
155
|
+
end # each_line
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
def load_breweries_for_country_n_region( country_key, region_key, name, more_attribs={} )
|
160
|
+
country = Country.find_by_key!( country_key )
|
161
|
+
logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
|
162
|
+
|
163
|
+
more_attribs[ :country_id ] = country.id
|
164
|
+
|
165
|
+
# note: region lookup requires country id (region key only unique for country)
|
166
|
+
region = Region.find_by_key_and_country_id( region_key, country.id )
|
167
|
+
if region.nil?
|
168
|
+
# note: allow unknown region keys; issue warning n skip region
|
169
|
+
logger.warn "Region w/ key >#{region_key}< not found; skip adding region"
|
170
|
+
else
|
171
|
+
logger.debug "Region #{region.key} >#{region.title}<"
|
172
|
+
more_attribs[ :region_id ] = region.id
|
173
|
+
end
|
174
|
+
|
175
|
+
more_attribs[ :txt ] = name # store source ref
|
176
|
+
|
177
|
+
load_breweries_worker( name, more_attribs )
|
178
|
+
end
|
179
|
+
|
180
|
+
def load_breweries_for_country( country_key, name, more_attribs={} )
|
181
|
+
country = Country.find_by_key!( country_key )
|
182
|
+
logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
|
183
|
+
|
184
|
+
more_attribs[ :country_id ] = country.id
|
185
|
+
|
186
|
+
more_attribs[ :txt ] = name # store source ref
|
187
|
+
|
188
|
+
load_breweries_worker( name, more_attribs )
|
189
|
+
end
|
190
|
+
|
191
|
+
def load_breweries_worker( name, more_attribs={} )
|
192
|
+
|
193
|
+
if name =~ /\(m\)/ # check for (m) mid-size/medium marker -todo- use $?? must be last?
|
194
|
+
more_attribs[ :prod_m ] = true
|
195
|
+
elsif name =~ /\(l\)/ # check for (l) large marker - todo - use $?? must be last?
|
196
|
+
more_attribs[ :prod_l ] = true
|
197
|
+
else
|
198
|
+
## no marker; do nothing
|
199
|
+
end
|
200
|
+
|
201
|
+
reader = create_breweries_reader( name, more_attribs ) ### "virtual" method - required by concrete class
|
202
|
+
|
203
|
+
reader.each_line do |new_attributes, values|
|
204
|
+
|
205
|
+
#######
|
206
|
+
# fix: move to (inside)
|
207
|
+
# Brewery.create_or_update_from_attribs ||||
|
208
|
+
## note: group header not used for now; do NOT forget to remove from hash!
|
209
|
+
if new_attributes[:header].present?
|
210
|
+
logger.warn "removing unused group header #{new_attributes[:header]}"
|
211
|
+
new_attributes.delete(:header) ## note: do NOT forget to remove from hash!
|
212
|
+
end
|
213
|
+
|
214
|
+
Brewery.create_or_update_from_attribs( new_attributes, values )
|
215
|
+
end # each_line
|
216
|
+
end
|
217
|
+
|
218
|
+
end # class ReaderBase
|
219
|
+
end # module BeerDb
|