brewscribe 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ ## 0.1.0, released 2012-04-05
2
+
3
+ * Added Brewscribe::Document to represent .bsmx file
4
+ * Moved XML to Hash conversion to Brewscribe::Document, leaving Brewscribe::Recipe
5
+ to work based on the resulting Hash.
6
+ * Brewscribe::Recipe#create\_accessors removed in favor of explicit attr\_accessors
7
+ * Brewscribe#import now returns a Brewscribe::Document
8
+
9
+ ## 0.0.1, released 2012-03-23
10
+
11
+ * Added Brewscribe.import sugar to Brewscribe::Recipe.new
12
+ * Added IngredientList parsing of Brewscribe::Recipe
data/README.md CHANGED
@@ -9,8 +9,9 @@ Brewscribe is a Beersmith2 (.bsmx) file parser.
9
9
  ## Usage
10
10
 
11
11
  To start, you can import your .bsmx file with `Brewscribe.import(file)` where file
12
- is any object that responds to `#read`. This will return an array of Brewscribe::Recipe
13
- objects. You now have a parsed version of the recipe files.
12
+ is any object that responds to `#read`. This will return a `Brewscribe::Document`
13
+ object, containing all the parsed information within the file. Currently, only Recipe
14
+ objects will be parsed.
14
15
 
15
16
  By default, Brewscribe will set a text property for each attribute of the recipe, and
16
17
  if it has a parser object it will attempt to further parse the data.
@@ -18,7 +19,8 @@ if it has a parser object it will attempt to further parse the data.
18
19
  An example of this is found in `Brewscribe::IngredientList`:
19
20
 
20
21
  ```
21
- recipe = Brewscribe.import File.read './spec/support/recipe.bsmx'
22
+ document = Brewscribe.import File.read './spec/support/recipe.bsmx'
23
+ recipe = document.recipes.first
22
24
  recipe.ingredients.class # => Brewscribe::IngredientList
23
25
  recipe.ingredients.grains.class # => Array
24
26
  recipe.ingredients.grains.first.class # => Brewscribe::Grain
@@ -35,6 +37,13 @@ I <3 Contributions.
35
37
  4. Push to the branch (`git push origin my-new-feature`)
36
38
  5. Create new Pull Request
37
39
 
40
+ ## TODO
41
+
42
+ * More detailed Brewscribe::Recipe parsing. Mash info especially
43
+ * Beersmith Style parsing
44
+ * Writing back to .bsmx
45
+ * More documentation
46
+
38
47
  ## Author
39
48
 
40
49
  Created by [Andrew Nordman](https://github.com/cadwallion/).
data/lib/brewscribe.rb CHANGED
@@ -1,4 +1,5 @@
1
- require "brewscribe/version"
1
+ require 'brewscribe/version'
2
+ require 'brewscribe/document'
2
3
  require 'brewscribe/recipe'
3
4
  require 'brewscribe/ingredient_list'
4
5
  require 'brewscribe/conversion'
@@ -6,6 +7,6 @@ require 'brewscribe/conversion'
6
7
  module Brewscribe
7
8
  def self.import file
8
9
  data = file.read
9
- Recipe.new(data)
10
+ Document.new(data: data)
10
11
  end
11
12
  end
@@ -1,3 +1,4 @@
1
+ require 'date'
1
2
  module Brewscribe
2
3
  module Conversion
3
4
  BOOLEAN_CONV = ->(k) { k == '1' }
@@ -0,0 +1,77 @@
1
+ module Brewscribe
2
+ class Document
3
+ attr_reader :recipes, :raw_data, :hash
4
+
5
+ def initialize options = {}
6
+ @recipes = []
7
+
8
+ if options[:file]
9
+ @raw_data = File.read options[:file]
10
+ elsif options[:data]
11
+ @raw_data = options[:data]
12
+ end
13
+
14
+ parse_data
15
+ end
16
+
17
+ def parse_data
18
+ @xml = Nokogiri::XML(@raw_data).xpath('/Selections/Data')
19
+ @hash = xml_node_to_hash @xml.first
20
+
21
+ if @hash[:recipe].class == Hash
22
+ parse_recipes [@hash[:recipe]]
23
+ else
24
+ parse_recipes Array @hash[:recipe]
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ def parse_recipes recipes
31
+ recipes.each do |recipe_hash|
32
+ @recipes << Recipe.new(recipe_hash)
33
+ end
34
+ end
35
+
36
+ def xml_node_to_hash node
37
+ if node.element?
38
+ if node.children.size > 0
39
+ result_hash = {}
40
+
41
+ node.children.each do |child|
42
+ result = xml_node_to_hash child
43
+ property = clean_key child.name
44
+ key = property.to_sym
45
+
46
+ if child.name == 'text'
47
+ return result if !child.next && !child.previous
48
+ elsif result_hash[key]
49
+ if result_hash[key].is_a? Array
50
+ result_hash[key] << result
51
+ else
52
+ result_hash[key] = [result_hash[key]] << result
53
+ end
54
+ else
55
+ result_hash[key] = result
56
+ end
57
+ end
58
+
59
+ return result_hash
60
+ else
61
+ return nil
62
+ end
63
+ else
64
+ return node.content.to_s
65
+ end
66
+ end
67
+
68
+ def clean_key key
69
+ extracted = key.to_s.match(/(F_(\w{1,2}_)?)?(_MOD_|.+)/)[3]
70
+ if extracted == '_MOD_'
71
+ return 'last_modified'
72
+ else
73
+ extracted.downcase
74
+ end
75
+ end
76
+ end
77
+ end
@@ -3,74 +3,22 @@ require 'nokogiri'
3
3
  module Brewscribe
4
4
  class Recipe
5
5
  attr_reader :raw_data, :hash
6
-
7
- def initialize raw_data
8
- @raw_data = raw_data
9
-
10
- parse_raw_data
11
- end
12
-
13
- def parse_raw_data
14
- @xml = Nokogiri::XML(@raw_data).xpath('/Selections/Data/Recipe')
15
- @hash = xml_node_to_hash(@xml.first)
16
-
17
- create_recipe_accessors
18
- parse_ingredients
19
- end
20
-
21
- def create_recipe_accessors
22
- @hash.keys.each do |key|
23
- self.class.module_eval do
24
- attr_accessor key
25
- end
26
-
27
- self.send "#{key}=", @hash[key]
6
+ attr_accessor :age, :asst_brewer, :base_grain, :boil_vol_measured, :brewer,
7
+ :carb, :carb_vols, :color_adj_string, :date, :description, :desired_color,
8
+ :desired_ibu, :desired_og, :equipment, :fg_measured, :final_vol_measured,
9
+ :image, :image_x, :image_y, :include_starter, :ingredients, :inv_date,
10
+ :last_modified, :locked, :mash, :mash_ph, :name, :notes, :og_boil_measured,
11
+ :og_measured, :og_primary, :og_secondary, :old_boil_vol, :old_efficiency,
12
+ :old_type, :old_vol, :rating, :raw_data, :rebalance_scale, :running_gravity,
13
+ :runoff_ph, :starter_size, :stir_plate, :style, :type, :version,
14
+ :volume_measured
15
+
16
+ def initialize data = {}
17
+ data.keys.each do |key|
18
+ self.send "#{key}=", data[key]
28
19
  end
29
- end
30
-
31
- def clean_key key
32
- extracted = key.to_s.match(/(F_(\w{1,2}_)?)?(_MOD_|.+)/)[3]
33
- if extracted == '_MOD_'
34
- return 'last_modified'
35
- else
36
- extracted.downcase
37
- end
38
- end
39
-
40
- def parse_ingredients
41
- self.ingredients = IngredientList.from_data(self.ingredients[:data])
42
- end
43
-
44
- def xml_node_to_hash node
45
- if node.element?
46
- if node.children.size > 0
47
- result_hash = {}
48
-
49
- node.children.each do |child|
50
- result = xml_node_to_hash child
51
- property = clean_key child.name
52
- key = property.to_sym
53
-
54
- if child.name == 'text'
55
- return result if !child.next && !child.previous
56
- elsif result_hash[key]
57
- if result_hash[key].is_a? Array
58
- result_hash[key] << result
59
- else
60
- result_hash[key] = [result_hash[key]] << result
61
- end
62
- else
63
- result_hash[key] = result
64
- end
65
- end
66
20
 
67
- return result_hash
68
- else
69
- return nil
70
- end
71
- else
72
- return node.content.to_s
73
- end
21
+ self.ingredients = IngredientList.from_data self.ingredients[:data]
74
22
  end
75
23
  end
76
24
  end
@@ -1,3 +1,3 @@
1
1
  module Brewscribe
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -14,11 +14,11 @@ describe Brewscribe do
14
14
  Brewscribe.import(file)
15
15
  end
16
16
 
17
- it 'should return a Recipe object' do
17
+ it 'should return a Document object' do
18
18
  file = double()
19
19
  file.stub(:read)
20
20
  recipe = Brewscribe.import(file)
21
- recipe.should be_a(Brewscribe::Recipe)
21
+ recipe.should be_a(Brewscribe::Document)
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brewscribe::Document do
4
+ let(:file) { File.open(File.dirname(__FILE__) + '/support/recipe.bsmx', 'r') }
5
+ subject { Brewscribe::Document.new file: file }
6
+
7
+ describe '#parse' do
8
+ it 'should add a Recipe to recipes when a Recipe entry is found' do
9
+ subject.recipes.should have(0).recipes
10
+ hash = subject.parse
11
+ subject.recipes.should have(1).recipe
12
+ subject.recipes[0].should be_a Brewscribe::Recipe
13
+ end
14
+ end
15
+
16
+ describe '#clean_key' do
17
+ it 'converts an ugly key into something more readable' do
18
+ subject.clean_key("F_Y_BREW_DATE").should == 'brew_date'
19
+ end
20
+
21
+ it 'converts _MOD_ key to last_modified' do
22
+ subject.clean_key('_MOD_').should == 'last_modified'
23
+ end
24
+ end
25
+
26
+ describe '#xml_node_to_hash' do
27
+ it 'converts xml to a corresponding hash' do
28
+ xml = Nokogiri::XML('<foo><bar><baz>1</baz></bar><bazaar>2</bazaar></foo>')
29
+ actual = subject.xml_node_to_hash(xml.root)
30
+ expected = { bar: { baz: '1' }, bazaar: '2' }
31
+ actual.should == expected
32
+ end
33
+ end
34
+ end
data/spec/recipe_spec.rb CHANGED
@@ -1,43 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Brewscribe::Recipe do
4
- let(:recipe_file) { File.open(File.dirname(__FILE__) + '/support/recipe.bsmx', 'r') }
5
- subject { Brewscribe::Recipe.new(recipe_file.read) }
6
- describe '#parse_raw_data' do
7
- it 'should convert the recipe data into properties' do
8
- subject.brewer.should == 'CadBrew'
9
- end
10
-
11
- it 'should return a hash for nested recipe attributes' do
12
- subject.equipment.should be_a Hash
13
- subject.equipment[:name].should be_a String
14
- end
15
- end
16
-
17
- describe '#clean_key' do
18
- it 'converts an ugly key into something more readable' do
19
- subject.clean_key("F_Y_BREW_DATE").should == 'brew_date'
20
- end
21
-
22
- it 'converts _MOD_ key to last_modified' do
23
- subject.clean_key('_MOD_').should == 'last_modified'
24
- end
4
+ let(:recipe_file) { File.read(File.dirname(__FILE__) + '/support/recipe.bsmx') }
5
+ let(:data) { Brewscribe::Document.new(data: recipe_file).parse.hash[:recipe] }
6
+ subject { Brewscribe::Recipe.new(data) }
7
+ it 'should convert the recipe data into properties' do
8
+ subject.brewer.should == 'CadBrew'
25
9
  end
26
10
 
27
- describe '#xml_node_to_hash' do
28
- it 'converts xml to a corresponding hash' do
29
- xml = Nokogiri::XML('<foo><bar><baz>1</baz></bar><bazaar>2</bazaar></foo>')
30
- actual = subject.xml_node_to_hash(xml.root)
31
- expected = { bar: { baz: '1' }, bazaar: '2' }
32
- actual.should == expected
33
- end
11
+ it 'should return a hash for nested recipe attributes' do
12
+ subject.equipment.should be_a Hash
13
+ subject.equipment[:name].should be_a String
34
14
  end
35
15
 
36
- describe '#parse_ingredients' do
37
- it 'should create a Brewscribe::IngredientList object' do
38
- subject.ingredients = subject.hash[:ingredients]
39
- subject.parse_ingredients
40
- subject.ingredients.should be_a Brewscribe::IngredientList
41
- end
16
+ it 'should contain an IngredientsList' do
17
+ subject.ingredients.should be_a Brewscribe::IngredientList
42
18
  end
43
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brewscribe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.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: 2012-03-23 00:00:00.000000000 Z
12
+ date: 2012-04-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70238062434800 !ruby/object:Gem::Requirement
16
+ requirement: &70355888747600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70238062434800
24
+ version_requirements: *70355888747600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: guard
27
- requirement: &70238062434120 !ruby/object:Gem::Requirement
27
+ requirement: &70355888746600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70238062434120
35
+ version_requirements: *70355888746600
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: guard-rspec
38
- requirement: &70238062433640 !ruby/object:Gem::Requirement
38
+ requirement: &70355888744860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70238062433640
46
+ version_requirements: *70355888744860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: nokogiri
49
- requirement: &70238062433060 !ruby/object:Gem::Requirement
49
+ requirement: &70355888731820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70238062433060
57
+ version_requirements: *70355888731820
58
58
  description:
59
59
  email:
60
60
  - cadwallion@gmail.com
@@ -64,6 +64,7 @@ extra_rdoc_files: []
64
64
  files:
65
65
  - .gitignore
66
66
  - .rspec
67
+ - CHANGELOG.md
67
68
  - Gemfile
68
69
  - Guardfile
69
70
  - LICENSE
@@ -72,6 +73,7 @@ files:
72
73
  - brewscribe.gemspec
73
74
  - lib/brewscribe.rb
74
75
  - lib/brewscribe/conversion.rb
76
+ - lib/brewscribe/document.rb
75
77
  - lib/brewscribe/grain.rb
76
78
  - lib/brewscribe/hops.rb
77
79
  - lib/brewscribe/ingredient_list.rb
@@ -80,6 +82,7 @@ files:
80
82
  - lib/brewscribe/yeast.rb
81
83
  - spec/brewscribe_spec.rb
82
84
  - spec/conversion_spec.rb
85
+ - spec/document_spec.rb
83
86
  - spec/grain_spec.rb
84
87
  - spec/hops_spec.rb
85
88
  - spec/ingredient_list_spec.rb
@@ -101,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
104
  version: '0'
102
105
  segments:
103
106
  - 0
104
- hash: -1391733853884989833
107
+ hash: -1660558714471080415
105
108
  required_rubygems_version: !ruby/object:Gem::Requirement
106
109
  none: false
107
110
  requirements:
@@ -110,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
113
  version: '0'
111
114
  segments:
112
115
  - 0
113
- hash: -1391733853884989833
116
+ hash: -1660558714471080415
114
117
  requirements: []
115
118
  rubyforge_project:
116
119
  rubygems_version: 1.8.17
@@ -120,6 +123,7 @@ summary: A Beersmith (.bsmx) file parser
120
123
  test_files:
121
124
  - spec/brewscribe_spec.rb
122
125
  - spec/conversion_spec.rb
126
+ - spec/document_spec.rb
123
127
  - spec/grain_spec.rb
124
128
  - spec/hops_spec.rb
125
129
  - spec/ingredient_list_spec.rb