rake-commander 0.1.2
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.
- 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
|