french_man 0.0.2 → 0.0.3

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