beerdb-models 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ module BeerDb
4
+
5
+ ## todo: "old" classic reader - rename to FileReader ?? why? why not?
6
+
7
+ class Reader < ReaderBase
8
+
9
+ def initialize( include_path, opts = {} )
10
+ @include_path = include_path
11
+ end
12
+
13
+ def create_fixture_reader( name )
14
+ path = "#{@include_path}/#{name}.txt"
15
+
16
+ logger.info "parsing data (setup) '#{name}' (#{path})..."
17
+
18
+ FixtureReader.from_file( path )
19
+ end
20
+
21
+ def create_beers_reader( name, more_attribs={} )
22
+ real_name = name_to_real_name( name )
23
+
24
+ path = "#{@include_path}/#{real_name}.txt"
25
+
26
+ logger.info "parsing data (beers) '#{name}' (#{path})..."
27
+
28
+ ValuesReader.from_file( path, more_attribs )
29
+ ## ValuesReaderV2.new( name, @include_path, more_attribs )
30
+ end
31
+
32
+ def create_breweries_reader( name, more_attribs={} )
33
+ real_name = name_to_real_name( name )
34
+
35
+ path = "#{@include_path}/#{real_name}.txt"
36
+
37
+ logger.info "parsing data (breweries) '#{name}' (#{path})..."
38
+
39
+ ValuesReader.from_file( path, more_attribs )
40
+ ## ValuesReaderV2.new( name, @include_path, more_attribs )
41
+ end
42
+
43
+ private
44
+
45
+ def name_to_real_name( name )
46
+ # map name to real_name path
47
+ # name might include !/ for virtual path (gets cut off)
48
+ # e.g. at-austria!/w-wien/beers becomse w-wien/beers
49
+ pos = name.index( '!/')
50
+ if pos.nil?
51
+ name # not found; real path is the same as name
52
+ else
53
+ # cut off everything until !/ e.g.
54
+ # at-austria!/w-wien/beers becomes
55
+ # w-wien/beers
56
+ name[ (pos+2)..-1 ]
57
+ end
58
+ end
59
+
60
+ end # class Reader
61
+ end # module BeerDb
62
+
@@ -0,0 +1,112 @@
1
+ # encoding: UTF-8
2
+
3
+ module BeerDb
4
+
5
+
6
+ class ZipReader < ReaderBase
7
+
8
+ def initialize( name, include_path, opts = {} )
9
+
10
+ ## todo/fix: make include_path an opts (included in opts?) - why? why not??
11
+
12
+ path = "#{include_path}/#{name}.zip"
13
+ ## todo: check if zip exists
14
+
15
+ @zip_file = Zip::File.open( path ) ## NOTE: do NOT create if file is missing; let it crash
16
+
17
+ ### allow prefix (path) in name
18
+ ### e.g. assume all files relative to setup manifest
19
+ ## e.g. at-austria-master/setups/all.txt or
20
+ ## be-belgium-master/setups/all.txt
21
+ ## for
22
+ ## setups/all.txt
23
+ ###
24
+ ## will get (re)set w/ fixture/setup reader
25
+ ##
26
+ ## todo/fix: change/rename to @relative_path ?? - why? why not?
27
+ @zip_prefix = ''
28
+ end
29
+
30
+
31
+ def close
32
+ ## todo/check: add a close method - why? why not ???
33
+ @zip_file.close
34
+ end
35
+
36
+
37
+ def create_fixture_reader( name )
38
+ ## e.g. pass in => setups/all or setups/test etc. e.g. w/o .txt extension
39
+ query = "**/#{name}.txt"
40
+
41
+ ## note: returns an array of Zip::Entry
42
+ candidates = @zip_file.glob( query )
43
+ pp candidates
44
+
45
+ ## use first candidates entry as match
46
+ ## todo/fix: issue warning if more than one entries/matches!!
47
+
48
+ ## get fullpath e.g. at-austria-master/setups/all.txt
49
+ path = candidates[0].name
50
+ logger.debug " zip entry path >>#{path}<<"
51
+
52
+ ## cut-off at-austria-master/ NOTE: includes trailing slash (if present)
53
+ ## logger.debug " path.size #{path.size} >>#{path}<<"
54
+ ## logger.debug " name.size #{name.size+4} >>#{name}<<"
55
+
56
+ ## note: add +4 for extension (.txt)
57
+ @zip_prefix = path[ 0...(path.size-(name.size+4)) ]
58
+ logger.debug " zip entry prefix >>#{@zip_prefix}<<"
59
+
60
+ logger.info "parsing data in zip '#{name}' (#{path})..."
61
+
62
+ FixtureReader.from_zip( @zip_file, path )
63
+ end
64
+
65
+
66
+ def create_beers_reader( name, more_attribs={} )
67
+ path = name_to_zip_entry_path( name )
68
+
69
+ logger.debug "parsing data (beers) in zip '#{name}' (#{path})..."
70
+
71
+ ValuesReader.from_zip( @zip_file, path, more_attribs )
72
+ end
73
+
74
+ def create_breweries_reader( name, more_attribs={} )
75
+ path = name_to_zip_entry_path( name )
76
+
77
+ logger.debug "parsing data (breweries) in zip '#{name}' (#{path})..."
78
+
79
+ ValuesReader.from_zip( @zip_file, path, more_attribs )
80
+ end
81
+
82
+ private
83
+
84
+ def path_to_real_path( path )
85
+ # map name to name_real_path
86
+ # name might include !/ for virtual path (gets cut off)
87
+ # e.g. at-austria!/w-wien/beers becomse w-wien/beers
88
+ pos = path.index( '!/')
89
+ if pos.nil?
90
+ path # not found; real path is the same as name
91
+ else
92
+ # cut off everything until !/ e.g.
93
+ # at-austria!/w-wien/beers becomes
94
+ # w-wien/beers
95
+ path[ (pos+2)..-1 ]
96
+ end
97
+ end
98
+
99
+ def name_to_zip_entry_path( name )
100
+ path = "#{name}.txt"
101
+
102
+ real_path = path_to_real_path( path )
103
+
104
+ # NOTE: add possible zip entry prefix path
105
+ # (if present includes trailing slash e.g. /)
106
+ entry_path = "#{@zip_prefix}#{real_path}"
107
+ entry_path
108
+ end
109
+
110
+
111
+ end # class ZipReader
112
+ end # module BeerDb
@@ -0,0 +1,195 @@
1
+ # encoding: UTF-8
2
+
3
+ module BeerDb
4
+
5
+
6
+ class CreateDb < ActiveRecord::Migration
7
+
8
+ def up
9
+
10
+ create_table :beers do |t|
11
+ t.string :key, :null => false # import/export key
12
+ t.string :title, :null => false
13
+ t.string :synonyms # comma separated list of synonyms
14
+
15
+ t.string :web # optional url link (e.g. )
16
+ t.integer :since # optional year (e.g. 1896)
17
+
18
+ # t.boolean :bottle, :null => false, :default => false # Flaschenbier
19
+ # t.boolean :draft, :null => false, :default => false # Fassbier
20
+ ## todo: check seasonal is it proper english?
21
+ t.boolean :seasonal, :null => false, :default => false # all year or just eg. Festbier/Oktoberfest Special
22
+ t.boolean :limited, :null => false, :default => false # one year or season only
23
+ ## todo: add microbrew/brewpub flag?
24
+ #### t.boolean :brewpub, :null => false, :default => false
25
+
26
+ ## add t.boolean :lite flag ??
27
+ t.decimal :kcal # kcal/100ml e.g. 45.0 kcal/100ml
28
+
29
+ ## check: why decimal and not float?
30
+ t.decimal :abv # Alcohol by volume (abbreviated as ABV, abv, or alc/vol) e.g. 4.9 %
31
+ t.decimal :og # malt extract (original gravity) in plato
32
+ t.integer :srm # color in srm
33
+ t.integer :ibu # bitterness in ibu
34
+
35
+ ### fix/todo: add bitterness field
36
+
37
+ # renamed - old field names
38
+ ## t.decimal :plato # stammwuerze / gravity in plato scale (e.g. °P) e.g. 12.6° - todo: use a different field name e.g. just p or gravity?
39
+ ## t.integer :color # beer color in Standard Reference Method (SRM)
40
+
41
+ # see en.wikipedia.org/wiki/Plato_scale#Colour
42
+
43
+ # SRM/Lovibond | Example | Beer color | EBC
44
+ # ---------------------------------------------------------------
45
+ # 2 | Pale lager, Witbier, Pilsener, Berliner Weisse | #F8F753 | 4
46
+ # 3 | Maibock, Blonde Ale | #F6F513 | 6
47
+ # 4 | Weissbier | #ECE61A | 8
48
+ # 6 | American Pale Ale, India Pale Ale | #D5BC26 | 12
49
+ # 8 | Weissbier, Saison | #BF923B | 16
50
+ # 10 | English Bitter, ESB | #BF813A | 20
51
+ # 13 | Biere de Garde, Double IPA | #BC6733 | 26
52
+ # 17 | Dark lager, Vienna lager, Marzen, Amber Ale | #8D4C32 | 33
53
+ # 20 | Brown Ale, Bock, Dunkel, Dunkelweizen | #5D341A | 39
54
+ # 24 | Irish Dry Stout, Doppelbock, Porter | #261716 | 47
55
+ # 29 | Stout | #0F0B0A | 57
56
+ # 35 | Foreign Stout, Baltic Porter | #080707 | 69
57
+ # 40+ | Imperial Stout | #030403 | 79
58
+
59
+ t.references :brewery # optional (for now)
60
+ t.references :brand # optional (for now)
61
+
62
+
63
+ ## todo: add categories e.g. (A/B/C, 1/2/3, main/major/minor ??)
64
+ # - A-grade /1st class/ tier1 / main beer brand/bestseller/flagship ?
65
+ # - B-grade /2nd class/ tier2 / regular, major, - todo: find better names?
66
+ # - C-grade /3nd class/ tier3/ / speciality, minor ?
67
+
68
+ # use stars in .txt e.g. # ***/**/*/- => 1/2/3/4
69
+ t.integer :grade, :null => false, :default => 4
70
+
71
+ t.string :txt # source ref
72
+ t.boolean :txt_auto, :null => false, :default => false # inline? got auto-added?
73
+
74
+
75
+ t.references :country, :null => false
76
+ t.references :region # optional
77
+ t.references :city # optional
78
+
79
+ t.timestamps
80
+ end
81
+
82
+
83
+ create_table :brands do |t| # beer families (sharing same name e.g. brand)
84
+ t.string :key, :null => false # import/export key
85
+ t.string :title, :null => false
86
+ t.string :synonyms # comma separated list of synonyms
87
+ t.string :web # optional web page (e.g. www.ottakringer.at)
88
+ t.string :wiki # optional wiki(pedia page)
89
+ t.integer :since
90
+
91
+ ## scope of brand (global/intern'l/national/regional/local) ??
92
+ t.boolean :global, :null => false, :default => false
93
+ t.boolean :internl, :null => false, :default => false
94
+ t.boolean :national, :null => false, :default => false
95
+ t.boolean :regional, :null => false, :default => false
96
+ t.boolean :local, :null => false, :default => false
97
+
98
+ # t.integer :brand_grade # 1/2/3/4/5 (global/intern'l/national/regional/local)
99
+
100
+ # use stars in .txt e.g. # ***/**/*/- => 1/2/3/4
101
+ t.integer :grade, :null => false, :default => 4
102
+ # -- todo: add plus 1 for brewery w/ *** ??
103
+
104
+ t.string :txt # source ref
105
+ t.boolean :txt_auto, :null => false, :default => false # inline? got auto-added?
106
+
107
+
108
+ t.references :brewery # optional (for now)
109
+
110
+ t.references :country, :null => false
111
+ t.references :region # optional
112
+ t.references :city # optional
113
+
114
+ t.timestamps
115
+ end
116
+
117
+ create_table :breweries do |t|
118
+ t.string :key, :null => false # import/export key
119
+ t.string :title, :null => false
120
+ t.string :synonyms # comma separated list of synonyms
121
+ t.string :address
122
+ t.integer :since
123
+ ### fix: rename back to founded or use opened/closed
124
+ ## fix: add flag for ca./about boolean opened_guess / opened_est / opened_??
125
+ ## ca. / about 1010 marker e.g t.boolean : opened_est (for estimate) or similar!!!
126
+ ## renamed to founded to since
127
+ ## t.integer :founded # year founded/established - todo/fix: rename to since?
128
+ t.integer :closed # optional; year brewery closed
129
+
130
+ ## todo: add optional parent brewery (owned_by) ???
131
+
132
+ t.boolean :brewpub, :null => false, :default => false
133
+ t.boolean :prod_m, :null => false, :default => false # prod medium (mid-size/regional brewery)
134
+ # e.g. > 15_000 barrels (us)
135
+ t.boolean :prod_l, :null => false, :default => false # prod large
136
+ # e.g. > 500_000 hl (at), > 6_000_000 barrels (us)
137
+
138
+ t.integer :prod # (estimated) annual production/capacity in hl (1hl=100l) e.g. megabrewery 2_000_000, microbrewery 1_000 hl; brewbup 500 hl etc.
139
+ t.integer :prod_grade # 1/2/3/4/5/6/7/8/9/10/11
140
+
141
+ # grade - classified using annual production (capacity) in hl
142
+ # < 1_000 hl => 11
143
+ # < 3_000 hl => 10
144
+ # < 5_000 hl => 9
145
+ # < 10_000 hl => 8
146
+ # < 50_000 hl => 7
147
+ # < 100_000 hl => 6
148
+ # < 200_000 hl => 5
149
+ # < 500_000 hl => 4
150
+ # < 1_000_000 hl => 3
151
+ # < 2_000_000 hl => 2
152
+ # > 2_000_000 hl => 1
153
+
154
+
155
+ # use stars in .txt e.g. # ***/**/*/- => 1/2/3/4
156
+ t.integer :grade, :null => false, :default => 4
157
+
158
+
159
+ t.string :txt # source ref
160
+ t.boolean :txt_auto, :null => false, :default => false # inline? got auto-added?
161
+
162
+ t.string :web # optional web page (e.g. www.ottakringer.at)
163
+ t.string :wikipedia # optional wiki(pedia page)
164
+
165
+ t.boolean :indie # independent brewery (flag)
166
+
167
+ # for convenience (easy queries) use flags for top beer multinationals (-- later use just tags? more flexible)
168
+ t.boolean :abinbev # owned by AB InBev / Anheuser-Busch InBev (and Grupo Modelo)
169
+ t.boolean :sabmiller # owned by SAB Miller (in US cooperates w/ Molson Coors using MillerCoors venture)
170
+ t.boolean :heineken # owned by Heineken
171
+ t.boolean :carlsberg # owned by Carlsberg
172
+ t.boolean :molsoncoors # owned by Molson Coors
173
+ t.boolean :diageo # owned by Diageo (e.g. Guiness, Kilkenny,...)
174
+
175
+
176
+ # todo: add t.references :parent # for parent brewery
177
+ # (or better use has many parents w/ percentage of ownership; might not be 100%)
178
+
179
+ t.references :country, :null => false
180
+ t.references :region # optional
181
+ t.references :city # optional
182
+
183
+ t.timestamps
184
+ end
185
+
186
+ end # method up
187
+
188
+ def down
189
+ raise ActiveRecord::IrreversibleMigration
190
+ end
191
+
192
+
193
+ end # class CreateDb
194
+
195
+ end # module BeerDb
@@ -0,0 +1,45 @@
1
+ # encoding: UTF-8
2
+
3
+ module BeerDb::Model
4
+
5
+ class BeerSerializer
6
+
7
+ def initialize( beer )
8
+ @beer = beer
9
+ end
10
+
11
+ attr_reader :beer
12
+
13
+ def as_json
14
+ brewery = {}
15
+ if beer.brewery.present?
16
+ brewery = { key: beer.brewery.key,
17
+ title: beer.brewery.title }
18
+ end
19
+
20
+ tags = []
21
+ if beer.tags.present?
22
+ beer.tags.each { |tag| tags << tag.key }
23
+ end
24
+
25
+ country = {
26
+ key: beer.country.key,
27
+ title: beer.country.title
28
+ }
29
+
30
+ data = { key: beer.key,
31
+ title: beer.title,
32
+ synonyms: beer.synonyms,
33
+ abv: beer.abv,
34
+ srm: beer.srm,
35
+ og: beer.og,
36
+ tags: tags,
37
+ brewery: brewery,
38
+ country: country }
39
+
40
+ data.to_json
41
+ end
42
+
43
+ end # class BeerSerializer
44
+
45
+ end # module BeerDb::Model
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+
3
+ module BeerDb::Model
4
+
5
+ class BrewerySerializer
6
+
7
+ def initialize( brewery )
8
+ @brewery = brewery
9
+ end
10
+
11
+ attr_reader :brewery
12
+
13
+ def as_json
14
+
15
+ beers = []
16
+ brewery.beers.each do |b|
17
+ beers << { key: b.key, title: b.title }
18
+ end
19
+
20
+ tags = []
21
+ if brewery.tags.present?
22
+ brewery.tags.each { |tag| tags << tag.key }
23
+ end
24
+
25
+ country = {
26
+ key: brewery.country.key,
27
+ title: brewery.country.title
28
+ }
29
+
30
+ data = { key: brewery.key,
31
+ title: brewery.title,
32
+ synonyms: brewery.synonyms,
33
+ since: brewery.since,
34
+ address: brewery.address,
35
+ web: brewery.web,
36
+ prod: brewery.prod, # (estimated) annual production in hl e.g. 2_000 hl
37
+ tags: tags,
38
+ beers: beers,
39
+ country: country }
40
+
41
+ data.to_json
42
+ end
43
+
44
+ end # class BrewerySerializer
45
+
46
+ end # module BeerDb::Model