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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 81cbea581c2fdb972632982aa387c16ad9c8120c
4
+ data.tar.gz: 8865a095da2b63a7e11447452226d29af752d8d3
5
+ SHA512:
6
+ metadata.gz: 541a57ed981411438c18a0e40f9d276c84e9922d3dbe084aec5c4b807ec425e72b502cd5d15598278200fd1e514b8d1574b08094a440a7dad67f69dbf3a650f1
7
+ data.tar.gz: e9cc5b27bb0e342ca75e70b052743b5fe23b9b5fff12c77081028476d59fd5d7433f25d6b07273375aae9dc414863ecaa5eebdefdce5501e4bee0f25417ce479
data/.gemtest ADDED
File without changes
data/HISTORY.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2012-10-17
2
+
3
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,25 @@
1
+ HISTORY.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/beerdb/deleter.rb
6
+ lib/beerdb/models.rb
7
+ lib/beerdb/models/beer.rb
8
+ lib/beerdb/models/brand.rb
9
+ lib/beerdb/models/brewery.rb
10
+ lib/beerdb/models/forward.rb
11
+ lib/beerdb/models/tag.rb
12
+ lib/beerdb/models/world/city.rb
13
+ lib/beerdb/models/world/country.rb
14
+ lib/beerdb/models/world/region.rb
15
+ lib/beerdb/reader.rb
16
+ lib/beerdb/reader_file.rb
17
+ lib/beerdb/reader_zip.rb
18
+ lib/beerdb/schema.rb
19
+ lib/beerdb/serializers/beer.rb
20
+ lib/beerdb/serializers/brewery.rb
21
+ lib/beerdb/stats.rb
22
+ lib/beerdb/version.rb
23
+ test/helper.rb
24
+ test/test_fixture_matchers.rb
25
+ test/test_values.rb
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # beerdb-models - beer.db schema 'n' models for easy (re)use
2
+
3
+
4
+ * home :: [github.com/beerkit/beer.db.models](https://github.com/beerkit/beer.db.models)
5
+ * bugs :: [github.com/beerkit/beer.db.models/issues](https://github.com/beerkit/beer.db.models/issues)
6
+ * gem :: [rubygems.org/gems/beerdb-models](https://rubygems.org/gems/beerdb-models)
7
+ * rdoc :: [rubydoc.info/gems/beerdb-models](http://rubydoc.info/gems/beerdb-models)
8
+ * forum :: [groups.google.com/group/beerdb](https://groups.google.com/group/beerdb)
9
+
10
+
11
+ ## Usage Models
12
+
13
+ Brewery Model
14
+
15
+ ```
16
+ by = Brewery.find_by_key( 'guinness' )
17
+
18
+ by.title
19
+ => 'St. James's Gate Brewery / Guinness Brewery'
20
+
21
+ by.country.key
22
+ => 'ie'
23
+
24
+ by.country.title
25
+ => 'Ireland'
26
+
27
+ by.city.title
28
+ => 'Dublin'
29
+
30
+ by.beers.first
31
+ => 'Guinness', 4.2
32
+
33
+ ...
34
+ ```
35
+
36
+
37
+ Beer Model
38
+
39
+ ```
40
+ b = Beer.find_by_key( 'guinness' )
41
+
42
+ b.title
43
+ => 'Guinness'
44
+
45
+ b.abv
46
+ => 4.2
47
+
48
+ b.tags
49
+ => 'irish_dry_stout', 'dry_stout', 'stout'
50
+
51
+ b.brewery.title
52
+ => 'St. James's Gate Brewery / Guinness Brewery'
53
+
54
+ ...
55
+ ```
56
+
57
+
58
+ Country Model
59
+
60
+ ```
61
+ at = Country.find_by_key( 'at' )
62
+
63
+ at.beers
64
+ => 'Weitra Helles', 'Hadmar', 'Zwettler Original', ...
65
+
66
+ at.breweries
67
+ => 'Weitra Bräu Bierwerkstatt', 'Zwettler Brauerei', ...
68
+
69
+ ...
70
+ ```
71
+
72
+
73
+ City Model
74
+
75
+ ```
76
+ wien = City.find_by_key( 'wien' )
77
+
78
+ wien.beers
79
+ => 'Ottakringer Helles', 'Ottakringer (Gold Fassl) Zwickl', ...
80
+
81
+ wien.breweries
82
+ => 'Ottakringer Brauerei'
83
+
84
+ ...
85
+ ```
86
+
87
+
88
+ ## License
89
+
90
+ The `beerdb-models` scripts are dedicated to the public domain.
91
+ Use it as you please with no restrictions whatsoever.
92
+
93
+ ## Questions? Comments?
94
+
95
+ Send them along to the [Open Beer & Brewery Database Forum/Mailing List](http://groups.google.com/group/beerdb).
96
+ Thanks!
97
+
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'hoe'
2
+ require './lib/beerdb/version.rb'
3
+
4
+
5
+ Hoe.spec 'beerdb-models' do
6
+
7
+ self.version = BeerDb::VERSION
8
+
9
+ self.summary = "beerdb-models - beer.db schema 'n' models for easy (re)use"
10
+ self.description = summary
11
+
12
+ self.urls = ['https://github.com/beerkit/beer.db.models']
13
+
14
+ self.author = 'Gerald Bauer'
15
+ self.email = 'beerdb@googlegroups.com'
16
+
17
+ # switch extension to .markdown for gihub formatting
18
+ self.readme_file = 'README.md'
19
+ self.history_file = 'HISTORY.md'
20
+
21
+ self.extra_deps = [
22
+ ['worlddb-models', '>= 2.2.0'], # Note: worlddb-models pulls in all dependencies
23
+ ]
24
+
25
+ self.licenses = ['Public Domain']
26
+
27
+ self.spec_extras = {
28
+ required_ruby_version: '>= 1.9.2'
29
+ }
30
+
31
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ module BeerDb
4
+
5
+ class Deleter
6
+
7
+ include Models
8
+
9
+ def run
10
+ # for now delete all tables
11
+
12
+ ### fix: use if defined? BeerDbNote or similar or/and check if table exist ??
13
+ ### or move to beerdb-note ??
14
+
15
+ ## Bookmark.delete_all # db model extension - move to its own addon?
16
+ ## Drink.delete_all # db model extension - move to its own addon?
17
+ ## Note.delete_all # db model extension - move to its own addon?
18
+ ## User.delete_all # db model extension - move to its own addon?
19
+
20
+ Beer.delete_all
21
+ Brand.delete_all
22
+ Brewery.delete_all
23
+ end
24
+
25
+ end # class Deleter
26
+
27
+ end # module BeerDb
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ require 'worlddb/models' # Note: pull in all required stdlibs n gems via worlddb/models
5
+
6
+
7
+ # our own code
8
+
9
+ require 'beerdb/version' ## version always goes first
10
+
11
+ require 'beerdb/models/forward'
12
+ require 'beerdb/models/world/country'
13
+ require 'beerdb/models/world/region'
14
+ require 'beerdb/models/world/city'
15
+ require 'beerdb/models/tag'
16
+ require 'beerdb/models/beer'
17
+ require 'beerdb/models/brand'
18
+ require 'beerdb/models/brewery'
19
+
20
+
21
+ require 'beerdb/serializers/beer'
22
+ require 'beerdb/serializers/brewery'
23
+
24
+ require 'beerdb/schema'
25
+ require 'beerdb/reader'
26
+ require 'beerdb/reader_file'
27
+ require 'beerdb/reader_zip'
28
+ require 'beerdb/deleter'
29
+ require 'beerdb/stats'
30
+
31
+
32
+ module BeerDb
33
+
34
+
35
+ def self.create
36
+ CreateDb.new.up
37
+
38
+ ### fix: make optional do NOT auto create here
39
+ ### fix: use if defined? BeerDbNote or similar or/and check if table exist ??
40
+ ### or move to beerdb-note ??
41
+
42
+ # CreateDbExtrasUsers.new.up
43
+ # CreateDbExtrasBookmarks.new.up
44
+ # CreateDbExtrasDrinks.new.up
45
+ # CreateDbExtrasNotes.new.up
46
+
47
+ ConfDb::Model::Prop.create!( key: 'db.schema.beer.version', value: VERSION )
48
+ end
49
+
50
+ ## convenience helper for all-in-one create for tables
51
+ def self.create_all
52
+ LogDb.create
53
+ ConfDb.create
54
+ TagDb.create
55
+ WorldDb.create
56
+ BeerDb.create
57
+ end
58
+
59
+
60
+ def self.read( ary, include_path )
61
+ reader = Reader.new( include_path )
62
+ ary.each do |name|
63
+ reader.load( name )
64
+ end
65
+ end
66
+
67
+ def self.read_setup( setup, include_path, opts={} )
68
+ reader = Reader.new( include_path, opts )
69
+ reader.load_setup( setup )
70
+ end
71
+
72
+ def self.read_setup_from_zip( zip_name, setup, include_path, opts={} ) ## todo/check - use a better (shorter) name ??
73
+ reader = ZipReader.new( zip_name, include_path, opts )
74
+ reader.load_setup( setup )
75
+ reader.close
76
+ end
77
+
78
+ def self.read_all( include_path, opts={} ) # load all builtins (using plain text reader); helper for convenience
79
+ read_setup( 'setups/all', include_path, opts )
80
+ end # method read_all
81
+
82
+
83
+ # delete ALL records (use with care!)
84
+ def self.delete!
85
+ puts '*** deleting beer table records/data...'
86
+ Deleter.new.run
87
+ end # method delete!
88
+
89
+ def self.delete_all!( opts={} )
90
+ # to be done
91
+ end
92
+
93
+ def self.tables
94
+ Stats.new.tables
95
+ end
96
+
97
+
98
+ end # module BeerDb
99
+
100
+
101
+
102
+ # say hello
103
+ puts BeerDb.banner if $DEBUG || (defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG)
@@ -0,0 +1,201 @@
1
+ # encoding: UTF-8
2
+
3
+ module BeerDb
4
+ module Model
5
+
6
+ class Beer < 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?, self.is_address?, is_taglist? etc.
13
+
14
+ belongs_to :country, :class_name => 'WorldDb::Model::Country', :foreign_key => 'country_id'
15
+ belongs_to :region, :class_name => 'WorldDb::Model::Region', :foreign_key => 'region_id'
16
+ belongs_to :city, :class_name => 'WorldDb::Model::City', :foreign_key => 'city_id'
17
+
18
+ belongs_to :brand, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'brand_id'
19
+ belongs_to :brewery, :class_name => 'BeerDb::Model::Brewery', :foreign_key => 'brewery_id'
20
+
21
+
22
+ has_many :taggings, class_name: 'TagDb::Model::Tagging', :as => :taggable
23
+ has_many :tags, class_name: 'TagDb::Model::Tag', :through => :taggings
24
+
25
+
26
+ ## fix/todo: move to regex to patterns; see worlddb
27
+ validates :key, :format => { :with => /\A[a-z][a-z0-9]+\z/, :message => 'expected two or more lowercase letters a-z or 0-9 digits' }
28
+
29
+
30
+ ########################
31
+ # begin extras/extension drink/bookmar/user
32
+
33
+ has_many :drinks ## :class_name => 'Drink'
34
+ has_many :notes ## :class_name => 'Note'
35
+ has_many :bookmarks, :as => :bookmarkable
36
+
37
+ # end extensions
38
+ ########
39
+
40
+
41
+ ### support old names (read-only) for now (remove later)
42
+
43
+ def color() puts "*** depreceated fn api - use srm"; srm; end
44
+ def plato() puts "*** depreceated fn api - use og"; og; end
45
+
46
+ def color=(value)
47
+ puts "*** depreceated fn api - use srm="
48
+ self.srm = value
49
+ end
50
+
51
+ def plato=(value)
52
+ puts "*** depreceated fn api - use og="
53
+ self.og = value
54
+ end
55
+
56
+
57
+ def as_json_v2( opts={} )
58
+ # NB: do NOT overwrite "default" / builtin as_json, thus, lets use as_json_v2
59
+ BeerSerializer.new( self ).as_json
60
+ end
61
+
62
+
63
+ def self.create_or_update_from_values( values, more_attribs={} )
64
+
65
+ attribs, more_values = find_key_n_title( values )
66
+ attribs = attribs.merge( more_attribs )
67
+
68
+ # check for optional values
69
+ Beer.create_or_update_from_attribs( attribs, more_values )
70
+ end
71
+
72
+
73
+ def self.create_or_update_from_attribs( attribs, values )
74
+
75
+ # fix: add/configure logger for ActiveRecord!!!
76
+ logger = LogKernel::Logger.root
77
+
78
+ value_tag_keys = []
79
+
80
+ ## check for grades (e.g. ***/**/*) in titles (will add attribs[:grade] to hash)
81
+ ## if grade missing; set default to 4; lets us update overwrite 1,2,3 values on update
82
+ attribs[ :grade ] ||= 4
83
+
84
+ ### check for "default" tags - that is, if present attribs[:tags] remove from hash
85
+ value_tag_keys += find_tags_in_attribs!( attribs )
86
+
87
+ ## check for optional values
88
+ values.each_with_index do |value,index|
89
+ if match_country(value) do |country|
90
+ attribs[ :country_id ] = country.id
91
+ end
92
+ elsif match_region_for_country(value, attribs[:country_id]) do |region|
93
+ attribs[ :region_id ] = region.id
94
+ end
95
+ elsif match_city(value) do |city|
96
+ if city.present?
97
+ attribs[ :city_id ] = city.id
98
+ else
99
+ ## todo/fix: add strict mode flag - fail w/ exit 1 in strict mode
100
+ logger.warn "city with key #{value[5..-1]} missing for beer #{attribs[:key]}"
101
+ end
102
+ end
103
+ elsif match_brewery(value) do |brewery|
104
+ attribs[ :brewery_id ] = brewery.id
105
+
106
+ # for easy queries cache city and region ids
107
+
108
+ # 1) check if brewery has city - if yes, use it for beer too
109
+ if brewery.city.present?
110
+ attribs[ :city_id ] = brewery.city.id
111
+ end
112
+
113
+ # 2) check if brewery has city w/ region if yes, use it for beer to
114
+ # if not check for region for brewery
115
+ if brewery.city.present? && brewery.city.region.present?
116
+ attribs[ :region_id ] = brewery.city.region.id
117
+ elsif brewery.region.present?
118
+ attribs[ :region_id ] = brewery.region.id
119
+ end
120
+ end
121
+ elsif match_year( value ) do |num| # founded/established year e.g. 1776
122
+ attribs[ :since ] = num
123
+ end
124
+ elsif match_website( value ) do |website| # check for url/internet address e.g. www.ottakringer.at
125
+ attribs[ :web ] = website
126
+ end
127
+ elsif match_abv( value ) do |num| # abv (alcohol by volume)
128
+ # nb: also allows leading < e.g. <0.5%
129
+ attribs[ :abv ] = num
130
+ end
131
+ elsif match_og( value ) do |num| # plato (stammwuerze/gravity?) e.g. 11.2°
132
+ # nb: no whitespace allowed between ° and number e.g. 11.2°
133
+ attribs[ :og ] = num
134
+ end
135
+ elsif match_kcal( value ) do |num| # kcal
136
+ # nb: allow 44.4 kcal/100ml or 44.4 kcal or 44.4kcal
137
+ attribs[ :kcal ] = num
138
+ end
139
+ elsif (values.size==(index+1)) && is_taglist?( value ) # tags must be last entry
140
+ logger.debug " found tags: >>#{value}<<"
141
+ value_tag_keys += find_tags( value )
142
+ else
143
+ # issue warning: unknown type for value
144
+ logger.warn "unknown type for value >#{value}< - key #{attribs[:key]}"
145
+ end
146
+ end # each value
147
+
148
+ # rec = Beer.find_by_key_and_country_id( attribs[ :key ], attribs[ :country_id] )
149
+ rec = Beer.find_by_key( attribs[ :key ] )
150
+
151
+ if rec.present?
152
+ logger.debug "update Beer #{rec.id}-#{rec.key}:"
153
+ else
154
+ logger.debug "create Beer:"
155
+ rec = Beer.new
156
+ end
157
+
158
+ logger.debug attribs.to_json
159
+
160
+ rec.update_attributes!( attribs )
161
+
162
+ ##################
163
+ # add taggings
164
+
165
+ ##
166
+ ## fix: delete all tags first or only add diff?
167
+ ## fix e.g.
168
+ ##
169
+ ## [debug] update Beer 1340-opatsvetlevycepni:
170
+ ## [debug] {"title":"Opat Světlé Výčepní","key":"opatsvetlevycepni","country_id":130,"txt":"cz-czech-republic!/beers","grade":4,"brewery_id":839,"city_id":1154,"region_id":241,"abv":4.2,"og":11.0}
171
+ ## [debug] adding 1 taggings: >>pale lager<<...
172
+ ## rake aborted!
173
+ ## 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 (?, ?, ?, ?, ?)
174
+
175
+ =begin
176
+ if value_tag_keys.size > 0
177
+
178
+ value_tag_keys.uniq! # remove duplicates
179
+ logger.debug " adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."
180
+
181
+ ### fix/todo: check tag_ids and only update diff (add/remove ids)
182
+
183
+ value_tag_keys.each do |key|
184
+ tag = Tag.find_by_key( key )
185
+ if tag.nil? # create tag if it doesn't exit
186
+ logger.debug " creating tag >#{key}<"
187
+ tag = Tag.create!( key: key )
188
+ end
189
+ rec.tags << tag
190
+ end
191
+ end
192
+ =end
193
+
194
+ rec # NB: return created or updated obj
195
+
196
+ end # method create_or_update_from_values
197
+
198
+ end # class Beer
199
+
200
+ end # module Model
201
+ end # module BeerDb