french_man 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in french_man.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011, FrontFoot Media Solutions
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "french_man"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "french_man"
7
+ s.version = FrenchMan::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rufus Post", "Jeremy Grant"]
10
+ s.email = ["rufuspost@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{machinist but just for hashes and arrays}
13
+
14
+ s.rubyforge_project = "french_man"
15
+
16
+ s.add_development_dependency "rspec", "2.5.0"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
data/lib/french_man.rb ADDED
@@ -0,0 +1,96 @@
1
+ # Constructs blueprints and assembles plans and has long holidays
2
+ #
3
+ # Example usage:
4
+ # FrenchMan::Login.blueprint {
5
+ # username { Faker.name }
6
+ # password { 'baguette' }
7
+ # }
8
+ #
9
+ #
10
+ # login = FrenchMan::Login.plan {
11
+ # username { 'francois' }
12
+ # }
13
+ #
14
+ # login.username
15
+ # => 'francois'
16
+ #
17
+ # login.password
18
+ # => 'baguette'
19
+ class FrenchMan
20
+ VERSION = "0.0.2"
21
+
22
+ def self.const_missing(name) #:nodoc:
23
+ clazz = Class.new do
24
+ def self.blueprint(&block)
25
+ blueprint = Blueprint.new &block
26
+ send(:class_variable_set, :@@blueprint, blueprint)
27
+ end
28
+
29
+ def self.plan(&block)
30
+ blueprint = send(:class_variable_get, :@@blueprint)
31
+ raise "blueprint is missing" if blueprint.nil?
32
+ plan = Plan.new &block
33
+ blueprint.merge plan.hash
34
+ end
35
+ end
36
+ self.const_set name, clazz
37
+ end
38
+
39
+ # Creates a new plan hash for merging with a blueprint
40
+ class Plan
41
+ undef_method :id
42
+
43
+ attr_reader :hash
44
+
45
+ def initialize(&block) #:nodoc:
46
+ @hash = {}
47
+ instance_eval &block unless block.nil?
48
+ end
49
+
50
+ def method_missing(attribute, &block) #:nodoc:
51
+ @hash.merge!(attribute => block.call)
52
+ end
53
+ end
54
+
55
+ # The blueprint to create hashes from
56
+ class Blueprint
57
+ undef_method :id, :type
58
+
59
+ def initialize(&block) #:nodoc:
60
+ @hash = {}
61
+ instance_eval &block
62
+ end
63
+
64
+ # takes a hash as an argument and merges it with a the blueprint
65
+ # hash and returns the hash wrapped in an +ObjectifiedHash+ object
66
+ def merge(plan)
67
+ attribute_names = @hash.keys - plan.keys
68
+ attribute_names.each do |attribute_name|
69
+ value = @hash[attribute_name]
70
+ plan[attribute_name] = value.respond_to?(:call) ? value.call : value
71
+ end
72
+ ObjectifiedHash.new plan
73
+ end
74
+
75
+ def method_missing(attribute, &block) #:nodoc:
76
+ @hash.merge!(attribute => block)
77
+ end
78
+ end
79
+
80
+ # Wraper for plan hashes so dot syntax can be used
81
+ class ObjectifiedHash
82
+ undef_method :==, :===, :=~, :id
83
+
84
+ def initialize(attributes = {}) #:nodoc:
85
+ @attributes = attributes
86
+ end
87
+
88
+ def method_missing(name, *args) #:nodoc:
89
+ if @attributes.has_key? name
90
+ value = @attributes[name]
91
+ else
92
+ @attributes.send name, *args
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe FrenchMan do
4
+ let(:resulting_blueprint) {
5
+ {
6
+ :username => 'francois',
7
+ :password => 'baguette',
8
+ :groceries => {
9
+ :garlic => true,
10
+ :vino => {
11
+ :red => 'tempranillo',
12
+ :white => 'sav'
13
+ },
14
+ :other_items => [
15
+ {
16
+ :name => 'one',
17
+ :num => 1
18
+ },
19
+ {
20
+ :name => 'two',
21
+ :num => 2
22
+ }
23
+ ]
24
+ }
25
+ }
26
+ }
27
+
28
+ before do
29
+ FrenchMan::Login.blueprint {
30
+ username { 'francois' }
31
+ password { 'baguette' }
32
+ }
33
+
34
+ FrenchMan::Grocery.blueprint {
35
+ garlic { true }
36
+ }
37
+
38
+ FrenchMan::Vino.blueprint {
39
+ red { 'tempranillo' }
40
+ white { 'sav' }
41
+ }
42
+
43
+ FrenchMan::OtherItem.blueprint {
44
+ name { 'one' }
45
+ num { 1 }
46
+ }
47
+
48
+ FrenchMan::TestType.blueprint {
49
+ type { 'test' }
50
+ }
51
+ end
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
+ ]
66
+ }
67
+ }
68
+ }
69
+ }
70
+ build.should == resulting_blueprint
71
+ end
72
+
73
+ it "should return objectified hash objects" do
74
+ build = FrenchMan::Login.plan {
75
+ groceries {
76
+ FrenchMan::Grocery.plan {
77
+ vino {
78
+ FrenchMan::Vino.plan {
79
+ red { "Syrah" }
80
+ white { "Cabernet Sauvignon" }
81
+ }
82
+ }
83
+ cheeses {
84
+ ['Camembert', 'Crotin du Chavignol']
85
+ }
86
+ }
87
+ }
88
+ }
89
+ build.groceries.vino.red.should == "Syrah"
90
+ build.groceries.cheeses.should == ['Camembert', 'Crotin du Chavignol']
91
+ end
92
+
93
+ it "should handle type in object" do
94
+ test_type = FrenchMan::TestType.plan
95
+ test_type[:type].should == 'test'
96
+ end
97
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'french_man'
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: french_man
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Rufus Post
14
+ - Jeremy Grant
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2012-05-16 00:00:00 +10:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rspec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - "="
29
+ - !ruby/object:Gem::Version
30
+ hash: 27
31
+ segments:
32
+ - 2
33
+ - 5
34
+ - 0
35
+ version: 2.5.0
36
+ type: :development
37
+ version_requirements: *id001
38
+ description:
39
+ email:
40
+ - rufuspost@gmail.com
41
+ executables: []
42
+
43
+ extensions: []
44
+
45
+ extra_rdoc_files: []
46
+
47
+ files:
48
+ - .gitignore
49
+ - .rspec
50
+ - Gemfile
51
+ - LICENSE
52
+ - Rakefile
53
+ - french_man.gemspec
54
+ - lib/french_man.rb
55
+ - spec/french_man_spec.rb
56
+ - spec/spec_helper.rb
57
+ has_rdoc: true
58
+ homepage: ""
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 3
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirements: []
85
+
86
+ rubyforge_project: french_man
87
+ rubygems_version: 1.6.2
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: machinist but just for hashes and arrays
91
+ test_files:
92
+ - spec/french_man_spec.rb
93
+ - spec/spec_helper.rb