rake-commander 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.rubocop.yml +74 -0
- data/.yardopts +10 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +6 -0
- data/README.md +28 -0
- data/Rakefile +32 -0
- data/examples/basic.rb +30 -0
- data/lib/rake-commander/base/class_auto_loader.rb +112 -0
- data/lib/rake-commander/base/class_helpers.rb +168 -0
- data/lib/rake-commander/base.rb +29 -0
- data/lib/rake-commander/custom.rb +3 -0
- data/lib/rake-commander/option.rb +153 -0
- data/lib/rake-commander/options/arguments.rb +116 -0
- data/lib/rake-commander/options/error.rb +18 -0
- data/lib/rake-commander/options/error_rely.rb +58 -0
- data/lib/rake-commander/options/name.rb +160 -0
- data/lib/rake-commander/options/set.rb +16 -0
- data/lib/rake-commander/options.rb +171 -0
- data/lib/rake-commander/rake_context/wrapper.rb +39 -0
- data/lib/rake-commander/rake_task.rb +157 -0
- data/lib/rake-commander/version.rb +3 -0
- data/lib/rake-commander.rb +9 -0
- data/rake-commander.gemspec +29 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 79568da769a6523e7024fa641eb8d792b2fd4dfcc600f11f0cbf56e6bb1f45d9
|
4
|
+
data.tar.gz: e8e55e77085b67e37fd9befdb1b0b77cd0f8403ff1c0ab939160c3659c0cd67f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fe77e58170a2e2bed3c9d52202e8deaa039422bda0ded1284f0d8fb316c83a6609fffb6753d2387d573b0ed70c7d5a2c74b5d868e8a89f5ba96dfa2d472b8587
|
7
|
+
data.tar.gz: f75fa6017995dd942cd37cc6494db0a0c9d5273eb28e1b9ef9fe7d909fa39abffc25b6aa681c05ba1dce868b2265fb0bf54f01c55a31fd4298aaf6f70f3b435c
|
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# it's a gem, ignore the lockfile
|
2
|
+
Gemfile.lock
|
3
|
+
|
4
|
+
# build artifacts
|
5
|
+
*.gem
|
6
|
+
/.bundle/
|
7
|
+
/vendor/bundle
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
/pkg/
|
11
|
+
|
12
|
+
# docs
|
13
|
+
/.yardoc
|
14
|
+
/_yardoc/
|
15
|
+
/coverage/
|
16
|
+
/doc/
|
17
|
+
|
18
|
+
# rspec failure tracking
|
19
|
+
.rspec_status
|
20
|
+
scratch.rb
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.7.2
|
3
|
+
Exclude:
|
4
|
+
- 'config/routes.rb'
|
5
|
+
|
6
|
+
Naming/VariableNumber:
|
7
|
+
EnforcedStyle: snake_case
|
8
|
+
Naming/FileName:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Metrics/LineLength:
|
12
|
+
Enabled: false
|
13
|
+
Metrics/BlockLength:
|
14
|
+
ExcludedMethods: [context, describe]
|
15
|
+
Max: 50
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Max: 50
|
18
|
+
Metrics/ClassLength:
|
19
|
+
Max: 200
|
20
|
+
Metrics/AbcSize:
|
21
|
+
Max: 50
|
22
|
+
Metrics/CyclomaticComplexity:
|
23
|
+
Max: 15
|
24
|
+
Metrics/PerceivedComplexity:
|
25
|
+
Max: 15
|
26
|
+
|
27
|
+
ParameterLists:
|
28
|
+
Max: 5
|
29
|
+
CountKeywordArgs: false
|
30
|
+
|
31
|
+
Style/StringLiterals:
|
32
|
+
Enabled: false
|
33
|
+
Style/FrozenStringLiteralComment:
|
34
|
+
Enabled: false
|
35
|
+
Style/CommentedKeyword:
|
36
|
+
Enabled: false
|
37
|
+
Style/MultilineBlockChain:
|
38
|
+
Enabled: false
|
39
|
+
Style/Documentation:
|
40
|
+
Enabled: false
|
41
|
+
Style/StringLiteralsInInterpolation:
|
42
|
+
Enabled: false
|
43
|
+
Style/AndOr:
|
44
|
+
Enabled: false
|
45
|
+
Style/SlicingWithRange:
|
46
|
+
Enabled: false
|
47
|
+
Style/ClassAndModuleChildren:
|
48
|
+
Enabled: false
|
49
|
+
Style/OptionalBooleanParameter:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
Layout/SpaceInsideHashLiteralBraces:
|
53
|
+
Enabled: false
|
54
|
+
Layout/SpaceInsideBlockBraces:
|
55
|
+
Enabled: false
|
56
|
+
Layout/SpaceAroundOperators:
|
57
|
+
Enabled: false
|
58
|
+
Layout/ExtraSpacing:
|
59
|
+
AllowForAlignment: true
|
60
|
+
Layout/AccessModifierIndentation:
|
61
|
+
EnforcedStyle: indent
|
62
|
+
Layout/DotPosition:
|
63
|
+
EnforcedStyle: trailing
|
64
|
+
Layout/MultilineMethodCallIndentation:
|
65
|
+
EnforcedStyle: indented
|
66
|
+
Layout/FirstHashElementIndentation:
|
67
|
+
Enabled: false
|
68
|
+
Layout/EmptyLineAfterGuardClause:
|
69
|
+
Enabled: false
|
70
|
+
Layout/LeadingCommentSpace:
|
71
|
+
Enabled: false
|
72
|
+
|
73
|
+
Lint/AssignmentInCondition:
|
74
|
+
Enabled: false
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
## TO DO
|
5
|
+
- Rake task parameters (see: https://stackoverflow.com/a/825832/4352306)
|
6
|
+
- `OptionParser#parse` result (what to do with unknown ARGV `leftovers`)
|
7
|
+
|
8
|
+
## [0.1.2] - 2023-04-19
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- First commit
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
### Changed
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Ecoportal::API
|
2
|
+
|
3
|
+
Another way to define re-usable rake tasks and samples.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'rake-commander', require: %w[rake-commander]
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rake-commander
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
|
24
|
+
## Development
|
25
|
+
|
26
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
27
|
+
|
28
|
+
For more info on available `Rake` tasks: `rake -T`
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "yard"
|
4
|
+
require "redcarpet"
|
5
|
+
|
6
|
+
desc "run the specs"
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
desc "run rspec showing backtrace"
|
10
|
+
RSpec::Core::RakeTask.new(:spec_trace) do |task|
|
11
|
+
task.rspec_opts = ['--backtrace']
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "run rspec stopping on first fail, and show backtrace"
|
15
|
+
RSpec::Core::RakeTask.new(:spec_fast) do |task|
|
16
|
+
task.rspec_opts = ['--fail-fast', '--backtrace']
|
17
|
+
end
|
18
|
+
|
19
|
+
# default task name is yard
|
20
|
+
desc "Yard: generate all the documentation"
|
21
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
22
|
+
#t.files = ['lib/**/*.rb']
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Examples: Run examples (rake examples[basic] -- -h)"
|
26
|
+
task :examples, [:sample] do |t, args|
|
27
|
+
require_relative "examples/#{args[:sample]}"
|
28
|
+
end
|
29
|
+
|
30
|
+
task default: [:spec]
|
31
|
+
task rspec_trace: :spec_trace
|
32
|
+
task rspec_fast: :spec_fast
|
data/examples/basic.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative File.join(__dir__, '../lib/rake-commander')
|
2
|
+
class RakeCommander::Custom::Basic < RakeCommander
|
3
|
+
namespace :examples
|
4
|
+
|
5
|
+
desc 'A simple example to get started'
|
6
|
+
task :basic
|
7
|
+
|
8
|
+
#banner "Usage: basic:example -- [options]"
|
9
|
+
option '-s', '--say [SOMETHING]', "It says 'something'", default: %q(I don't know what to "say"...)
|
10
|
+
option :d, '--folder NAME', default: '.', desc: 'Source local folder', required: true
|
11
|
+
option '-e', '--enviro ENV', 'The target environment to run this task', required: true
|
12
|
+
option '-t', :show_time, TrueClass, desc: 'Displays the local time'
|
13
|
+
option :v, :debug, TrueClass, 'Shows the parsed options'
|
14
|
+
|
15
|
+
def task(*_args)
|
16
|
+
if options[:v]
|
17
|
+
puts 'We got these options:'
|
18
|
+
pp options
|
19
|
+
end
|
20
|
+
puts Time.now.strftime('%d %b at %H:%M') if options[:t]
|
21
|
+
puts options[:s] if options.key?(:s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
RakeCommander.self_load
|
26
|
+
Rake::Task[:'examples:basic'].invoke
|
27
|
+
# ruby basic.rb -- -v -d /some/folder -t
|
28
|
+
|
29
|
+
#RakeCommander::Custom::Basic.parse_options %w[--help]
|
30
|
+
#RakeCommander::Custom::Basic.parse_options %w[-d]
|
@@ -0,0 +1,112 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Base
|
3
|
+
# Helpers for dynamic object loading based on class declaration
|
4
|
+
# @note
|
5
|
+
# - this helpers aim to boost the usage of the ruby language in complex api configurations.
|
6
|
+
module ClassAutoLoader
|
7
|
+
include RakeCommander::Base::ClassHelpers
|
8
|
+
|
9
|
+
# To enable the class autoloader, you should use this method
|
10
|
+
def autoloads_children_of(klass)
|
11
|
+
class_resolver :autoloader_class, klass
|
12
|
+
@autoloaded_class = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
# Resolves the class `autoloader_class` if it has been defined via `autoloads_children_of`
|
16
|
+
def autoloaded_class
|
17
|
+
return nil unless @autoloaded_class
|
18
|
+
autoloader_class
|
19
|
+
end
|
20
|
+
|
21
|
+
# To which restricted namespaces this class autoloads from
|
22
|
+
def autoloaded_namespaces(type = :include)
|
23
|
+
@autoloaded_namespaces ||= {}
|
24
|
+
@autoloaded_namespaces[type] ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
# To restrict which namespaces it is allowed to load from
|
28
|
+
def autoload_namespace(*namespaces)
|
29
|
+
_autoload_namespace(:include, *namespaces)
|
30
|
+
end
|
31
|
+
|
32
|
+
# To ignore certain namespaces this class should not autoload from
|
33
|
+
def autoload_namespace_ignore(*namespaces)
|
34
|
+
_autoload_namespace(:ignore, *namespaces)
|
35
|
+
end
|
36
|
+
|
37
|
+
def _autoload_namespace(type, *namespaces)
|
38
|
+
autoloaded_namespaces(type).concat(namespaces) unless namespaces.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param constant [Class, String] a class or namespace we want to check auto-load entitlement thereof.
|
42
|
+
# @return [Boolean] determines if a given namespace is entitled for autoloading
|
43
|
+
def autoload_class?(constant)
|
44
|
+
constants = constant.to_s.split("::").compact
|
45
|
+
autoload = true
|
46
|
+
unless autoloaded_namespaces(:include).empty?
|
47
|
+
autoload = autoloaded_namespaces(:include).any? do |ns|
|
48
|
+
ns.to_s.split("::").compact.zip(constants).all? {|(r, c)| r == c}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
unless autoloaded_namespaces(:ignore).empty?
|
52
|
+
autoload &&= autoloaded_namespaces(:ignore).none? do |ns|
|
53
|
+
ns.to_s.split("::").compact.zip(constants).all? {|(r, c)| r == c}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
autoload
|
57
|
+
end
|
58
|
+
|
59
|
+
# As children are loaded as they are declared, we should not load twice same children.
|
60
|
+
def autoloaded_children
|
61
|
+
@autoloaded_children ||= []
|
62
|
+
end
|
63
|
+
|
64
|
+
# Children classes of `autoloader_class` that have not been created an instance of.
|
65
|
+
def unloaded_children
|
66
|
+
return [] unless autoloaded_class
|
67
|
+
new_detected = new_classes
|
68
|
+
known_class!(*new_detected)
|
69
|
+
descendants(parent_class: autoloaded_class, scope: new_detected).select do |child_class|
|
70
|
+
!autoloaded_children.include?(child_class) && autoload_class?(child_class)
|
71
|
+
end.sort
|
72
|
+
end
|
73
|
+
|
74
|
+
# It loads/creates a new instance of children classes pending to be loaded.
|
75
|
+
# @return [Boolean] `true` if there were children loaded, `false` otherwise.
|
76
|
+
def autoload_children(object = nil)
|
77
|
+
return false if !autoloaded_class || @loading_children
|
78
|
+
pending_children = unloaded_children
|
79
|
+
return false if pending_children.empty?
|
80
|
+
@loading_children = true
|
81
|
+
pending_children.each do |klass|
|
82
|
+
child = object ? klass.new(object) : klass.new
|
83
|
+
yield(child) if block_given?
|
84
|
+
|
85
|
+
rescue TypeError
|
86
|
+
# Can't create from this class (must be the singleton class)
|
87
|
+
# Just ignore
|
88
|
+
ensure
|
89
|
+
autoloaded_children.push(klass)
|
90
|
+
end
|
91
|
+
@loading_children = false
|
92
|
+
true
|
93
|
+
end
|
94
|
+
|
95
|
+
# Known namespaces serves the purpose to discover recently added namespaces
|
96
|
+
# provided that the namespace discovery is optimized
|
97
|
+
def known_classes
|
98
|
+
@known_classes ||= []
|
99
|
+
end
|
100
|
+
|
101
|
+
# Add to known namespaces
|
102
|
+
def known_class!(*classes)
|
103
|
+
known_classes.concat(classes)
|
104
|
+
end
|
105
|
+
|
106
|
+
# List all new namespaces
|
107
|
+
def new_classes
|
108
|
+
ObjectSpace.each_object(::Class).to_a - known_classes
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Base
|
3
|
+
module ClassHelpers
|
4
|
+
NOT_USED = 'no_used!'.freeze
|
5
|
+
|
6
|
+
# Helper to determine if a paramter has been used
|
7
|
+
# @note to effectivelly use this helper, you should initialize your target
|
8
|
+
# paramters with the constant `NOT_USED`
|
9
|
+
# @param val [] the value of the paramter
|
10
|
+
# @return [Boolean] `true` if value other than `NOT_USED`, `false` otherwise
|
11
|
+
def used_param?(val)
|
12
|
+
val != NOT_USED
|
13
|
+
end
|
14
|
+
|
15
|
+
# Redefines constant `const` with `value` without triggering a warning.
|
16
|
+
def redef_without_warning(const, value)
|
17
|
+
self.class.send(:remove_const, const) if self.class.const_defined?(const)
|
18
|
+
self.class.const_set(const, value)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Defines a class and instance method for lazy resolving a class.
|
22
|
+
def class_resolver(name, klass)
|
23
|
+
define_singleton_method(name) { resolve_class(klass) }
|
24
|
+
define_method(name) { self.class.resolve_class(klass) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Class resolver
|
28
|
+
# @note it caches the resolved `klass`es
|
29
|
+
# @raise [Exception] when could not resolve if `exception` is `true`
|
30
|
+
# @param klass [Class, String, Symbol] the class to resolve
|
31
|
+
# @param source_class [Class] when the reference to `klass` belongs to a different inheritance chain.
|
32
|
+
# @param exception [Boolean] if it should raise exception when could not resolve
|
33
|
+
# @return [Class] the `Class` constant
|
34
|
+
def resolve_class(klass, source_class: self, exception: true)
|
35
|
+
@resolved ||= {}
|
36
|
+
@resolved[klass] ||=
|
37
|
+
case klass
|
38
|
+
when Class
|
39
|
+
klass
|
40
|
+
when String
|
41
|
+
begin
|
42
|
+
Kernel.const_get(klass)
|
43
|
+
rescue NameError
|
44
|
+
raise if exception
|
45
|
+
end
|
46
|
+
when Symbol
|
47
|
+
source_class.resolve_class(source_class.send(klass))
|
48
|
+
when Hash
|
49
|
+
referrer, referred = klass.first
|
50
|
+
resolve_class(referred, source_class: referrer, exception: exception)
|
51
|
+
else
|
52
|
+
raise "Unknown class: #{klass}" if exception
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Helper to normalize `key` into a correct `ruby` **constant name**
|
57
|
+
# @note it removes namespace syntax `::`
|
58
|
+
# @param key [String, Symbol] to be normalized
|
59
|
+
# @return [String] a correct constant name
|
60
|
+
def to_constant(key)
|
61
|
+
key.to_s.strip.split(/::/).compact.map do |str|
|
62
|
+
str.slice(0).upcase + str.slice(1..-1)
|
63
|
+
end.join("").split(/[-_ :]+/i).compact.map do |str|
|
64
|
+
str.slice(0).upcase + str.slice(1..-1)
|
65
|
+
end.join("")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Helper to create an instance variable `name`
|
69
|
+
# @param [String, Symbol] the name of the variable
|
70
|
+
# @reutrn [String] the name of the created instance variable
|
71
|
+
def instance_variable_name(name)
|
72
|
+
str = name.to_s
|
73
|
+
str = "@#{str}" unless str.start_with?("@")
|
74
|
+
str
|
75
|
+
end
|
76
|
+
|
77
|
+
# If the class for `name` exists, it returns it. Otherwise it generates it.
|
78
|
+
# @param name [String, Symbol] the name of the new class
|
79
|
+
# @param inherits [Class] the parent class to _inherit_ from
|
80
|
+
# @param namespace [Class, String] an existing `constant` (class or module) the new class will be namespaced on
|
81
|
+
# @yield [child_class] configure the new class
|
82
|
+
# @yieldparam child_class [Class] the new class
|
83
|
+
# @return [Class] the new generated class
|
84
|
+
def new_class(name = "Child#{uid}", inherits: self, namespace: inherits)
|
85
|
+
name = name.to_s.to_sym.freeze
|
86
|
+
class_name = to_constant(name)
|
87
|
+
|
88
|
+
unless target_class = resolve_class("#{namespace}::#{class_name}", exception: false)
|
89
|
+
target_class = Class.new(inherits)
|
90
|
+
Kernel.const_get(namespace.to_s).const_set class_name, target_class
|
91
|
+
end
|
92
|
+
|
93
|
+
target_class.tap do |klass|
|
94
|
+
yield(klass) if block_given?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Finds all child classes of the current class.
|
99
|
+
# @param parent_class [Class] the parent class we want to find children of.
|
100
|
+
# @param direct [Boolean] it will only include direct child classes.
|
101
|
+
# @param scope [nil, Array] to only look for descendants among the ones in `scope`.
|
102
|
+
# @return [Arrary<Class>] the child classes in hierarchy order.
|
103
|
+
def descendants(parent_class: self, direct: false, scope: nil)
|
104
|
+
scope ||= ObjectSpace.each_object(::Class)
|
105
|
+
return [] if scope.empty?
|
106
|
+
scope.select do |klass|
|
107
|
+
klass < parent_class
|
108
|
+
end.sort do |k_1, k_2|
|
109
|
+
next -1 if k_2 < k_1
|
110
|
+
next 1 if k_1 < k_2
|
111
|
+
0
|
112
|
+
end.tap do |siblings|
|
113
|
+
if direct
|
114
|
+
siblings.reject! do |si|
|
115
|
+
siblings.any? {|s| si < s}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @param parent_class [Class] the parent class we want to find children of.
|
122
|
+
# @param direct [Boolean] it will only include direct child classes.
|
123
|
+
# @return [Boolean] `true` if the current class has child classes, and `false` otherwise.
|
124
|
+
def descendants?(parent_class: self, direct: false)
|
125
|
+
!descendants(parent_class: parent_class, direct: direct).empty?
|
126
|
+
end
|
127
|
+
|
128
|
+
# Keeps track on class instance variables that should be inherited by child classes.
|
129
|
+
# @note
|
130
|
+
# - subclasses will inherit the value as is at that moment
|
131
|
+
# - any change afterwards will be only on the specific class (in line with class instance variables)
|
132
|
+
# - adapted from https://stackoverflow.com/a/10729812/4352306
|
133
|
+
# TODO: this separates the logic of the method to the instance var. Think if would be possible to join them somehow.
|
134
|
+
def inheritable_class_vars(*vars)
|
135
|
+
@inheritable_class_vars ||= [:inheritable_class_vars]
|
136
|
+
@inheritable_class_vars += vars
|
137
|
+
end
|
138
|
+
|
139
|
+
# Builds the attr_reader and attr_writer of `attrs` and registers the associated instance variable as inheritable.
|
140
|
+
def inheritable_attrs(*attrs, add_accessors: false)
|
141
|
+
if add_accessors
|
142
|
+
attrs.each do |attr|
|
143
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
144
|
+
class << self; attr_accessor :#{attr} end
|
145
|
+
RUBY
|
146
|
+
end
|
147
|
+
end
|
148
|
+
inheritable_class_vars(*attrs)
|
149
|
+
end
|
150
|
+
|
151
|
+
# This callback method is called whenever a subclass of the current class is created.
|
152
|
+
# @note
|
153
|
+
# - values of the instance variables are copied as they are (no dups or clones)
|
154
|
+
# - the above means: avoid methods that change the state of the mutable object on it
|
155
|
+
# - mutating methods would reflect the changes on other classes as well
|
156
|
+
# - therefore, `freeze` will be called on the values that are inherited.
|
157
|
+
def inherited(subclass)
|
158
|
+
super.tap do
|
159
|
+
inheritable_class_vars.each do |var|
|
160
|
+
instance_var = instance_variable_name(var)
|
161
|
+
value = instance_variable_get(instance_var)
|
162
|
+
subclass.instance_variable_set(instance_var, value.freeze)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'base/class_helpers'
|
2
|
+
require_relative 'base/class_auto_loader'
|
3
|
+
require_relative 'rake_task'
|
4
|
+
require_relative 'options'
|
5
|
+
|
6
|
+
class RakeCommander
|
7
|
+
module Base
|
8
|
+
class << self
|
9
|
+
def included(base)
|
10
|
+
super(base)
|
11
|
+
base.extend RakeCommander::Base::ClassHelpers
|
12
|
+
base.extend RakeCommander::Base::ClassAutoLoader
|
13
|
+
base.autoloads_children_of RakeCommander
|
14
|
+
|
15
|
+
base.extend ClassMethods
|
16
|
+
base.send :include, RakeTask
|
17
|
+
|
18
|
+
base.send :include, Options
|
19
|
+
#autoload_namespace_ignore "RakeCommander::Samples"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def self_load
|
25
|
+
autoload_children
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|