beerdb 0.4.0 → 0.5.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.
- data/README.md +110 -3
- data/Rakefile +1 -1
- data/lib/beerdb/models/beer.rb +136 -1
- data/lib/beerdb/models/brewery.rb +113 -0
- data/lib/beerdb/reader.rb +7 -264
- data/lib/beerdb/schema.rb +8 -3
- data/lib/beerdb/server.rb +5 -1
- data/lib/beerdb/version.rb +1 -1
- metadata +13 -13
data/README.md
CHANGED
@@ -2,12 +2,114 @@
|
|
2
2
|
|
3
3
|
beer.db Command Line Tool in Ruby
|
4
4
|
|
5
|
-
* [
|
5
|
+
* home :: [github.com/geraldb/beer.db.ruby](https://github.com/geraldb/beer.db.ruby)
|
6
|
+
* bugs :: [github.com/geraldb/beer.db.ruby/issues](https://github.com/geraldb/beer.db.ruby/issues)
|
7
|
+
* gem :: [rubygems.org/gems/beerdb](https://rubygems.org/gems/beerdb)
|
8
|
+
* rdoc :: [rubydoc.info/gems/beerdb](http://rubydoc.info/gems/beerdb)
|
9
|
+
* forum :: [groups.google.com/group/beerdb](https://groups.google.com/group/beerdb)
|
6
10
|
|
7
11
|
|
8
|
-
## Usage
|
12
|
+
## Usage Command Line
|
9
13
|
|
10
|
-
|
14
|
+
beer.db command line tool, version 0.5.0
|
15
|
+
|
16
|
+
Commands:
|
17
|
+
create Create DB schema
|
18
|
+
help Display global or [command] help documentation.
|
19
|
+
load Load fixtures
|
20
|
+
logs Show logs
|
21
|
+
props Show props
|
22
|
+
serve Start web service (HTTP JSON API)
|
23
|
+
setup Create DB schema 'n' load all data
|
24
|
+
stats Show stats
|
25
|
+
test Debug/test command suite
|
26
|
+
|
27
|
+
Global Options:
|
28
|
+
-i, --include PATH Data path (default is .)
|
29
|
+
-d, --dbpath PATH Database path (default is .)
|
30
|
+
-n, --dbname NAME Database name (datault is beer.db)
|
31
|
+
-q, --quiet Only show warnings, errors and fatal messages
|
32
|
+
-w, --verbose Show debug messages
|
33
|
+
-h, --help Display help documentation
|
34
|
+
-v, --version Display version information
|
35
|
+
-t, --trace Display backtrace when an error occurs
|
36
|
+
|
37
|
+
|
38
|
+
## Usage Models
|
39
|
+
|
40
|
+
Brewery Model
|
41
|
+
|
42
|
+
```
|
43
|
+
by = Brewery.find_by_key( 'guinness' )
|
44
|
+
|
45
|
+
by.title
|
46
|
+
=> 'St. James's Gate Brewery / Guinness Brewery'
|
47
|
+
|
48
|
+
by.country.key
|
49
|
+
=> 'ie'
|
50
|
+
|
51
|
+
by.country.title
|
52
|
+
=> 'Irland'
|
53
|
+
|
54
|
+
by.city.title
|
55
|
+
=> 'Dublin'
|
56
|
+
|
57
|
+
by.beers.first
|
58
|
+
=> 'Guinness', 4.2
|
59
|
+
|
60
|
+
...
|
61
|
+
```
|
62
|
+
|
63
|
+
|
64
|
+
Beer Model
|
65
|
+
|
66
|
+
```
|
67
|
+
b = Beer.find_by_key( 'guinness' )
|
68
|
+
|
69
|
+
b.title
|
70
|
+
=> 'Guinness'
|
71
|
+
|
72
|
+
b.abv
|
73
|
+
=> 4.2
|
74
|
+
|
75
|
+
b.tags
|
76
|
+
=> 'irish_dry_stout', 'dry_stout', 'stout'
|
77
|
+
|
78
|
+
b.brewery.title
|
79
|
+
=> 'St. James's Gate Brewery / Guinness Brewery'
|
80
|
+
|
81
|
+
...
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
Country Model
|
86
|
+
|
87
|
+
```
|
88
|
+
at = Country.find_by_key( 'at' )
|
89
|
+
|
90
|
+
at.beers
|
91
|
+
=> 'Weitra Helles', 'Hadmar', 'Zwettler Original', ...
|
92
|
+
|
93
|
+
at.breweries
|
94
|
+
=> 'Weitra Bräu Bierwerkstatt', 'Zwettler Brauerei', ...
|
95
|
+
|
96
|
+
...
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
City Model
|
101
|
+
|
102
|
+
```
|
103
|
+
wien = City.find_by_key( 'wien' )
|
104
|
+
|
105
|
+
wien.beers
|
106
|
+
=> 'Ottakringer Helles', 'Ottakringer (Gold Fassl) Zwickl', ...
|
107
|
+
|
108
|
+
wien.breweries
|
109
|
+
=> 'Ottakringer Brauerei'
|
110
|
+
|
111
|
+
...
|
112
|
+
```
|
11
113
|
|
12
114
|
|
13
115
|
## Install
|
@@ -21,3 +123,8 @@ Just install the gem:
|
|
21
123
|
|
22
124
|
The `beerdb` scripts are dedicated to the public domain.
|
23
125
|
Use it as you please with no restrictions whatsoever.
|
126
|
+
|
127
|
+
## Questions? Comments?
|
128
|
+
|
129
|
+
Send them along to the [Open Beer & Brewery Database Forum/Mailing List](http://groups.google.com/group/beerdb). Thanks!
|
130
|
+
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ Hoe.spec 'beerdb' do
|
|
11
11
|
self.urls = ['https://github.com/geraldb/beer.db.ruby']
|
12
12
|
|
13
13
|
self.author = 'Gerald Bauer'
|
14
|
-
self.email = '
|
14
|
+
self.email = 'beerdb@googlegroups.com'
|
15
15
|
|
16
16
|
# switch extension to .markdown for gihub formatting
|
17
17
|
self.readme_file = 'README.md'
|
data/lib/beerdb/models/beer.rb
CHANGED
@@ -30,7 +30,142 @@ class Beer < ActiveRecord::Base
|
|
30
30
|
self.og = value
|
31
31
|
end
|
32
32
|
|
33
|
-
end # class Beer
|
34
33
|
|
34
|
+
def self.create_or_update_from_values( new_attributes, values )
|
35
|
+
value_tag_keys = []
|
36
|
+
|
37
|
+
### check for "default" tags - that is, if present new_attributes[:tags] remove from hash
|
38
|
+
|
39
|
+
if new_attributes[:tags].present?
|
40
|
+
more_tag_keys = new_attributes[:tags].split('|')
|
41
|
+
new_attributes.delete(:tags)
|
42
|
+
|
43
|
+
## unify; replace _ w/ space; remove leading n trailing whitespace
|
44
|
+
more_tag_keys = more_tag_keys.map do |key|
|
45
|
+
key = key.gsub( '_', ' ' )
|
46
|
+
key = key.strip
|
47
|
+
key
|
48
|
+
end
|
49
|
+
|
50
|
+
value_tag_keys += more_tag_keys
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
## check for optional values
|
55
|
+
values.each_with_index do |value,index|
|
56
|
+
if value =~ /^country:/ ## country:
|
57
|
+
value_country_key = value[8..-1] ## cut off country: prefix
|
58
|
+
value_country = Country.find_by_key!( value_country_key )
|
59
|
+
new_attributes[ :country_id ] = value_country.id
|
60
|
+
elsif value =~ /^region:/ ## region:
|
61
|
+
value_region_key = value[7..-1] ## cut off region: prefix
|
62
|
+
value_region = Region.find_by_key_and_country_id!( value_region_key, new_attributes[:country_id] )
|
63
|
+
new_attributes[ :region_id ] = value_region.id
|
64
|
+
elsif value =~ /^[A-Z]{1,2}$/ ## assume region code e.g. TX or N
|
65
|
+
value_region = Region.find_by_key_and_country_id!( value.downcase, new_attributes[:country_id] )
|
66
|
+
new_attributes[ :region_id ] = value_region.id
|
67
|
+
elsif value =~ /^city:/ ## city:
|
68
|
+
value_city_key = value[5..-1] ## cut off city: prefix
|
69
|
+
value_city = City.find_by_key( value_city_key )
|
70
|
+
if value_city.present?
|
71
|
+
new_attributes[ :city_id ] = value_city.id
|
72
|
+
else
|
73
|
+
## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
|
74
|
+
logger.warn "city with key #{value_city_key} missing"
|
75
|
+
end
|
76
|
+
elsif value =~ /^by:/ ## by: -brewed by/brewery
|
77
|
+
value_brewery_key = value[3..-1] ## cut off by: prefix
|
78
|
+
value_brewery = Brewery.find_by_key!( value_brewery_key )
|
79
|
+
new_attributes[ :brewery_id ] = value_brewery.id
|
80
|
+
|
81
|
+
# for easy queries cache city and region ids
|
82
|
+
|
83
|
+
# 1) check if brewery has city - if yes, use it for beer too
|
84
|
+
if value_brewery.city.present?
|
85
|
+
new_attributes[ :city_id ] = value_brewery.city.id
|
86
|
+
end
|
87
|
+
|
88
|
+
# 2) check if brewery has city w/ region if yes, use it for beer to
|
89
|
+
# if not check for region for brewery
|
90
|
+
if value_brewery.city.present? && value_brewery.city.region.present?
|
91
|
+
new_attributes[ :region_id ] = value_brewery.city.region.id
|
92
|
+
elsif value_brewery.region.present?
|
93
|
+
new_attributes[ :region_id ] = value_brewery.region.id
|
94
|
+
end
|
95
|
+
|
96
|
+
elsif value =~ /^[0-9]{4}$/ # founded/established year e.g. 1776
|
97
|
+
new_attributes[ :since ] = value.to_i
|
98
|
+
elsif value =~ /^www\.|\.com$/ # check for url/internet address e.g. www.ottakringer.at
|
99
|
+
# fix: support more url format (e.g. w/o www. - look for .com .country code etc.)
|
100
|
+
new_attributes[ :web ] = value
|
101
|
+
elsif value =~ /^<?\s*(\d+(?:\.\d+)?)\s*%$/ ## abv (alcohol by volumee)
|
102
|
+
## nb: allow leading < e.g. <0.5%
|
103
|
+
value_abv_str = $1.dup # convert to decimal? how? use float?
|
104
|
+
new_attributes[ :abv ] = value_abv_str
|
105
|
+
elsif value =~ /^(\d+(?:\.\d+)?)°$/ ## plato (stammwuerze/gravity?) e.g. 11.2°
|
106
|
+
## nb: no whitespace allowed between ° and number e.g. 11.2°
|
107
|
+
value_og_str = $1.dup # convert to decimal? how? use float?
|
108
|
+
new_attributes[ :og ] = value_og_str
|
109
|
+
elsif value =~ /^(\d+(?:\.\d+)?)\s*kcal(?:\/100ml)?$/ ## kcal
|
110
|
+
## nb: allow 44.4 kcal/100ml or 44.4 kcal or 44.4kcal
|
111
|
+
value_kcal_str = $1.dup # convert to decimal? how? use float?
|
112
|
+
new_attributes[ :kcal ] = value_kcal_str
|
113
|
+
elsif (values.size==(index+1)) && value =~ /^[a-z0-9\|_ ]+$/ # tags must be last entry
|
114
|
+
|
115
|
+
logger.debug " found tags: >>#{value}<<"
|
116
|
+
|
117
|
+
tag_keys = value.split('|')
|
118
|
+
|
119
|
+
## unify; replace _ w/ space; remove leading n trailing whitespace
|
120
|
+
tag_keys = tag_keys.map do |key|
|
121
|
+
key = key.gsub( '_', ' ' )
|
122
|
+
key = key.strip
|
123
|
+
key
|
124
|
+
end
|
125
|
+
|
126
|
+
value_tag_keys += tag_keys
|
127
|
+
else
|
128
|
+
# issue warning: unknown type for value
|
129
|
+
logger.warn "unknown type for value >#{value}<"
|
130
|
+
end
|
131
|
+
end # each value
|
132
|
+
|
133
|
+
# rec = Beer.find_by_key_and_country_id( new_attributes[ :key ], new_attributes[ :country_id] )
|
134
|
+
rec = Beer.find_by_key( new_attributes[ :key ] )
|
135
|
+
|
136
|
+
if rec.present?
|
137
|
+
logger.debug "update Beer #{rec.id}-#{rec.key}:"
|
138
|
+
else
|
139
|
+
logger.debug "create Beer:"
|
140
|
+
rec = Beer.new
|
141
|
+
end
|
142
|
+
|
143
|
+
logger.debug new_attributes.to_json
|
144
|
+
|
145
|
+
rec.update_attributes!( new_attributes )
|
146
|
+
|
147
|
+
##################
|
148
|
+
# add taggings
|
149
|
+
|
150
|
+
if value_tag_keys.size > 0
|
151
|
+
|
152
|
+
value_tag_keys.uniq! # remove duplicates
|
153
|
+
logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
|
154
|
+
|
155
|
+
### fix/todo: check tag_ids and only update diff (add/remove ids)
|
156
|
+
|
157
|
+
value_tag_keys.each do |key|
|
158
|
+
tag = Tag.find_by_key( key )
|
159
|
+
if tag.nil? # create tag if it doesn't exit
|
160
|
+
logger.debug " creating tag >#{key}<"
|
161
|
+
tag = Tag.create!( key: key )
|
162
|
+
end
|
163
|
+
rec.tags << tag
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end # method create_or_update_from_values
|
168
|
+
|
169
|
+
end # class Beer
|
35
170
|
|
36
171
|
end # module BeerDb::Models
|
@@ -24,6 +24,119 @@ class Brewery < ActiveRecord::Base
|
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
|
+
|
28
|
+
def self.create_or_update_from_values( new_attributes, values )
|
29
|
+
|
30
|
+
value_tag_keys = []
|
31
|
+
|
32
|
+
### check for "default" tags - that is, if present new_attributes[:tags] remove from hash
|
33
|
+
|
34
|
+
if new_attributes[:tags].present?
|
35
|
+
more_tag_keys = new_attributes[:tags].split('|')
|
36
|
+
new_attributes.delete(:tags)
|
37
|
+
|
38
|
+
## unify; replace _ w/ space; remove leading n trailing whitespace
|
39
|
+
more_tag_keys = more_tag_keys.map do |key|
|
40
|
+
key = key.gsub( '_', ' ' )
|
41
|
+
key = key.strip
|
42
|
+
key
|
43
|
+
end
|
44
|
+
|
45
|
+
value_tag_keys += more_tag_keys
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
## check for optional values
|
50
|
+
values.each_with_index do |value,index|
|
51
|
+
if value =~ /^country:/ ## country:
|
52
|
+
value_country_key = value[8..-1] ## cut off country: prefix
|
53
|
+
value_country = Country.find_by_key!( value_country_key )
|
54
|
+
new_attributes[ :country_id ] = value_country.id
|
55
|
+
elsif value =~ /^region:/ ## region:
|
56
|
+
value_region_key = value[7..-1] ## cut off region: prefix
|
57
|
+
value_region = Region.find_by_key_and_country_id!( value_region_key, new_attributes[:country_id] )
|
58
|
+
new_attributes[ :region_id ] = value_region.id
|
59
|
+
elsif value =~ /^[A-Z]{1,2}$/ ## assume region code e.g. TX or N
|
60
|
+
value_region = Region.find_by_key_and_country_id!( value.downcase, new_attributes[:country_id] )
|
61
|
+
new_attributes[ :region_id ] = value_region.id
|
62
|
+
elsif value =~ /^city:/ ## city:
|
63
|
+
value_city_key = value[5..-1] ## cut off city: prefix
|
64
|
+
value_city = City.find_by_key( value_city_key )
|
65
|
+
if value_city.present?
|
66
|
+
new_attributes[ :city_id ] = value_city.id
|
67
|
+
else
|
68
|
+
## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
|
69
|
+
logger.warn "city with key #{value_city_key} missing"
|
70
|
+
end
|
71
|
+
|
72
|
+
## for easy queries: cache region_id (from city)
|
73
|
+
# - check if city w/ region if yes, use it for brewery too
|
74
|
+
if value_city.present? && value_city.region.present?
|
75
|
+
new_attributes[ :region_id ] = value_city.region.id
|
76
|
+
end
|
77
|
+
elsif value =~ /^[0-9]{4}$/ # founded/established year e.g. 1776
|
78
|
+
new_attributes[ :since ] = value.to_i
|
79
|
+
elsif value =~ /^www\.|\.com$/ # check for url/internet address e.g. www.ottakringer.at
|
80
|
+
# fix: support more url format (e.g. w/o www. - look for .com .country code etc.)
|
81
|
+
new_attributes[ :web ] = value
|
82
|
+
elsif value =~ /\/{2}/ # if value includes // assume address e.g. 3970 Weitra // Sparkasseplatz 160
|
83
|
+
new_attributes[ :address ] = value
|
84
|
+
elsif (values.size==(index+1)) && value =~ /^[a-z0-9\|_ ]+$/ # tags must be last entry
|
85
|
+
|
86
|
+
logger.debug " found tags: >>#{value}<<"
|
87
|
+
|
88
|
+
tag_keys = value.split('|')
|
89
|
+
|
90
|
+
## unify; replace _ w/ space; remove leading n trailing whitespace
|
91
|
+
tag_keys = tag_keys.map do |key|
|
92
|
+
key = key.gsub( '_', ' ' )
|
93
|
+
key = key.strip
|
94
|
+
key
|
95
|
+
end
|
96
|
+
|
97
|
+
value_tag_keys += tag_keys
|
98
|
+
else
|
99
|
+
# issue warning: unknown type for value
|
100
|
+
logger.warn "unknown type for value >#{value}<"
|
101
|
+
end
|
102
|
+
end # each value
|
103
|
+
|
104
|
+
## todo: check better style using self.find_by_key?? why? why not?
|
105
|
+
rec = Brewery.find_by_key( new_attributes[ :key ] )
|
106
|
+
|
107
|
+
if rec.present?
|
108
|
+
logger.debug "update Brewery #{rec.id}-#{rec.key}:"
|
109
|
+
else
|
110
|
+
logger.debug "create Brewery:"
|
111
|
+
rec = Brewery.new
|
112
|
+
end
|
113
|
+
|
114
|
+
logger.debug new_attributes.to_json
|
115
|
+
|
116
|
+
rec.update_attributes!( new_attributes )
|
117
|
+
|
118
|
+
##################
|
119
|
+
## add taggings
|
120
|
+
|
121
|
+
if value_tag_keys.size > 0
|
122
|
+
|
123
|
+
value_tag_keys.uniq! # remove duplicates
|
124
|
+
logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
|
125
|
+
|
126
|
+
### fix/todo: check tag_ids and only update diff (add/remove ids)
|
127
|
+
|
128
|
+
value_tag_keys.each do |key|
|
129
|
+
tag = Tag.find_by_key( key )
|
130
|
+
if tag.nil? # create tag if it doesn't exit
|
131
|
+
logger.debug " creating tag >#{key}<"
|
132
|
+
tag = Tag.create!( key: key )
|
133
|
+
end
|
134
|
+
rec.tags << tag
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end # method create_or_update_from_values
|
139
|
+
|
27
140
|
end # class Brewery
|
28
141
|
|
29
142
|
|
data/lib/beerdb/reader.rb
CHANGED
@@ -90,7 +90,9 @@ class Reader
|
|
90
90
|
|
91
91
|
reader = ValuesReader.new( path, more_values )
|
92
92
|
|
93
|
-
|
93
|
+
reader.each_line do |new_attributes, values|
|
94
|
+
Beer.create_or_update_from_values( new_attributes, values )
|
95
|
+
end # each_line
|
94
96
|
|
95
97
|
Prop.create_from_fixture!( name, path )
|
96
98
|
end
|
@@ -107,272 +109,13 @@ class Reader
|
|
107
109
|
logger.info "parsing data '#{name}' (#{path})..."
|
108
110
|
|
109
111
|
reader = ValuesReader.new( path, more_values )
|
110
|
-
|
111
|
-
|
112
|
+
|
113
|
+
reader.each_line do |new_attributes, values|
|
114
|
+
Brewery.create_or_update_from_values( new_attributes, values )
|
115
|
+
end # each_line
|
112
116
|
|
113
117
|
Prop.create_from_fixture!( name, path )
|
114
118
|
end
|
115
119
|
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
def load_breweries_worker( reader )
|
120
|
-
|
121
|
-
## NB: assumes active activerecord db connection
|
122
|
-
|
123
|
-
reader.each_line do |attribs, values|
|
124
|
-
|
125
|
-
|
126
|
-
### todo/fix: move this code to model (lets us reuse it)
|
127
|
-
|
128
|
-
value_tag_keys = []
|
129
|
-
|
130
|
-
### check for "default" tags - that is, if present attribs[:tags] remove from hash
|
131
|
-
|
132
|
-
if attribs[:tags].present?
|
133
|
-
more_tag_keys = attribs[:tags].split('|')
|
134
|
-
attribs.delete(:tags)
|
135
|
-
|
136
|
-
## unify; replace _ w/ space; remove leading n trailing whitespace
|
137
|
-
more_tag_keys = more_tag_keys.map do |key|
|
138
|
-
key = key.gsub( '_', ' ' )
|
139
|
-
key = key.strip
|
140
|
-
key
|
141
|
-
end
|
142
|
-
|
143
|
-
value_tag_keys += more_tag_keys
|
144
|
-
end
|
145
|
-
|
146
|
-
|
147
|
-
## check for optional values
|
148
|
-
values.each_with_index do |value,index|
|
149
|
-
if value =~ /^country:/ ## country:
|
150
|
-
value_country_key = value[8..-1] ## cut off country: prefix
|
151
|
-
value_country = Country.find_by_key!( value_country_key )
|
152
|
-
attribs[ :country_id ] = value_country.id
|
153
|
-
elsif value =~ /^region:/ ## region:
|
154
|
-
value_region_key = value[7..-1] ## cut off region: prefix
|
155
|
-
value_region = Region.find_by_key_and_country_id!( value_region_key, attribs[:country_id] )
|
156
|
-
attribs[ :region_id ] = value_region.id
|
157
|
-
elsif value =~ /^[A-Z]{1,2}$/ ## assume region code e.g. TX or N
|
158
|
-
value_region = Region.find_by_key_and_country_id!( value.downcase, attribs[:country_id] )
|
159
|
-
attribs[ :region_id ] = value_region.id
|
160
|
-
elsif value =~ /^city:/ ## city:
|
161
|
-
value_city_key = value[5..-1] ## cut off city: prefix
|
162
|
-
value_city = City.find_by_key( value_city_key )
|
163
|
-
if value_city.present?
|
164
|
-
attribs[ :city_id ] = value_city.id
|
165
|
-
else
|
166
|
-
## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
|
167
|
-
logger.warn "city with key #{value_city_key} missing"
|
168
|
-
end
|
169
|
-
|
170
|
-
## for easy queries: cache region_id (from city)
|
171
|
-
# - check if city w/ region if yes, use it for brewery too
|
172
|
-
if value_city.present? && value_city.region.present?
|
173
|
-
attribs[ :region_id ] = value_city.region.id
|
174
|
-
end
|
175
|
-
elsif value =~ /^[0-9]{4}$/ # founded/established year e.g. 1776
|
176
|
-
attribs[ :since ] = value.to_i
|
177
|
-
elsif value =~ /\/{2}/ # if value includes // assume address e.g. 3970 Weitra // Sparkasseplatz 160
|
178
|
-
attribs[ :address ] = value
|
179
|
-
elsif (values.size==(index+1)) && value =~ /^[a-z0-9\|_ ]+$/ # tags must be last entry
|
180
|
-
|
181
|
-
logger.debug " found tags: >>#{value}<<"
|
182
|
-
|
183
|
-
tag_keys = value.split('|')
|
184
|
-
|
185
|
-
## unify; replace _ w/ space; remove leading n trailing whitespace
|
186
|
-
tag_keys = tag_keys.map do |key|
|
187
|
-
key = key.gsub( '_', ' ' )
|
188
|
-
key = key.strip
|
189
|
-
key
|
190
|
-
end
|
191
|
-
|
192
|
-
value_tag_keys += tag_keys
|
193
|
-
else
|
194
|
-
# issue warning: unknown type for value
|
195
|
-
logger.warn "unknown type for value >#{value}<"
|
196
|
-
end
|
197
|
-
end # each value
|
198
|
-
|
199
|
-
rec = Brewery.find_by_key( attribs[ :key ] )
|
200
|
-
|
201
|
-
if rec.present?
|
202
|
-
logger.debug "update Brewery #{rec.id}-#{rec.key}:"
|
203
|
-
else
|
204
|
-
logger.debug "create Brewery:"
|
205
|
-
rec = Brewery.new
|
206
|
-
end
|
207
|
-
|
208
|
-
logger.debug attribs.to_json
|
209
|
-
|
210
|
-
rec.update_attributes!( attribs )
|
211
|
-
|
212
|
-
##################
|
213
|
-
## add taggings
|
214
|
-
|
215
|
-
if value_tag_keys.size > 0
|
216
|
-
|
217
|
-
value_tag_keys.uniq! # remove duplicates
|
218
|
-
logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
|
219
|
-
|
220
|
-
### fix/todo: check tag_ids and only update diff (add/remove ids)
|
221
|
-
|
222
|
-
value_tag_keys.each do |key|
|
223
|
-
tag = Tag.find_by_key( key )
|
224
|
-
if tag.nil? # create tag if it doesn't exit
|
225
|
-
logger.debug " creating tag >#{key}<"
|
226
|
-
tag = Tag.create!( key: key )
|
227
|
-
end
|
228
|
-
rec.tags << tag
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
end # each_line
|
233
|
-
|
234
|
-
end # method load_breweries_worker
|
235
|
-
|
236
|
-
|
237
|
-
def load_beers_worker( reader )
|
238
|
-
|
239
|
-
## NB: assumes active activerecord db connection
|
240
|
-
##
|
241
|
-
|
242
|
-
reader.each_line do |attribs, values|
|
243
|
-
|
244
|
-
### todo/fix: move this code to model (lets us reuse it)
|
245
|
-
|
246
|
-
value_tag_keys = []
|
247
|
-
|
248
|
-
### check for "default" tags - that is, if present attribs[:tags] remove from hash
|
249
|
-
|
250
|
-
if attribs[:tags].present?
|
251
|
-
more_tag_keys = attribs[:tags].split('|')
|
252
|
-
attribs.delete(:tags)
|
253
|
-
|
254
|
-
## unify; replace _ w/ space; remove leading n trailing whitespace
|
255
|
-
more_tag_keys = more_tag_keys.map do |key|
|
256
|
-
key = key.gsub( '_', ' ' )
|
257
|
-
key = key.strip
|
258
|
-
key
|
259
|
-
end
|
260
|
-
|
261
|
-
value_tag_keys += more_tag_keys
|
262
|
-
end
|
263
|
-
|
264
|
-
|
265
|
-
## check for optional values
|
266
|
-
values.each_with_index do |value,index|
|
267
|
-
if value =~ /^country:/ ## country:
|
268
|
-
value_country_key = value[8..-1] ## cut off country: prefix
|
269
|
-
value_country = Country.find_by_key!( value_country_key )
|
270
|
-
attribs[ :country_id ] = value_country.id
|
271
|
-
elsif value =~ /^region:/ ## region:
|
272
|
-
value_region_key = value[7..-1] ## cut off region: prefix
|
273
|
-
value_region = Region.find_by_key_and_country_id!( value_region_key, attribs[:country_id] )
|
274
|
-
attribs[ :region_id ] = value_region.id
|
275
|
-
elsif value =~ /^[A-Z]{1,2}$/ ## assume region code e.g. TX or N
|
276
|
-
value_region = Region.find_by_key_and_country_id!( value.downcase, attribs[:country_id] )
|
277
|
-
attribs[ :region_id ] = value_region.id
|
278
|
-
elsif value =~ /^city:/ ## city:
|
279
|
-
value_city_key = value[5..-1] ## cut off city: prefix
|
280
|
-
value_city = City.find_by_key( value_city_key )
|
281
|
-
if value_city.present?
|
282
|
-
attribs[ :city_id ] = value_city.id
|
283
|
-
else
|
284
|
-
## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
|
285
|
-
logger.warn "city with key #{value_city_key} missing"
|
286
|
-
end
|
287
|
-
elsif value =~ /^by:/ ## by: -brewed by/brewery
|
288
|
-
value_brewery_key = value[3..-1] ## cut off by: prefix
|
289
|
-
value_brewery = Brewery.find_by_key!( value_brewery_key )
|
290
|
-
attribs[ :brewery_id ] = value_brewery.id
|
291
|
-
|
292
|
-
# for easy queries cache city and region ids
|
293
|
-
|
294
|
-
# 1) check if brewery has city - if yes, use it for beer too
|
295
|
-
if value_brewery.city.present?
|
296
|
-
attribs[ :city_id ] = value_brewery.city.id
|
297
|
-
end
|
298
|
-
|
299
|
-
# 2) check if brewery has city w/ region if yes, use it for beer to
|
300
|
-
# if not check for region for brewery
|
301
|
-
if value_brewery.city.present? && value_brewery.city.region.present?
|
302
|
-
attribs[ :region_id ] = value_brewery.city.region.id
|
303
|
-
elsif value_brewery.region.present?
|
304
|
-
attribs[ :region_id ] = value_brewery.region.id
|
305
|
-
end
|
306
|
-
|
307
|
-
elsif value =~ /^<?\s*(\d+(?:\.\d+)?)\s*%$/ ## abv (alcohol by volumee)
|
308
|
-
## nb: allow leading < e.g. <0.5%
|
309
|
-
value_abv_str = $1.dup # convert to decimal? how? use float?
|
310
|
-
attribs[ :abv ] = value_abv_str
|
311
|
-
elsif value =~ /^(\d+(?:\.\d+)?)°$/ ## plato (stammwuerze/gravity?) e.g. 11.2°
|
312
|
-
## nb: no whitespace allowed between ° and number e.g. 11.2°
|
313
|
-
value_og_str = $1.dup # convert to decimal? how? use float?
|
314
|
-
attribs[ :og ] = value_og_str
|
315
|
-
elsif value =~ /^(\d+(?:\.\d+)?)\s*kcal(?:\/100ml)?$/ ## kcal
|
316
|
-
## nb: allow 44.4 kcal/100ml or 44.4 kcal or 44.4kcal
|
317
|
-
value_kcal_str = $1.dup # convert to decimal? how? use float?
|
318
|
-
attribs[ :kcal ] = value_kcal_str
|
319
|
-
elsif (values.size==(index+1)) && value =~ /^[a-z0-9\|_ ]+$/ # tags must be last entry
|
320
|
-
|
321
|
-
logger.debug " found tags: >>#{value}<<"
|
322
|
-
|
323
|
-
tag_keys = value.split('|')
|
324
|
-
|
325
|
-
## unify; replace _ w/ space; remove leading n trailing whitespace
|
326
|
-
tag_keys = tag_keys.map do |key|
|
327
|
-
key = key.gsub( '_', ' ' )
|
328
|
-
key = key.strip
|
329
|
-
key
|
330
|
-
end
|
331
|
-
|
332
|
-
value_tag_keys += tag_keys
|
333
|
-
else
|
334
|
-
# issue warning: unknown type for value
|
335
|
-
logger.warn "unknown type for value >#{value}<"
|
336
|
-
end
|
337
|
-
end # each value
|
338
|
-
|
339
|
-
# rec = Beer.find_by_key_and_country_id( attribs[ :key ], attribs[ :country_id] )
|
340
|
-
rec = Beer.find_by_key( attribs[ :key ] )
|
341
|
-
|
342
|
-
if rec.present?
|
343
|
-
logger.debug "update Beer #{rec.id}-#{rec.key}:"
|
344
|
-
else
|
345
|
-
logger.debug "create Beer:"
|
346
|
-
rec = Beer.new
|
347
|
-
end
|
348
|
-
|
349
|
-
logger.debug attribs.to_json
|
350
|
-
|
351
|
-
rec.update_attributes!( attribs )
|
352
|
-
|
353
|
-
##################
|
354
|
-
## add taggings
|
355
|
-
|
356
|
-
if value_tag_keys.size > 0
|
357
|
-
|
358
|
-
value_tag_keys.uniq! # remove duplicates
|
359
|
-
logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
|
360
|
-
|
361
|
-
### fix/todo: check tag_ids and only update diff (add/remove ids)
|
362
|
-
|
363
|
-
value_tag_keys.each do |key|
|
364
|
-
tag = Tag.find_by_key( key )
|
365
|
-
if tag.nil? # create tag if it doesn't exit
|
366
|
-
logger.debug " creating tag >#{key}<"
|
367
|
-
tag = Tag.create!( key: key )
|
368
|
-
end
|
369
|
-
rec.tags << tag
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
end # each_line
|
374
|
-
|
375
|
-
end # method load_beers_worker
|
376
|
-
|
377
120
|
end # class Reader
|
378
121
|
end # module BeerDb
|
data/lib/beerdb/schema.rb
CHANGED
@@ -27,8 +27,8 @@ create_table :beers do |t|
|
|
27
27
|
|
28
28
|
## check: why decimal and not float?
|
29
29
|
t.decimal :abv # Alcohol by volume (abbreviated as ABV, abv, or alc/vol) e.g. 4.9 %
|
30
|
-
t.decimal :og
|
31
|
-
t.integer :srm
|
30
|
+
t.decimal :og # malt extract (original gravity) in plato
|
31
|
+
t.integer :srm # color in srm
|
32
32
|
|
33
33
|
### fix/todo: add bitterness field
|
34
34
|
|
@@ -69,9 +69,14 @@ create_table :breweries do |t|
|
|
69
69
|
t.string :title, :null => false
|
70
70
|
t.string :synonyms # comma separated list of synonyms
|
71
71
|
t.string :address
|
72
|
-
t.
|
72
|
+
t.integer :since
|
73
73
|
## renamed to founded to since
|
74
74
|
## t.integer :founded # year founded/established - todo/fix: rename to since?
|
75
|
+
t.integer :closed # optional; year brewery closed
|
76
|
+
|
77
|
+
## todo: add optional parent brewery (owned_by)
|
78
|
+
|
79
|
+
t.integer :prod # (estimated) annual production in hl (1hl=100l) e.g. megabrewery 2_000_000, microbrewery 1_000 hl; brewbup 500 hl etc.
|
75
80
|
|
76
81
|
t.string :web # optional web page (e.g. www.ottakringer.at)
|
77
82
|
|
data/lib/beerdb/server.rb
CHANGED
@@ -110,9 +110,13 @@ class Server < Sinatra::Base
|
|
110
110
|
title: brewery.country.title
|
111
111
|
}
|
112
112
|
|
113
|
-
data = { brewery: { key: brewery.key,
|
113
|
+
data = { brewery: { key: brewery.key,
|
114
|
+
title: brewery.title,
|
115
|
+
synonyms: brewery.synonyms,
|
114
116
|
since: brewery.since,
|
115
117
|
address: brewery.address,
|
118
|
+
web: brewery.web,
|
119
|
+
prod: brewery.prod, # (estimated) annual production in hl e.g. 2_000 hl
|
116
120
|
tags: tags,
|
117
121
|
beers: beers,
|
118
122
|
country: country }}
|
data/lib/beerdb/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beerdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement: &
|
16
|
+
requirement: &75828730 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.2'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *75828730
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: worlddb
|
27
|
-
requirement: &
|
27
|
+
requirement: &75828510 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.6'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *75828510
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: commander
|
38
|
-
requirement: &
|
38
|
+
requirement: &75828290 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 4.1.3
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *75828290
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rdoc
|
49
|
-
requirement: &
|
49
|
+
requirement: &75828070 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '3.10'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *75828070
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: hoe
|
60
|
-
requirement: &
|
60
|
+
requirement: &75827850 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,9 +65,9 @@ dependencies:
|
|
65
65
|
version: '3.3'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *75827850
|
69
69
|
description: beerdb - beer.db command line tool
|
70
|
-
email:
|
70
|
+
email: beerdb@googlegroups.com
|
71
71
|
executables:
|
72
72
|
- beerdb
|
73
73
|
extensions: []
|