french_man 0.0.2 → 0.0.3

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.
@@ -0,0 +1,39 @@
1
+ # French Man
2
+
3
+ Hash and object mocking
4
+
5
+ ## Basic Example
6
+
7
+ ``` ruby
8
+ groceries = FrenchMan::Grocery.blueprint {
9
+ garlic { true }
10
+ }
11
+
12
+ groceries.garlic #=> true
13
+ groceries[:garlic] #=> true
14
+ ```
15
+
16
+ ## Bigger Example
17
+
18
+ ``` ruby
19
+ groceries = FrenchMan::Grocery.plan {
20
+ vino {
21
+ FrenchMan::Vino.plan {
22
+ red { "Syrah" }
23
+ white { "Cabernet Sauvignon" }
24
+ }
25
+ }
26
+ cheeses {
27
+ ['Camembert', 'Crotin du Chavignol']
28
+ }
29
+ }
30
+
31
+ groceries.vino.red #=> "Syrah"
32
+ ```
33
+
34
+ ## Hash Example
35
+ ```ruby
36
+ groceries = FrenchMan::Grocery.plan :vino => { :red => "Syrah", :white => "Cabernet Sauvignon"}
37
+
38
+ groceries.vino.red #=> "Syrah"
39
+ ```
@@ -14,6 +14,9 @@ Gem::Specification.new do |s|
14
14
  s.rubyforge_project = "french_man"
15
15
 
16
16
  s.add_development_dependency "rspec", "2.5.0"
17
+ s.add_development_dependency "rake"
18
+ s.add_development_dependency "ruby-debug"
19
+ s.add_development_dependency "json"
17
20
 
18
21
  s.files = `git ls-files`.split("\n")
19
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -17,7 +17,7 @@
17
17
  # login.password
18
18
  # => 'baguette'
19
19
  class FrenchMan
20
- VERSION = "0.0.2"
20
+ VERSION = "0.0.3"
21
21
 
22
22
  def self.const_missing(name) #:nodoc:
23
23
  clazz = Class.new do
@@ -26,19 +26,39 @@ class FrenchMan
26
26
  send(:class_variable_set, :@@blueprint, blueprint)
27
27
  end
28
28
 
29
- def self.plan(&block)
29
+ def self.plan(hash = nil, &block)
30
30
  blueprint = send(:class_variable_get, :@@blueprint)
31
31
  raise "blueprint is missing" if blueprint.nil?
32
- plan = Plan.new &block
32
+ plan = hash.nil? ? Plan.new(&block) : HashBuild.new(hash)
33
33
  blueprint.merge plan.hash
34
34
  end
35
35
  end
36
36
  self.const_set name, clazz
37
37
  end
38
38
 
39
+ class HashBuild
40
+ def initialize(hash)
41
+ @hash = hash || {}
42
+ end
43
+
44
+ def hash
45
+ result = {}
46
+ @hash.each_pair do |key, value|
47
+ key_string = key.to_s.capitalize
48
+ if FrenchMan.const_defined? key_string
49
+ blueprint = FrenchMan.const_get key_string
50
+ result.merge! key => blueprint.plan(value)
51
+ else
52
+ result.merge! key => value
53
+ end
54
+ end
55
+ ObjectifiedHash.new result
56
+ end
57
+ end
58
+
39
59
  # Creates a new plan hash for merging with a blueprint
40
60
  class Plan
41
- undef_method :id
61
+ undef_method :id if method_defined?(:id)
42
62
 
43
63
  attr_reader :hash
44
64
 
@@ -54,7 +74,8 @@ class FrenchMan
54
74
 
55
75
  # The blueprint to create hashes from
56
76
  class Blueprint
57
- undef_method :id, :type
77
+ undef_method :id if method_defined?(:id)
78
+ undef_method :type if method_defined?(:type)
58
79
 
59
80
  def initialize(&block) #:nodoc:
60
81
  @hash = {}
@@ -77,17 +98,33 @@ class FrenchMan
77
98
  end
78
99
  end
79
100
 
80
- # Wraper for plan hashes so dot syntax can be used
81
101
  class ObjectifiedHash
82
- undef_method :==, :===, :=~, :id
102
+ undef_method :id if method_defined?(:id)
103
+ undef_method :==, :===, :=~
83
104
 
84
105
  def initialize(attributes = {}) #:nodoc:
85
106
  @attributes = attributes
86
107
  end
87
108
 
109
+ def to_hash
110
+ hash = {}
111
+ @attributes.each do |key, val|
112
+ if val.is_a? Array
113
+ hash[key] = val.map { |elmt| (elmt.respond_to? 'to_hash') ? elmt.to_hash : elmt }
114
+ else
115
+ hash[key] = (val.respond_to? 'to_hash') ? val.to_hash : val
116
+ end
117
+ end
118
+ hash
119
+ end
120
+
121
+ def to_json(options={}) # by default Object.to_json return 'attributes' root key
122
+ to_hash.to_json(options)
123
+ end
124
+
88
125
  def method_missing(name, *args) #:nodoc:
89
126
  if @attributes.has_key? name
90
- value = @attributes[name]
127
+ value = name.is_a?(Hash) ? self.class.new(@attributes[name]) : @attributes[name]
91
128
  else
92
129
  @attributes.send name, *args
93
130
  end
@@ -50,28 +50,49 @@ describe FrenchMan do
50
50
  }
51
51
  end
52
52
 
53
- it "should build a hash using a dsl" do
54
- build = FrenchMan::Login.plan {
55
- groceries {
56
- FrenchMan::Grocery.plan {
57
- vino { FrenchMan::Vino.plan }
58
- other_items {
59
- [
60
- FrenchMan::OtherItem.plan,
61
- FrenchMan::OtherItem.plan {
62
- name { 'two' }
63
- num { 2 }
64
- }
65
- ]
53
+ describe "working with a few level of nesting" do
54
+
55
+ let(:build) {
56
+ FrenchMan::Login.plan {
57
+ groceries {
58
+ FrenchMan::Grocery.plan {
59
+ vino { FrenchMan::Vino.plan }
60
+ other_items {
61
+ [
62
+ FrenchMan::OtherItem.plan,
63
+ FrenchMan::OtherItem.plan {
64
+ name { 'two' }
65
+ num { 2 }
66
+ }
67
+ ]
68
+ }
66
69
  }
67
70
  }
68
71
  }
69
72
  }
70
- build.should == resulting_blueprint
73
+
74
+ it "should build a hash using a dsl" do
75
+ build.should == resulting_blueprint
76
+ end
77
+
78
+ it "should be able to return a proper hash (without showing the 'attributes' root element)" do
79
+ build.to_hash.should == resulting_blueprint
80
+ end
81
+
82
+ it "should be able to produce the same json as a standard hash (if available)" do
83
+ require 'json'
84
+ build.to_json.should == resulting_blueprint.to_json
85
+ end
86
+
71
87
  end
72
88
 
73
- it "should return objectified hash objects" do
74
- build = FrenchMan::Login.plan {
89
+ it "should handle type in object" do
90
+ test_type = FrenchMan::TestType.plan
91
+ test_type[:type].should == 'test'
92
+ end
93
+
94
+ let(:shopping) {
95
+ FrenchMan::Login.plan {
75
96
  groceries {
76
97
  FrenchMan::Grocery.plan {
77
98
  vino {
@@ -86,12 +107,27 @@ describe FrenchMan do
86
107
  }
87
108
  }
88
109
  }
89
- build.groceries.vino.red.should == "Syrah"
90
- build.groceries.cheeses.should == ['Camembert', 'Crotin du Chavignol']
110
+ }
111
+
112
+ it "should return objectified hash objects" do
113
+ shopping.groceries.vino.red.should == "Syrah"
114
+ shopping[:groceries][:vino][:red].should == "Syrah"
91
115
  end
92
116
 
93
- it "should handle type in object" do
117
+ it "should return objectified hash objects" do
118
+ shopping.groceries.cheeses.should == ['Camembert', 'Crotin du Chavignol']
119
+ shopping[:groceries][:cheeses].should == ['Camembert', 'Crotin du Chavignol']
120
+ end
121
+
122
+ it "should be able to use hash syntax for plan" do
123
+ hash = FrenchMan::Login.plan :grocery => { :vino => { :red => "Syrah", :white => "Cabernet Sauvignon"} }
124
+ hash.grocery.vino.red.should == "Syrah"
125
+ hash[:grocery][:vino][:red].should == "Syrah"
126
+ end
127
+
128
+ it "should handle type in object for <= ruby 1.8.7" do
94
129
  test_type = FrenchMan::TestType.plan
95
130
  test_type[:type].should == 'test'
96
131
  end
132
+
97
133
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: french_man
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Rufus Post
@@ -16,8 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-05-16 00:00:00 +10:00
20
- default_executable:
19
+ date: 2012-10-03 00:00:00 Z
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
23
22
  name: rspec
@@ -35,6 +34,48 @@ dependencies:
35
34
  version: 2.5.0
36
35
  type: :development
37
36
  version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: ruby-debug
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: json
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
38
79
  description:
39
80
  email:
40
81
  - rufuspost@gmail.com
@@ -49,12 +90,12 @@ files:
49
90
  - .rspec
50
91
  - Gemfile
51
92
  - LICENSE
93
+ - README.md
52
94
  - Rakefile
53
95
  - french_man.gemspec
54
96
  - lib/french_man.rb
55
97
  - spec/french_man_spec.rb
56
98
  - spec/spec_helper.rb
57
- has_rdoc: true
58
99
  homepage: ""
59
100
  licenses: []
60
101
 
@@ -84,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
125
  requirements: []
85
126
 
86
127
  rubyforge_project: french_man
87
- rubygems_version: 1.6.2
128
+ rubygems_version: 1.8.24
88
129
  signing_key:
89
130
  specification_version: 3
90
131
  summary: machinist but just for hashes and arrays