brewscribe 0.0.1 → 0.1.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/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