beerdb-models 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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