noe 1.0.0 → 1.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 +27 -0
- data/Gemfile +2 -0
- data/LICENCE.md +22 -0
- data/README.md +111 -45
- data/Rakefile +18 -20
- data/bin/noe +1 -1
- data/lib/noe.rb +7 -21
- data/lib/noe/commons.rb +23 -0
- data/lib/noe/config.yaml +2 -2
- data/lib/noe/ext/array.rb +18 -0
- data/lib/noe/ext/hash.rb +48 -0
- data/lib/noe/go.rb +158 -40
- data/lib/noe/install.rb +13 -7
- data/lib/noe/list.rb +34 -10
- data/lib/noe/loader.rb +67 -0
- data/lib/noe/main.rb +15 -15
- data/lib/noe/prepare.rb +121 -0
- data/lib/noe/show_spec.rb +45 -0
- data/lib/noe/template.rb +84 -4
- data/noe.gemspec +186 -30
- data/spec/ext/hash/methodize_spec.rb +30 -0
- data/spec/noe_spec.rb +4 -0
- data/spec/spec_helper.rb +0 -2
- data/spec/template/entry/infer_wlang_dialect_spec.rb +31 -0
- data/tasks/gem.rake +44 -0
- data/tasks/spec_test.rake +61 -0
- data/tasks/unit_test.rake +56 -0
- data/tasks/yard.rake +36 -0
- data/templates/ruby/CHANGELOG.md +9 -1
- data/templates/ruby/README.md +47 -10
- data/templates/ruby/noespec.yaml +195 -26
- data/templates/ruby/short.yaml +33 -0
- data/templates/ruby/src/Gemfile +2 -0
- data/templates/ruby/src/LICENCE.md +22 -0
- data/templates/ruby/src/Manifest.txt +11 -0
- data/templates/ruby/src/README.md +6 -1
- data/templates/ruby/src/Rakefile +16 -36
- data/templates/ruby/src/__lower__.gemspec +178 -23
- data/templates/ruby/src/lib/__lower__.rb +5 -2
- data/templates/ruby/src/lib/__lower__/loader.rb +65 -0
- data/templates/ruby/src/spec/spec_helper.rb +0 -2
- data/templates/ruby/src/tasks/gem.rake +44 -0
- data/templates/ruby/src/tasks/spec_test.rake +61 -0
- data/templates/ruby/src/tasks/unit_test.rake +56 -0
- data/templates/ruby/src/tasks/yard.rake +36 -0
- metadata +349 -79
- data/LICENCE.txt +0 -20
- data/lib/noe/create.rb +0 -77
- data/templates/ruby/src/LICENCE.txt +0 -20
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
# 1.1.0 / FIX ME
|
2
|
+
|
3
|
+
* Template specification/instantiation enhancements
|
4
|
+
|
5
|
+
* Introduced a manifest entry in template-info
|
6
|
+
* Introduced an auto detection of the wlang dialect to use based on file extensions.
|
7
|
+
The dialect may also be specified under template-info/manifest/a_file_name/wlang-dialect
|
8
|
+
entry
|
9
|
+
* All hashes found in .noespec variables are methodized before being passed to template
|
10
|
+
* Templates are now instantiated on a specification being the result of YAML merging
|
11
|
+
between the user's .noespec file and the template noespec.yaml file.
|
12
|
+
|
13
|
+
* Command enhancements
|
14
|
+
|
15
|
+
* Removed 'noe create', which is replaced by an extended version named 'noe prepare'
|
16
|
+
* 'noe go' now supports --interactive and --safe-override additional options to control conflict strategy
|
17
|
+
* Added a 'noe show-spec' command that shows the complete specification used by 'noe go'
|
18
|
+
See 'noe help show-spec' for details
|
19
|
+
* 'noe COMMAND --help' is now an alias for 'noe help COMMAND'
|
20
|
+
* A wlang backtrace is now displayed when an instantation error occurs on 'noe go'
|
21
|
+
|
22
|
+
* Other changes
|
23
|
+
|
24
|
+
* Bumped wlang version to 0.10.0 to gain inclusion features on wlang/ruby and wlang/yaml
|
25
|
+
* Ruby skeleton largely enhanced (see it's own CHANGELOG.md)
|
26
|
+
* Noe code is now managed by Noe itself
|
27
|
+
|
1
28
|
# 1.0.0 / 2011-01-10
|
2
29
|
|
3
30
|
* Enhancements
|
data/Gemfile
ADDED
data/LICENCE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Licence
|
2
|
+
|
3
|
+
Copyright (c) 2011 - Bernard Lambeau
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,23 +1,14 @@
|
|
1
1
|
# Noe - A simple and extensible project generator
|
2
2
|
|
3
|
-
Noe
|
3
|
+
Noe is a tool that generates projects from predefined skeletons (aka project/application
|
4
|
+
templates). Skeletons are designed for building specific products (a ruby library, a static
|
5
|
+
or dynamic web site, ...). Noe instantiates them and helps you maintaining your product
|
6
|
+
via meta-information provided by a .noespec yaml file.
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
and I'll add them below:
|
10
|
-
|
11
|
-
See also:
|
12
|
-
|
13
|
-
* ...
|
14
|
-
|
15
|
-
Other reasons:
|
16
|
-
|
17
|
-
* Noe is agnostic: it does not make any assumption about project semantics
|
18
|
-
* Noe does not restrict itself to generation of ruby projects
|
19
|
-
* Noe is not required at runtime: once your project is generated you're done
|
20
|
-
* I don't like magic
|
8
|
+
Noe comes bundled with a skeleton for creating and maintaining a ruby gem. This skeleton
|
9
|
+
is written and maintained to follow ruby best practices and may also be tuned for your own
|
10
|
+
needs. Read more about it and related projects as well as the underlying philosophy in the
|
11
|
+
sections below.
|
21
12
|
|
22
13
|
## Getting started
|
23
14
|
|
@@ -26,19 +17,11 @@ Other reasons:
|
|
26
17
|
[noe help install]
|
27
18
|
noe install
|
28
19
|
|
29
|
-
Have a loot at ~/.noerc and ~/.noe for configuration and a default ruby
|
30
|
-
|
31
|
-
|
32
|
-
## Usage summary
|
20
|
+
Have a loot at ~/.noerc and ~/.noe for configuration and a default ruby template. To
|
21
|
+
instantiate a ruby project simply execute the following commands in turn:
|
33
22
|
|
34
|
-
|
35
|
-
|
36
|
-
specific needs.
|
37
|
-
|
38
|
-
To create a fresh new project:
|
39
|
-
|
40
|
-
# Given a template xxx under ~/.noe/xxx
|
41
|
-
noe create --template=xxx foo
|
23
|
+
# Given a template ruby under ~/.noe/ruby, install by default
|
24
|
+
noe prepare --template=ruby foo
|
42
25
|
cd foo
|
43
26
|
|
44
27
|
# Edit the template configuration foo/foo.noespec
|
@@ -47,10 +30,92 @@ To create a fresh new project:
|
|
47
30
|
# Launch template instantiation
|
48
31
|
noe go
|
49
32
|
|
50
|
-
That's it! But also have a look at 'noe help
|
33
|
+
That's it! But also have a look at 'noe help prepare' and 'not help go' for additional
|
51
34
|
options.
|
52
35
|
|
53
|
-
##
|
36
|
+
## Philosophy
|
37
|
+
|
38
|
+
Noe is designed to follow a certain number of good principles and helps you following
|
39
|
+
them as well.
|
40
|
+
|
41
|
+
### Separation of concerns
|
42
|
+
|
43
|
+
Noe maintains a strong separation of concerns. In particular one has to make the distinction
|
44
|
+
between a) Noe itself, b) a skeleton and c) an instantiated product. This fact has two
|
45
|
+
main consequences:
|
46
|
+
|
47
|
+
* Noe itself **is not dedicated to specific products** (like a ruby library). Even if Noe
|
48
|
+
comes bundled with a default skeleton for ruby projects, writing skeletons for something
|
49
|
+
else should not be a problem. In other words, Noe itself is agnostic: the semantics of
|
50
|
+
generated products is the secret of the skeleton, under the responsibility of it's
|
51
|
+
maintainer.
|
52
|
+
|
53
|
+
* Noe **should not be a runtime dependency** of the product. Good skeletons maintain this
|
54
|
+
separation. As an example the default ruby skeleton is strictly independent of Noe itself.
|
55
|
+
Principles discussed below explain why this is important.
|
56
|
+
|
57
|
+
### Master the tools YOU use
|
58
|
+
|
59
|
+
The separation of concerns described previously also drives what you have to learn and what
|
60
|
+
tools you have to master:
|
61
|
+
|
62
|
+
* As an ordinary Noe user (vs. skeleton maintainer) and because Noe itself (unlike skeletons
|
63
|
+
is project agnostic, you only have to know **basic Noe commands** (see 'noe --help') and
|
64
|
+
should never have to study Noe's API and internals. In contrast, you have to **master the
|
65
|
+
tools and best practices of your product's ecosystem**. A good skeleton should help you
|
66
|
+
along this task. As an example, the default ruby skeleton is fully documented to help you
|
67
|
+
gaining understanding of ***rake*, *spec*, *yard*, *bundler*** and so on but **not noe
|
68
|
+
itself**.
|
69
|
+
|
70
|
+
* This explains why Noe itself is not a runtime dependency. Using a particular skeleton
|
71
|
+
already means learning a lot, at least in the long run (see the section about Magic below).
|
72
|
+
Noe avoids interfering with generated products to avoid making the learning curve even
|
73
|
+
worse.
|
74
|
+
|
75
|
+
* Being a skeleton creator/maintainer is another story of course. To write a skeleton you'll
|
76
|
+
also have to learn **Noe's API and internals**. To write a good/reusable one, you'll
|
77
|
+
certainly have to **master the full ecosystem and best practices of the targetted product**,
|
78
|
+
which is a good opportunity for learning and sharing it!
|
79
|
+
|
80
|
+
### Magic Only If Flexible
|
81
|
+
|
82
|
+
"Don't Repeat Yourself" and "Convention over Configuration" are certainly good principles.
|
83
|
+
However tuning, configuration and options exist, are useful and should certainly not be
|
84
|
+
hidden to the user. Instead configuration and options should come with default values,
|
85
|
+
and should be fully documented. Providing magic is great if there is a user-centric way
|
86
|
+
(in contrast to a developer one) of understanding and controlling the magic and underlying
|
87
|
+
assumptions.
|
88
|
+
|
89
|
+
As an example, the default ruby template comes with some magic: you can create a project
|
90
|
+
and immediately invoke 'rake test', 'rake yard', ... and not investigating further. You
|
91
|
+
can also have a look at the _tasks_ folder to understand and control the rake tasks that
|
92
|
+
your project will use... In fact, you **must** investigate: the generated product is yours,
|
93
|
+
not mine and YOU have to master your build chain!
|
94
|
+
|
95
|
+
## Ruby skeleton and Related projects
|
96
|
+
|
97
|
+
Noe is inspired by existing projects, mostly from the ruby community. In particular, the
|
98
|
+
default ruby template has been heavily influenced by the projects below as well as feedback
|
99
|
+
of their authors:
|
100
|
+
|
101
|
+
* [hoe](http://seattlerb.rubyforge.org/hoe/), Ryan Davis and Eric Hodel
|
102
|
+
* [echoe](https://github.com/fauna/echoe), Evan Weaver
|
103
|
+
* [bones](https://github.com/TwP/bones), Tim Pease
|
104
|
+
|
105
|
+
These projects help you generating and maintaining ruby projects (generally gem libraries,
|
106
|
+
in fact). All provide powerful tools that supports you along the different steps of your
|
107
|
+
ruby software lifecycle (creating, testing, releasing, announcing, and so on.). They mostly
|
108
|
+
differ in the way you can tune/configure the generated project for specific needs.
|
109
|
+
|
110
|
+
These projects differ from the Ruby skeleton proposed by Noe in that they use a control
|
111
|
+
approach (rake tasks installed in your project via a development/runtime dependency) while
|
112
|
+
Noe uses a generative approach (the generated ruby project and rake tasks do not depend on
|
113
|
+
Noe at all).
|
114
|
+
|
115
|
+
You'll find more information about the Noe's ruby skeleton in it's own
|
116
|
+
[README](https://github.com/blambeau/noe/blob/master/templates/ruby/README.md).
|
117
|
+
|
118
|
+
## Short guide for template maintainers
|
54
119
|
|
55
120
|
Under ~/.noe, a valid template folder (say xxx) has the following structure
|
56
121
|
|
@@ -63,16 +128,17 @@ Under ~/.noe, a valid template folder (say xxx) has the following structure
|
|
63
128
|
|
64
129
|
### noespec.yaml
|
65
130
|
|
66
|
-
The noespec.yaml file of a template is used to formally describe the template. When a
|
67
|
-
(say foo) is created (see 'noe
|
68
|
-
~/.noe/ruby/noespec.yaml is used to generate foo/foo.noespec. The later is then used
|
69
|
-
'noe go' to instantiate the project.
|
131
|
+
The noespec.yaml file of a template is used to formally describe the template. When a
|
132
|
+
project (say foo) is created (see 'noe prepare') using a template (say ruby) the file
|
133
|
+
~/.noe/ruby/noespec.yaml is used to generate foo/foo.noespec. The later is then used
|
134
|
+
by 'noe go' to instantiate the project.
|
70
135
|
|
71
136
|
The noespec.yaml file should ressemble something like this:
|
72
137
|
|
73
138
|
# DO NOT TOUCH 'name' entry and specify the other
|
74
139
|
template-info:
|
75
140
|
name: !{template_name}
|
141
|
+
summary: ...
|
76
142
|
description: ...
|
77
143
|
version: ...
|
78
144
|
author: ...
|
@@ -90,16 +156,16 @@ Have a look at ~/.noe/ruby/noespec.yaml and ~/.noe/ruby/src for an example.
|
|
90
156
|
|
91
157
|
### Instantiation process
|
92
158
|
|
93
|
-
The instantiation process is really simple. Given the variables described in the
|
94
|
-
file (for which values are specified in your .noespec file) templates
|
95
|
-
meta-constructions:
|
159
|
+
The instantiation process is really simple. Given the variables described in the
|
160
|
+
noespec.yaml file (for which values are specified in your .noespec file) templates
|
161
|
+
can use the following meta-constructions:
|
96
162
|
|
97
|
-
* Template files and directories containing `__variable__` in their name are automatically
|
163
|
+
* Template files and directories containing `__variable__` in their name are automatically
|
98
164
|
renamed (`__variable__` is replaced by the corresponding value).
|
99
|
-
* All template files are instantiated by [wlang](https://github.com/blambeau/wlang). You
|
100
|
-
have to know wlang in depth. You simply have to know that `!{ruby_expression}` in
|
101
|
-
replaced by the expression evaluation. Variables are automatically in scope
|
102
|
-
so that `!{variable}` is replaced by its value.
|
165
|
+
* All template files are instantiated by [wlang](https://github.com/blambeau/wlang). You
|
166
|
+
don't have to know wlang in depth. You simply have to know that `!{ruby_expression}` in
|
167
|
+
a file is replaced by the expression evaluation. Variables are automatically in scope
|
168
|
+
of such expressions, so that `!{variable}` is replaced by its value.
|
103
169
|
|
104
170
|
## Contributing
|
105
171
|
|
@@ -111,7 +177,7 @@ Fork Noe on github! I'm particularly interested in the following enhancements:
|
|
111
177
|
* Add support for multi-generated files from arrays in .noespec files
|
112
178
|
* ...
|
113
179
|
|
114
|
-
If you think that your template is worth considering for (ruby, rails, js, latex, or
|
115
|
-
else) please let me known and I'll add it to the list below.
|
180
|
+
If you think that your template is worth considering for (ruby, rails, js, latex, or
|
181
|
+
anything else) please let me known and I'll add it to the list below.
|
116
182
|
|
117
183
|
* ...
|
data/Rakefile
CHANGED
@@ -1,24 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "
|
4
|
-
|
5
|
-
|
6
|
-
task :default => :spec
|
7
|
-
|
8
|
-
desc "Run all examples"
|
9
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
10
|
-
t.rspec_opts = %w[--color]
|
11
|
-
t.verbose = false
|
1
|
+
begin
|
2
|
+
gem "bundler", "~> 1.0"
|
3
|
+
require "bundler/setup"
|
4
|
+
rescue LoadError
|
5
|
+
abort "This project requires bundler, try 'gem install bundler'"
|
12
6
|
end
|
13
7
|
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
# Dynamically load the gem spec
|
9
|
+
$gemspec_file = File.expand_path('../noe.gemspec', __FILE__)
|
10
|
+
$gemspec = Kernel.eval(File.read($gemspec_file))
|
11
|
+
|
12
|
+
# We run tests by default
|
13
|
+
task :default => :test
|
19
14
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
#
|
16
|
+
# Install all tasks found in tasks folder
|
17
|
+
#
|
18
|
+
# See .rake files there for complete documentation.
|
19
|
+
#
|
20
|
+
Dir["tasks/*.rake"].each do |taskfile|
|
21
|
+
instance_eval File.read(taskfile), taskfile
|
24
22
|
end
|
data/bin/noe
CHANGED
data/lib/noe.rb
CHANGED
@@ -1,39 +1,25 @@
|
|
1
1
|
module Noe
|
2
2
|
|
3
3
|
# Noe's version
|
4
|
-
VERSION = "1.
|
5
|
-
|
6
|
-
# Requires some gem
|
7
|
-
def self.require(gem_name, version = nil, retried = false)
|
8
|
-
begin
|
9
|
-
Kernel.require gem_name
|
10
|
-
rescue LoadError
|
11
|
-
if retried
|
12
|
-
raise
|
13
|
-
else
|
14
|
-
retried = true
|
15
|
-
require 'rubygems'
|
16
|
-
gem gem_name, version
|
17
|
-
retry
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
4
|
+
VERSION = "1.1.0".freeze
|
21
5
|
|
22
6
|
class Error < StandardError; end
|
23
7
|
|
24
8
|
end # module Noe
|
25
|
-
|
26
|
-
Noe.require('quickl', ">= 0.2.0")
|
27
|
-
Noe.require('wlang', ">= 0.9")
|
9
|
+
require 'noe/loader'
|
28
10
|
require 'yaml'
|
29
11
|
require 'fileutils'
|
12
|
+
require 'noe/ext/array'
|
13
|
+
require 'noe/ext/hash'
|
30
14
|
require 'noe/config'
|
31
15
|
require 'noe/template'
|
16
|
+
|
32
17
|
require 'noe/main'
|
33
18
|
require 'noe/commons'
|
34
19
|
require 'noe/install'
|
35
20
|
require 'noe/help'
|
36
21
|
require 'noe/list'
|
37
|
-
require 'noe/
|
22
|
+
require 'noe/prepare'
|
38
23
|
require 'noe/go'
|
24
|
+
require 'noe/show_spec'
|
39
25
|
|
data/lib/noe/commons.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
module Noe
|
2
2
|
module Commons
|
3
3
|
|
4
|
+
# Install options
|
5
|
+
def self.add_common_options(opt)
|
6
|
+
opt.on_tail("--version", "Show version") do
|
7
|
+
raise Quickl::Exit, "#{File.basename($0 || 'noe')} #{Noe::VERSION} (c) 2011, Bernard Lambeau"
|
8
|
+
end
|
9
|
+
opt.on_tail('--help', "Show detailed help") do
|
10
|
+
raise Quickl::Help
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
# Returns configuration to use
|
5
15
|
def config
|
6
16
|
requester.config
|
@@ -13,6 +23,19 @@ module Noe
|
|
13
23
|
def template(name = config.default)
|
14
24
|
Template.new(File.join(templates_dir, name))
|
15
25
|
end
|
26
|
+
|
27
|
+
def find_noespec_file(args)
|
28
|
+
# Find spec file
|
29
|
+
spec_file = if args.size == 1
|
30
|
+
valid_read_file!(args.first)
|
31
|
+
else
|
32
|
+
spec_files = Dir['*.noespec']
|
33
|
+
if spec_files.size > 1
|
34
|
+
raise Noe::Error, "Ambiguous request, multiple specs: #{spec_files.join(', ')}"
|
35
|
+
end
|
36
|
+
spec_files.first
|
37
|
+
end
|
38
|
+
end
|
16
39
|
|
17
40
|
end # module Commons
|
18
41
|
end # module Noe
|
data/lib/noe/config.yaml
CHANGED
@@ -22,8 +22,8 @@ templates-dir:
|
|
22
22
|
|
23
23
|
#
|
24
24
|
# Name of the default template that you want to use. Commands
|
25
|
-
# that need a template (see 'noe help
|
26
|
-
# by default, and allow overriding
|
25
|
+
# that need a template (see 'noe help prepare', for example) use this
|
26
|
+
# by default, and allow overriding it via a --template=NAME option.
|
27
27
|
#
|
28
28
|
default:
|
29
29
|
ruby
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
def methodize_hashes!(recursive = true)
|
4
|
+
self.each do |val|
|
5
|
+
case val
|
6
|
+
when Hash
|
7
|
+
val.methodize!(recursive)
|
8
|
+
when Array
|
9
|
+
val.methodize_hashes!(recursive)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def noe_merge(right)
|
15
|
+
(self + right).uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class Array
|
data/lib/noe/ext/hash.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Methodize this hash
|
4
|
+
def methodize!(recursive = true)
|
5
|
+
self.extend(Methodize)
|
6
|
+
if recursive
|
7
|
+
self.values.each do |val|
|
8
|
+
case val
|
9
|
+
when Hash
|
10
|
+
val.methodize!(recursive)
|
11
|
+
when Array
|
12
|
+
val.methodize_hashes!(recursive)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Makes a fully recursive merge
|
19
|
+
def noe_merge(right)
|
20
|
+
self.merge(right) do |key,oldval,newval|
|
21
|
+
if oldval.nil?
|
22
|
+
newval
|
23
|
+
elsif oldval.class != newval.class
|
24
|
+
raise Noe::Error, "Conflict on #{key} has to be resolved manually, sorry.\n"\
|
25
|
+
"#{oldval} (#{oldval.class}) vs. #{newval} (#{newval.class})"
|
26
|
+
elsif oldval.respond_to?(:noe_merge)
|
27
|
+
oldval.noe_merge(newval)
|
28
|
+
else
|
29
|
+
newval
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module Methodize
|
35
|
+
|
36
|
+
# Allows using hash.key as a synonym for hash[:key] and
|
37
|
+
# hash['key']
|
38
|
+
def method_missing(name, *args, &block)
|
39
|
+
if args.empty? and block.nil?
|
40
|
+
self[name] || self[name.to_s]
|
41
|
+
else
|
42
|
+
super(name, *args, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|